百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

vue3学习11、12、13组件化开发(vue组件化开发案例)

ztj100 2024-11-12 14:22 11 浏览 0 评论

利用vue脚手架创建一个项目

vue create component_demo

可以在vscode中安装Vue VSCode Snippets插件或vue3 snippets,帮助生成一些代码片段

vbase-css

可以快速生成vue3模板

组件通信

父子组件之间通信

  • 父组件传递给子组件:通过props属性
  • 子组件传递给父组件:通过$emit触发事件

在父组件中引入组件传值

<show-message :title="title"></show-message>

子组件中在props中定义

    props: {
      title: {
        type: String,
        require: true,   //表示这个属性是必传的
        default: '123'  //默认属性
      },
      //当属性是Object型时,默认值要为一个函数.因为多个组件会引用同一个对象
      info: {
        type: Object,
        default() {
          return {name: 'juju'}
        }
      },
      //自定义验证函数
      man: {
        validator(value) {
          //这个值必须匹配下列字符串中的一个
          return ['success', 'warning', 'danger'].include(value)
        }
      }
    }

props命名 建议父组件中要传递的值采用驼峰写法

<show-message :message-info="title"></show-message>
...


data() {
    return {
        messageInfo: 'damn'
    }
}

非props的Attribute

当我们传递给一个组件某个属性,但是该属性并没有定义对应的props或者emits,就称之为非props的Aaaribute

常见的包括css,style,id属性等 例如当给子组件设置一个class属性

<show-message class="liin" :title="title"></show-message>

当组件有单个根节点时,会自动添加到根节点的attribute

<template>
  <div class="liin">
    <h2>{{ title }}</h2>
    <h2>{{ info.name }}</h2>
  </div>
</template>

如果我们不希望根组件继承attribute,可以在子组件中设置inheritAttrs: false 我们可以通过$attrs来访问所有的非props的attribute

<h2 :class="$attrs.class">{{ title }}</h2>

通过v-bind绑定所有属性 父组件

<show-message id="xixi" class="liin" :title="title"></show-message>

子组件

<h2 v-bind="$attrs">{{ title }}</h2>

子组件传递给父组件 子组件中与vue2不同的是多了个emit参数,里面存放着可能要触发的事件

  export default {
    //emits属性,里面存放着待会会触发的事件
    emits: ["add", "sub"],
    //emits的对象写法,目的是为了进行参数的验证
    emits: {
      sub: null,
      add: (name, age) => {
        if(name == 'juju') {
          return true
        }
        return false
      }
    },
    methods: {
      increament() {
        this.$emit("add","juju",18)   //后面多个参数跟着的是要传的参数
      },
      decreament() {
        this.$emit("sub")
      },
    }
  }

父组件中写法与vue2相同

<counter-operation @add="addOne" @sub="subOne"></counter-operation>

非父组件的通信

  • provide/inject
  • mitt全局事件总线
  • vuex

provide和inject

无论层级结构有多深,父组件都可以作为其所有子组件的依赖提供者; 父组件有一个provide选项来提供数据,子组件有一个inject选项来使用这些数据

在父组件中添加一个provide

    components: {
      Home
    },
    provide: {
      name: 'juju',
      age: 18
    },

在子孙组件中注入

  export default {
    inject: ["name", "age"]
  }

当然,许多情况下数据都要从data中拿并从后台请求了,此时的provide要写成函数形式

    provide() {
      return {
        name: juju,
        age: 18,
        title: this.title
      }
    },

如果后续title改变的话,inject里的值并不是响应式的,可以使用vue中的computed函数


import {computed} from 'vue'

    provide() {
      return {
        name: juju,
        age: 18,
        title: computed(() => {
          this.title
        })
      }
    },

全局事件总线mitt库

安装mitt库

npm install mitt

创建一个eventbus.js文件

import mitt from 'mitt'

const emitter = mitt();

export default emitter;

// 也可以创建多个mitt对象

测试叔侄组件之间通信 在叔组件中传递

import emmiter from '../util/eventbus.js'

    methods: {
      btnClick() {
        emmiter.emit("handle", "juju",18);  //第一个参数方法名,后面跟着的是参数
      }
    }

在侄组件的生命周期中监听

    import emitter from '../util/eventbus.js'
    created() {
      emitter.on("handle", (name,age)=> {
        console.log(name)
      })
    }

mitt事件取消

emitter.all.clear();  //全部取消监听

function onFoo(){}
emitter.on('foo', onFoo)  //监听
emitter.off('foo', onFoo)  //取消监听

插槽slot

对于不同的区域可能存放不同的内容,因此要使用slot

  • 插槽的使用过程其实是抽取共性,预留不同
  • 我们会将共同的元素,内容依然在组件内进行封装
  • 同时将不同的元素使用slot作为占位,让外部决定到底显示什么样的元素

简单插槽的使用

定义一个子组件

    <h2>组件开始</h2>
    <slot></slot>
    
    <h2>组件结束</h2>

