WEB架构师学习笔记_Vue_01组件化常用技术

ps:本系列博客稍微偏向原理,若只想用法那官方文档最合适不过了。

知识导航:

  • 组件通信
  • 插槽
  • 总结

1. 组件通信

1.1 父到子

方式一:利用属性props
此方法的核心是props,那么先来简单介绍它。

props的作用接收父组件传递过来的数据。它有两种类型,即数组或对象,而对象是被允许做一些高级配置的,如规定prop的类型、指定初始值、设置为该prop是否必填、自定义验证函数。props它的大体实现思路:父组件提供数据,vuejs内部通过子组件的props对数据进行筛选,然后添加到子组件的上下文中。

父组件中:
 <Text01 text="测试:方式一01"></Text01>
Text01组件:
模板内:<h2>{{text}}</h2>
js内:props: ["text"],

方式二:引用refs

父组件:
模板内:<Text01 ref="text01Ref"></Text01>
js内:
 mounted(){
    this.$refs.text01Ref.text02="测试:方式一02",
  },
子组件:
模板内:<h2>{{text02}}</h2>
js内:此时的数据不是由props接收的了,可以收在data内。其实是把数据直接给到了此DOM节点上
data() {
    return {
      text02: "",
    };
  }

方式三:利用$childen

注意:$children 并不保证顺序,也不是响应式的

父组件:
模板内:<Text01></Text01>
js内: 
mounted(){
    this.$children[0].text03="测试:方式一03"
  },
子组件:
模板内: <h2>{{text03}}</h2>
js内:
data() {
    return {
      text03: ""
    };
  }

1.2 子到父

子到父一般均采用自定义事件的方式,这里有一个方法就显得什么重要了,即$emit。
$emit的功能是触发当前实例上的事件,然后把后面的参数给监听器的回调。

当然这是官方文档的解释,什么意思?
参照vue的源码简单解释一下:事实上所有的事件监听器的回调函数都会被保存在vm._events中,它的大致格式为{事件名:回调处理函数}。但 $emit触发时,会根据 $emit的第一个属性即事件的名称去查找对应的键值对。找到了则执行它的回调。下面兄弟组件传参我会写一个简单的例子实现。

先看这里子到父的代码:

子组件:
模板内: <h2 @click="$emit('text04','子到父')">触发</h2>
父组件:
模板内<Text01 @text04=handle($event)></Text01>
js内
  methods: {
    handle(e){
      console.log(e);
    }
  },

通过这个栗子也可以走一下思路,父组件监听着一个叫做text04的事件。这个东西内会以{text04,fn}这样的格式保存在一个变量中。子组件中$emit的作用是 1先去那个变量中找键叫做text04的键值对,找的了,2 把它的回调处理函数fn哪里把自己参数搞进去即fn(‘子到父’)。fn即handle(e{console.log(e);}。
至于父组件为毛能监听到子组件中的事件我没有去研究vue这块是怎么处理的,我把它当成事件冒泡来理解的

1.3 兄弟

1.3.1 如两兄弟有共同父辈组件

介绍一个通常与$emit配对使用的 $on
$on是监听当前实例上的自定义事件,事件可以是由 e m i t 使 v m . emit触发的。它的使用 `vm. on(event,cb)` 其实还是和上面是差不多的。它的主要目的仍然是将{事件名:fn}保存起来以供$emit使用。cb回调就是事件的处理函数。
在这里即拿共有祖辈组件派发事件,共有祖辈在监听事件。干活的组件始终是一个组件而已,就是我自己触发了一个事件我自己再收回来

子组件1<template>
  <div @click="$parent.$emit('text04','兄弟传参')">
  子组件1
  </div>
</template>


组件2<template>
  <div>
   <h2>{{text02}}</h2>
  </div>
</template>
<script>
export default {
  name:'Text02',
  data() {
    return {
      text02: ""
    };
  },
  created() {
    this.$parent.$on("text04", msg => {
      this.text02 = msg;
    });
};
</script>


<script>

export default {
  }
};
</script>

1.3.2 无关系的两个兄弟

首先可以实现一个类,用于事件派发和事件监听。即实现$emit和 $on.

class Bus {
    constructor() {   
        this.callbacks = {}
        //即由于存放{事件名:处理函数}这种格式的对象结构
    }
    $on(name, fn) {
        this.callbacks[name] = fn;
    }
    $emit(name, args) {
        if (this.callbacks[name]) {
            this.callbacks[name](args);
        }
    }
}
//将这个类的实例挂到vue的原型上
Vue.prototype.$bus = new Bus()



组件1<h2 @click="$bus.$emit('text05','兄弟传参之总线模式')">组件1</h2>
组件2:
模板内 <h2>{{text02}}</h2>
js内:
<script>
export default {
  name:'Text02',
  props: ["text"],
  data() {
    return {
      text02: ""
    };
  },
  created() {
    
    this.$bus.$on('text05',msg=>{
      console.log(msg);  
      this.text02=msg 
    })
  }
};
</script>

1.4 隔代

隔代则又用到了两个东西:

  1. provide
  2. inject
    它们一般也是配套使用,主要用于插件和组件库的开发。它允许一个祖先组件向其所有的子孙后代中注入依赖,且无论组件层次有多深

栗子:

祖先组件:
js内添加一个provide选项,provide选项可以是一个对象,也可以是一个返对象的函数
provide(){
    return{
      a:"祖孙之间"
    }
  },
子孙组件:
js内添加一个inject选项,该选项可以是一个字符串数组或对象
 inject:['a'],

2. 插槽

插槽相对比较简单即预留位置

2.1 匿名插槽

// Text01组件
<div>
<slot></slot>
</div>
// 父组件
<Text01>hello</Text01>

2.2 具名插槽

即位置要进行匹配了。

// Text01组件
<div>
<slot></slot>
<slot name="content"></slot>
</div>
//父组件
<Text01>
<template v-slot:content>内容</template>
</Text01>

2.3 作用域插槽

有时候让插槽内容能够访问子组件中的数据是很有必要的。换句话说我们希望在父组件中应用该插槽时能够获取去子组件中的信息。

Text03组件:
<slot :foo="foo"></slot>
js内
 data() {
    return {
      foo:'text03组件中的内容'
    };
  },
父组件:
	<Text03>
       <!-- 把v-slot的值指定为作用域上下文对象 -->
        <template v-slot:default="ctx">
          来自子组件数据:{{ctx.foo}}
          </template>
      </Text03>

3 总结

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41086511/article/details/105924411
今日推荐