1. 组件间通信的六种方式
-
第一种:props
-
适用场景:父子组建通信
-
注意事项:
如果父组件给子组件传递的是「函数」:本质是子组件给父组件传递数据
如果父组件给子组件传递的是「非函数」:本质是父组件给子组件传递数据
-
书写方式:3种
-
第一种方式(只接收):
props:['name']
-
第二种方式(限制类型):
props:{name:String}
-
第三种方式(限制类型、限制必要性、指定默认值):
props:{ name:{ type:String, //类型 required:true, //必要性 default:'老王' //默认值 } }
-
-
小提示:路由的props书写形式:布尔值、对象、函数形式
-
-
第二种:自定义事件
- 适用场景:子组件给父组件传递数据
$on和$emit
-
第三种:全局事件总线
- 适用场景:万能
Vue.propotype.$bus = this
-
第四种:发布订阅pubsub-js(在React中使用比较多)
- 适用场景:万能
-
第五种: Vuex
- 适用场景:万能
-
第六种:插槽
- 适用场景:父子组件通信(标签)
- 默认插槽
- 具名插槽
- 作用域插槽
2. 自定义事件深入
-
事件分类
- 原生事件:鼠标事件、键盘事件等等
- 自定义事件
-
事件三要素
- 事件源
- 事件类型
- 事件回调
<!-- 1. 原生DOM绑定原生事件 --> <button @click="handler"></button> <!-- 2. 组件标签绑定原生事件(不起作用,因为默认当成自定义事件,需要添加.native修饰符)本质上是个子组件的根节点绑定事件——利用了事件的委派 --> <Event1 @click.native="handler1"></Event1> <!-- 3. 原生DOM绑定自定义事件(没有意义,无法触发$emit) --> <button @xxx="handler2"></button> <!-- 4. 组件标签绑定自定义事件 --> <Event2 @click="handler3" @xxx="handler3"></Event2> <!-- 并在Event组件中使用$emit触发事件 --> <button @click="$emit('click','自定义事件click')"></button> <button @click="$emit('xxx','自定义事件xxx')"></button>
3. v-model深入【组件通信方式的一种】
-
v-model是Vue框架中的指令,主要结合表单元素一起使用(文本框、单选、复选框等)
-
v-model实现原理:value与input事件实现的
-
需求1:用户在input输入框输入的数据在span中同步展示
<!-- 首先在data中配置 --> data() { return { message: "" } } <!-- 1. 通过v-model双向数据绑定实现 --> <input type="text" v-model="message"> <span>{{message}}</span> <!-- 2. 通过v-bind单项数据绑定和原生DOM事件oninput实现 oninput事件:当表单元素文本内容发生变化时会触发一次回调,与onchange不同的 是:不需要失去焦点即可触发 --> <input type="text" :value="message" @input="message = $event.target.value"> <span>{{message}}</span>
-
需求2:用户在子组件input输入框输入的数据在父组件的span中同步展示
一个组件上的
v-model
默认会利用名为value
的 prop 和名为input
的事件,但是像单选框、复选框等类型的输入控件可能会将value
attribute 用于不同的目的。model
选项可以用来避免这样的冲突<!-- 3. 深入学习v-model,实现父子组件数据同步(实现父子组件通信)--> <!-- 首先在父组件data中配置 --> data() { return { message: "" } } <!-- 方法一:利用props和自定义事件 组件标签中须要注意的两个问题: (1):value到底是什么?是父组件向子组件传递的props (2)@input到底是什么?是自定义事件 这里的$event不能更改否则无法接收参数 --> <CustomInput :value="message" @input="message = $event"/> <span>{{message}}</span> <!-- 方法二:在组件标签中使用v-model指令 --> <CustomInput v-model="message"/> <span>{{message}}</span> <!-- 在子组件中须要注意的两个问题: (1):value到底是什么?是v-bind绑定的动态属性,它的值为父组件传递过来的 message (2)@input到底是什么?是给原生DOM绑定的原生事件 --> <input type="text" :value="value" @input="$emit('input',$event.target.value)"> <!-- 并声明接收props --> props: ['value']
4. 属性修饰符sync【组件通信方式的一种】
-
需求:props的双向绑定,即可以在子组件中修改props并反馈到父组件中
-
注意使用.sync修饰符时不要忘了在子组件中声明接收props
-
:number.sync的含义
- 代表父组件给子组件传递props:[‘number’]
- 给当前子组件绑定了一个自定义事件:update:number=“number = $event”
<!-- 在父组件中:--> <!-- 方法一:不使用sync修饰符 --> <syncTest :number="number" @update:number="number = $event" ></syncTest> <span>{{number}}</span> <!-- 方法二:使用sync修饰符 --> <syncTest :number.sync="number" ></syncTest> <span>{{number}}</span> <!-- 配置number的值 --> data() { number: 100 } <!-- 在子组件中:--> <button @click="$emit('update:number',number-1)"> 点我number-1 </button> <span>{{number}}</span> <!-- 声明接收number --> props: ['number']
5. $attrs
和$listeners
- $attrs是子组件一个属性,可以用来获取父组件传递过来的props属性
-
例:在父组件中给子组件传递属性
<HintButton type="success" icon="el-icon-delete" size="mini" title="提示按钮" ></HintButton>
-
在子组件中通过
$attrs
获取传递过来的属性可以通过v-bind
绑定到元素上 -
注意:绑定的时候
v-bind
不能简写为:
<el-button v-bind:"$attrs"></el-button>
-
也可以单独绑定(比较麻烦)
<el-button :type="$attrs.type" :icon="$attrs.icon" :size="$attrs.size" ></el-button>
-
如果父组件传递过来的属性在子组件中已经使用props声明接收,则$attrs获取不到
props: ['title']
> 第一行为不使用props声明接收title属性,打印```this.$attrs```的结果
> 第二行为使用props声明接收title属性,打印```this.$attrs```的结果
$listeners
也是子组件的一个属性,可以获取到父组件传递给子组件的不含.native
修 饰符的自定义事件
-
在子组件中通过
$listeners
获取传递过来的自定义事件可以通过v-on
绑定到元素上 -
注意绑定的时候
v-on
不能简写为@
使用方法同
$attrs
6. $children
与$parent
$children
是组件实例的属性,可以获取到当前组件的所有直接子组件,如果有多个则返回「数组」
-
例:使用forEach()方法遍历并操作
this.$children.forEach(item => item.money -= 100)
-
注意:
$children
并不能保证顺序,切记不要这样书写this.$children[0] this.$children[1]
$refs也可以获取子组件,但每次只能获取一个,进行批量操作的时候比较麻烦
$parent
是组件实例是属性,可以获取到当前组件的父组件
-
例:操作父组件的money数据
this.$parent.money -= 100;