vue中的数据传递一般是单向数据流,即父组件数据通过props传递给子组件。但是子组件可以通过自定义事件间接修改父组件中的数据,这种方式采用了发布订阅模式。
举个例子:
<div id="app">
父组件中的的num是{{ num }}<br/>
<son @addnum="add">son>
div>
<template id="son">
<button @click="changeNum">改变父组件中的numbutton>
template>
<script src="./node_modules/vue/dist/vue.js">script>
<script>
let son = {
template: '#son',
methods: {
changeNum() {
// 子组件通过$emit方式触发传递给子组件的自定义事件来改变父组件中的数据
this.$emit('addnum', 1)
},
},
};
let vm = new Vue({
el: '#app',
data: {
num: 1,
},
components: {
son,
},
methods: {
add(val) {
this.num += val;
},
},
});
script>
注意:
这里的自定义事件名称addnum必须要使用小写方式,不能用驼峰方式。不同于组件和 prop,事件名不会被用作一个 JavaScript 变量名或 property 名,所以就没有理由使用 camelCase 或 PascalCase 了。并且 v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent——导致 myEvent 不可能被监听到。
因此,我们推荐你始终使用 kebab-case 的事件名。
由于子组件也能修改父组件中的数据,上面引申内容已经实现。在父组件和子组件两侧都没有明显的变更数据来源,所以此时我们可以通过update:myPropName
的模式触发事件取而代之。
举个例子:
<div id="app">
父组件中的的num是{{ num }}<br/>
<son :num="num" @update:addnum="num = $event">son>
div>
<template id="son">
<button @click="changeNum">改变父组件中的numbutton>
template>
<script src="./node_modules/vue/dist/vue.js">script>
<script>
let son = {
template: '#son',
props: ['num'],
methods: {
changeNum() {
// 子组件通过$emit方式触发传递给子组件的自定义事件来改变父组件中的数据
this.$emit('update:addnum', this.num + 1);
},
},
};
let vm = new Vue({
el: '#app',
data: {
num: 1,
},
components: {
son,
},
});
script>
或者上面这个例子可以改写成下面这样:
<div id="app">
父组件中的的num是{{ num }}<br/>
<son @update:addnum="add">son>
div>
<template id="son">
<button @click="changeNum">改变父组件中的numbutton>
template>
<script src="./node_modules/vue/dist/vue.js">script>
<script>
let son = {
template: '#son',
methods: {
changeNum() {
// 子组件通过$emit方式触发传递给子组件的自定义事件来改变父组件中的数据
this.$emit('update:addnum', 1);
},
},
};
let vm = new Vue({
el: '#app',
data: {
num: 1,
},
components: {
son,
},
methods: {
add(val) {
this.num += val;
},
},
});
script>
.sync修饰符是@update:自定义属性名
的语法糖
举个例子:
<div id="app">
父组件中的的num是{{ num }}<br/>
<son :num="num" :addnum.sync="num">son>
div>
<template id="son">
<button @click="changeNum">改变父组件中的numbutton>
template>
<script src="./node_modules/vue/dist/vue.js">script>
<script>
let son = {
template: '#son',
props: ['num'],
methods: {
changeNum() {
// 子组件通过$emit方式触发传递给子组件的自定义事件来改变父组件中的数据
this.$emit('update:addnum', this.num + 1);
},
},
};
let vm = new Vue({
el: '#app',
data: {
num: 1,
},
components: {
son,
},
});
script>