Vue组件

基本使用

通过 Vue.extend 来创建组件构造器对象

const cpnC = Vue.extend({
  template:`<div>
             <h2>hhhhh</h2>
             <p>xxxxxx</p>
            </div> `      
});

全局注册组件

Vue.component('my-cpn',cpnC);

局部注册组件,在对应的vue实例中去注册即可

  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!'
    },
    components:{
      cpn:cpnC
    }
  });

全局注册语法糖

Vue.component('cpn',{
  template:`
     <div>
       <h2>我是哈哈ha</h2>
       <p>我是内容</p>
     </div>
  `
});

局部注册语法糖

  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!'
    },
    components:{
          'cpn2':{
            template:`
             <div>
              <h2>我是哈哈ha</h2>
              <p>我是内容hhhh</p>
             </div>
             `
           }
          }
  });

组件通信

1. 父传子

通过props方式

2. 子传父

通过$emit方式

组件访问

1. 父访问子

$children

父组件调用$children会获取一个包含所有子组件的数组,可以通过该方式获取子组件的一些方法与属性

$refs

对象类型,默认是一个空对象。当有组件标签上加上了ref="xxx",这时这个对象才会返回这个组件的一些属性,可以用来操作一些DOM行为

2. 子访问父

通过$parent 方式

provide/inject

如果我们需要跨层级传递,上述介绍的方式使用起来就会很繁琐而且维护性不高

image-20210627165637124

如上图,我们需要通过A组件为最底层各个组件传递属性或者方法就可以采用 provide/inject方式

A组件:

provide() {
     return {
       theme: {
         //这里设置的color不是响应式的,
         color: this.color
       }
     };
   },
//下面就能实现响应式(提供了响应式的数据)
provide() {
    return {
      theme: this
    };
  },

如果实在不想把整个实例查传过去,可以使用Vue.observable 它能将对象变成响应式

  provide() {
    //另类实现响应式 
    this.theme = Vue.observable({
      color: "blue"
    });
    return {
      theme: this.theme
    };
  },

vue3推出的新api computed也可以实现响应式

//需要从vue中引入一个函数
import { computed } from "vue"

provide() {
    return {
        theme:computed(() => this.color)
    }
}

后代组件通过inject获取 theme对象

inject: {
    theme: {
      default: () => ({})
    }
  },

函数式组件(没有上下文对象)获取inject方式

<template functional>
  <div class="border2">
    <!-- 函数式组件取得inject的方式,因为没有上下文 -->
    <h3 :style="{ color: injections.theme.color }">I 结点</h3>
  </div>
</template>
<script>
export default {
  inject: {
    theme: {
      default: () => ({})
    }
  }
};
</script>

通过computed处理过的数据在子组件中的访问方式与其他的不同,因为computed返回的是一个ref对象,需要通过 .value方式去取数据

注意,inject的方式是类似与冒泡的方式去查找父级的provide 以最近的为准

事件总线

vue3移除掉了$on $off $once 等方法,这里使用一个第三方库 mitt来实现

下载

npm install mitt -S

使用方式:
创建一个文件夹 eventBus.js

//导入
import mitt from 'mitt'
//创建一个emitter对象
const emitter = mitt();
export default emitter;

例如 A B组件互为兄弟组件,A想向B组件发送一些数据

A组件

import emitter from "@/eventBus.js"
//发出一个自定义事件
emitter.emit('zhang', {name:'san', age:'18'});

B组件

import emitter from "@/eventBus.js"
//监听事件
emitter.on('zhang', (info) => {
    console.log(info)
})
//监听所有事件,这里参数有两个,一个是事件类型,一个是数据
emitter.on('*', (type, info) => {
    console.log(info)
})

事件的取消

//取消所有事件监听
emitter.all.clear();

//取消特定的事件
//我们这里监听事件就要传入一个函数的引用了
function fn() {}
emitter.on('zhang', fn);//监听
emitter.off('zhang', fn);//取消

动态组件

有时候我们需要在一个页面切换不同的组件,我们可以使用 v-if来条件渲染,也可以使用路由来进行切换,当然还可以使用 动态路由来实现
动态路由使用vue内置组件component 通过一个属性 is 来实现

<component
        :is="currentTab"
        @pageClick="pageClick"
        name="zhangsan"
        :age="20"
 ></component>

is 填写组件的内容可以为component函数注册的组件,也可以是在一个组件对象的components对象中注册的组件。

对于组件间传值和自定义事件也是和普通组件一样没有变化

另外,如果我们在切换组件的时候想要将组件的状态缓存,可以使用内置组件 keep-alive

<keep-alive>
      <component
        :is="currentTab"
        @pageClick="pageClick"
        name="zhangsan"
        :age="20"
      ></component>
 </keep-alive>

包裹在外层即可

keep-alive 属性

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

includeexclude 都可以使用逗号分隔字符串,匹配首先检查组件自身的name属性

Last modification:July 20, 2021
如果觉得我的文章对你有用,请随意赞赏