一、自定义事件
组件间的通信方式——自定义事件可以实现父子组件之间的双向数据绑定。
自定义事件分为触发和监听两部分。
(1)监听事件:通过v-on绑定,@
在父组件中给子组件绑定监听事件getMsg()
<template>
<div id="app">
{{ msg }}
<HelloWorld :msg="msg" @getMsg="handleGetMsg" />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: { HelloWorld },
data() {
return {
msg: "",
};
},
methods: {
handleGetMsg(val) {
this.msg = val;
},
},
};
</script>
(2)触发事件:子组件中绑定触发事件$emit(eventName,data)
<template>
<div>
<p>------------以下是子组件---------</p>
<button @click="getClick">点我一下</button>
{{ msg }}
</div>
</template>
<script>
export default {
props: {
msg: String,
},
data() {
return {
data: "111",
};
},
methods: {
getClick() {
this.$emit("getMsg", this.data);
},
},
};
</script>
(3)总结:
父组件个子组件传递数据通过props传递
子组件给父组件传递数据通过
e
m
i
t
(
)
传
递
通
过
p
r
o
p
s
和
emit()传递 通过props和
emit()传递通过props和emit()可以实现父子组件之间数据的双向绑定。
二、组件间的v-model
v-model不光可以实现表单输入之间的双向绑定,还可以实现组件之间的数据绑定。
<HelloWorld v-model="msg"></HelloWorld>
本质上是这种写法:
<HelloWorld :value="msg" @input="msg = $event"></HelloWorld>
有value这个prop和input事件传入HelloWorld组件。
(1)子组件HelloWorld的value需要绑定一个从父组件传过来的值,通过子组件的props接收。
(2)若在子组件中有新值会改变时,需要触发父组件的input事件,并将新的值作为参数传递给父组件,本质的改变的value的值。
详细步骤:
- 当有数据改变时,触发了input事件
- 触发父组件的input事件后并将值传递给了父组件
- 父组件监听到了input事件的改变,并拿到了传递的值,从而将值赋值给变量msg,到此,实现了子组件value值到父组件msg的单向绑定。
- 父组件将更新后的msg重新绑定到value
- 将父组件的value值通过props传递给子组件,实现了父组件的msg到子组件的value的单项绑定。
注意:
6. v-bind只能实现单向绑定
7. v-model(v-bind+触发的input事件)实现双向绑定。
三、.sync
在组件上使用v-model只能实现单个数据的双向绑定,当有多个数据时,就可以考虑.sync了。
vue提供了.sync修饰符,说白了就是一种简写的方法,开发中,我们会遇到父子组件双向绑定的问题,但是考虑到组件的可维护性,vue中是不允许子组件改变父组件传入的props值的。
父组件通过绑定属性的方式向子组件传值,而在子组件可以通过$emit向父组件通信,通过这种间接的方式改变父组件的data,从而间接实现子组件改变props的值。
子组件使用$emit向父组件发送事件:
父组件监听了这个事件并更新一个本地的数据
事件名称固定写法:updata:XXX
<HelloWorld :title="msg" @update:title="msg = $event"></HelloWorld>
为了方便写法,为这种模式提供了一个缩写,即.sync修饰符:
<HelloWorld :title.sync="msg"></HelloWorld>