在父组件中使用

    <my-slot-cpn>
      <button>我是按钮</button>
    </my-slot-cpn>

此时中间部分可以展示按钮或者图片或者组件,vue会将内容替换到slot的位置

具名插槽的使用

插槽的默认使用 如果子组件是这样的

  <div>
    <h2>组件开始</h2>
    <slot>
      <i>我是默认内容</i>
    </slot>

    <h2>组件结束</h2>
  </div>

父组件

    <my-slot-cpn>
    </my-slot-cpn>

则显示默认内容

具名插槽

在子组件中编写有name属性的插槽

<template>
  <div class="nav-bar">
    <div class="left">
      <slot name="left"></slot>
    </div>
    <div class="center">
      <slot name="center"></slot>
    </div>
    <div class="right">
      <slot name="right"></slot>
    </div>
  </div>
</template>

在父组件中用template v-slot方式分配元素至对于的slot内

    <!-- 具名插槽的使用 -->
    <nar-bar>
      <template v-slot:left>
        <button>左边按钮</button>
      </template>
      //等价于
       <template #left>
        <button>左边按钮</button>
      </template>
      <template v-slot:center>
        <h2>我是标题</h2>
      </template>
      <template v-slot:right>
        <i>右边的元素</i>
      </template>
    </nar-bar>

效果

如果名字是不定的话,template应该这么写

      <template v-slot:[name]>
        <i>右边的元素</i>
      </template>

作用域插槽

即子组件中的slot属性,可以传给父组件 子组件

<template>
  <div>
    <template v-for="(item,index) in names" :key="item">
      <slot :item="item" :index="index"></slot>
    </template>
  </div>
</template>

父组件通过v-slot取得

  <show-names>
    <template v-slot="slotProps">
      <button>{{slotProps.item}}-{{ slotProps.index }}</button>
    </template>
  </show-names>
  //是下面的简写,v-slot后跟插槽名字
    <show-names>
    <template v-slot:default="slotProps">
      <button>{{slotProps.item}}-{{ slotProps.index }}</button>
    </template>
  </show-names>

当只有默认插槽时,可以使用独占默认插槽写法

    <show-names v-slot="slotProps">
      <button>{{slotProps.item}}-{{ slotProps.index }}</button>
  </show-names>

动态组件的实现

根据不同的场景,去渲染不同的组件。以前基本都使用v-if去判断从而渲染不同的组件。但是当组件很多的时候,组件会显得很臃肿。此时可以考虑采用动态组件去实现。

动态组件是使用component组件,通过特殊的attribute is来实现。 例如

<component is="hello-world"></component>

此时就会渲染HelloWorld组件

动态组件传递参数

<component is="hello-world" name="juju" :age="18" @helloClick="handleClick"></component>

此时在helloworld组件可以用props接收,同时动态组件可以接受子组件的点击事件

keep-alive

默认情况下,切换组件会被销毁,再次回来会重新创建组件。此时,在开发中某些情况我们希望继续保持组件的状态,而不是销毁掉,这时我们可以使用一个内置组件:keep-alive。

<keep-alive>
    <component is="hello-world" name="juju" :age="18" @helloClick="handleClick"></component>
<keep-alive>

keep-alive有一些属性,

  • include.[string|regexp|array]只有名称匹配的组件会被缓存。
  • exclude[string|regexp|array]任何匹配的组件都不会会被缓存。
  • max[number|string]最多可以缓存多少组件实例,一旦达到这个数字,那么缓存组件中最近没有被访问的实例会被销毁


include是根据组件的name属性来进行适配,因此有时需要给组件加上name属性

  export default {
    name: 'about',
   }

webpack分包

正常打包的话会将所有资源打包到一个app.js文件中,采用webpack分包方式会将利用分包的资源打包到一个chunk文件中,需要时再去加载,可以优化首屏渲染。

//通过import函数导如的模块,后续webpack对其进行打包的时候就会进行分包的操作
import('./utils/math').then(res => {console.log(sum(10,20))})

异步组件

同时vue3提供一个函数可以使打包后的组件成为一个单独的文件夹,加快首屏渲染速度 defineAsyncComponent接受两种类型的参数: 类型一:工厂函数,该工厂函数需要返回一个promise对象 类型二:接受一个对象类型,对异步函数进行配置

import {defineAsyncComponent} from 'vue'
const AsyncHello = defineAsyncComponent(() => import('./components/HelloWorld.vue'))

一般开发中使用路由懒加载比较多

获取元素和refs

在某些情况下,我们组件想要直接获取到元素对象或者子组件实例 在vue开发中我们不推荐dom操作的,这个时候,可以给元素或者组件绑定以恶搞ref的attribute属性

<h2 ref="title">哈哈哈哈哈哈</h2>


    mounted() {
      console.log(this.$refs.title)
    },

打印结果


对于组件来说,调用this.refs.xx可以获取组件实例,取得data中的数据或调用一些方法。 同时,可以在子组件中采用this.parent取得父组件实例以及parent取得父组件实例以及parent取得父组件实例以及root获取根组件

组件的生命周期

  • beforecreated
  • created
  • beforemounted
  • mounted
  • beforeUpdate
  • updated
  • beforeUnmount
  • unmounted

对于有缓存的组件来说,再次进入时,我们是不会执行created或者mounted等生命周期的,这时我们可以使用activated和deactiveated这两个生命周期钩子函数来监听。

组件的v-model

    //组件绑定v-model与下列的等价
    <hy-input v-model="title"></hy-input>
    <!-- <hy-input :modelValue="title" @update:model-value="title = $event"></hy-input> -->
<template>
  <div>
    <button @click="btnClick">input按钮</button>
    {{ modelValue }}
  </div>
</template>

<script>
  export default {
    props: {
      modelValue: String
    },
    emits: ["update:modelValue"],
    methods: {
      btnClick() {
        this.$emit("update:modelValue", '嘿嘿')
      }
    }
  }
</script>

$event为update:model-value事件传出来的参数

如果子组件中有input可以实现v-model绑定计算属性的操作,因为不能绑定到props里

    <input v-model="value" />
    
    ...
    computed: {
      value: {
        get(){
          return this.modelValue
        },
        set(value) {
          this.$emit("update:modelValue", value)
        }
      }
    },  

绑定多个v-model,后面加名字,此时why为子组件prop的值

<hy-input v-model="title" v-model:why="why"></hy-input>

相关推荐

Whoosh,纯python编写轻量级搜索工具

引言在许多应用程序中,搜索功能是至关重要的。Whoosh是一个纯Python编写的轻量级搜索引擎库,可以帮助我们快速构建搜索功能。无论是在网站、博客还是本地应用程序中,Whoosh都能提供高效的全文搜...

如何用Python实现二分搜索算法(python二分法查找代码)

如何用Python实现二分搜索算法二分搜索(BinarySearch)是一种高效的查找算法,适用于在有序数组中快速定位目标值。其核心思想是通过不断缩小搜索范围,每次将问题规模减半,时间复杂度为(O...

路径扫描 -- dirsearch(路径查找器怎么使用)

外表干净是尊重别人,内心干净是尊重自己,干净,在今天这个时代,应该是一种极高的赞美和珍贵。。。----网易云热评一、软件介绍Dirsearch是一种命令行工具,可以强制获取web服务器中的目录和文件...

78行Python代码帮你复现微信撤回消息!

来源:悟空智能科技本文约700字,建议阅读5分钟。本文基于python的微信开源库itchat,教你如何收集私聊撤回的信息。...

从零开始学习 Python!2《进阶知识》 Python进阶之路

欢迎来到Python学习的进阶篇章!如果你说已经掌握了基础语法,那么这篇就是你开启高手之路的大门。我们将一起探讨面向对象编程...

白帽黑客如何通过dirsearch脚本工具扫描和收集网站敏感文件

一、背景介绍...

Python之txt数据预定替换word预定义定位标记生成word报告(四)

续接Python之txt数据预定替换word预定义定位标记生成word报告(一)https://mp.toutiao.com/profile_v4/graphic/preview?pgc_id=748...

假期苦短,我用Python!这有个自动回复拜年信息的小程序

...

Python——字符串和正则表达式中的反斜杠(&#39;\&#39;)问题详解

在本篇文章里小编给大家整理的是关于Python字符串和正则表达式中的反斜杠('\')问题以及相关知识点,有需要的朋友们可以学习下。在Python普通字符串中在Python中,我们用'\'来转义某些普通...

Python re模块:正则表达式综合指南

Python...

Python中re模块详解(rem python)

在《...

python之re模块(python re模块sub)

re模块一.re模块的介绍1.什么是正则表达式"定义:正则表达式是一种对字符和特殊字符操作的一种逻辑公式,从特定的字符中,用正则表达字符来过滤的逻辑。(也是一种文本模式;)2、正则表达式可以帮助我们...

MySQL、PostgreSQL、SQL Server 数据库导入导出实操全解

在数字化时代,数据是关键资产,数据库的导入导出操作则是连接数据与应用场景的桥梁。以下是常见数据库导入导出的实用方法及代码,包含更多细节和特殊情况处理,助你应对各种实际场景。一、MySQL数据库...

Zabbix监控系统系列之六:监控 mysql

zabbix监控mysql1、监控规划在创建监控项之前要尽量考虑清楚要监控什么,怎么监控,监控数据如何存储,监控数据如何展现,如何处理报警等。要进行监控的系统规划需要对Zabbix很了解,这里只是...

mysql系列之一文详解Navicat工具的使用(二)

本章内容是系列内容的第二部分,主要介绍Navicat工具的使用。若查看第一部分请见:...

取消回复欢迎 发表评论: