vue 组件数据交互
父组件向子组件传值
组件内部通过props接受传递过来的值
可以同时传递多个值,在props中添加多个值即可
Vue.component('menu-item',{
props: ['title'],
template: '<div>{{ title }}</div>'
})
父组件通过属性将值传递给子组件
//通过属性将值传递给子组件
<menu-item title="来自父组件的数据"></menu-item>
//通过v-bind将值传给子组件 <menu-item :title="title"></menu-item>
props属性名规则
- 在prop中使用驼峰形式,模板中需要使用短横线的形式
- 字符串形式的模板中没有这个限制
Vue.component('menu-item',{
//在JavaScript中是驼峰式的
props: ['title'],
template: '<div>{{ menuTitle }}</div>'
})
<!-- 在html中是短横线形式的 但是 -->
<menu-item menu-title="你好"><menu-item>
如果我们在使用时使用的是驼峰形式的
<menu-item menuTitle="你好"><menu-item>
虽然浏览器不会报错但是会给出以下警告

但是在字符串模板中使则用不会出现这种情况
props属性值类型
- 字符串String
- 数值number
- 布尔值Boolean
- 数组Array
- 对象Object
<div id="app">
<div>{{pmsg}}</div>
<menu-item :pstr='pstr' :pnum='12' :pboo='true' :parr='parr' :pobj='pobj'></menu-item>
</div>
Vue.component('menu-item', {
props: ['pstr','pnum','pboo','parr','pobj'],
template: `
<div>
<div>{{pstr}}</div>
<div>{{12 + pnum}}</div>
<div>{{pboo}}</div>
<ul>
<li :key='index' v-for='(item,index) in parr'>{{item}}</li>
</ul>
<span>{{pobj.name}}</span>
<span>{{pobj.age}}</span>
</div>
</div>
`
});
var vm = new Vue({
el: '#app',
data: {
pstr: 'hello',
parr: ['apple','orange','banana'],
pobj: {
name: 'lisi',
age: 12
}
}
});
通过props将值传递给子组件,最后运行的结果是

但是这里需要注意的是数值(Number)和布尔值(Boolean)类型的值,如果我们使用的不是v-bind传值,而是属性传值的话,我们可以通过typeof查看一下它传递过来值的类型。
<div id="app">
<div>{{pmsg}}</div>
<menu-item :pstr='pstr' pnum='12' pboo='true'></menu-item>
</div>
Vue.component('menu-item', {
props: ['pstr','pnum','pboo','parr','pobj'],
template: `
<div>
<div>{{pstr}}</div>
<div>{{typeof pnum}}</div>
<div>{{typeof pboo}}</div>
</div>
`
});
运行得到结果

我们可以看到最终得到的是string类型,所以在传值时我们还是使用v-bind进行传值
子组件向父组件传值
首先我们来看一个例子
<div id="app">
<menu-item :parr='parr'></menu-item>
</div>
Vue.component('menu-item', {
props: ['parr'],
template: `
<div>
<ul>
<li :key='index' v-for='(item,index) in parr'>{{item}}</li>
</ul>
<button @click='parr.push("d")'>点击</button>
</div>
`
});
var vm = new Vue({
el: '#app',
data: {
parr: ['a', 'b', 'c'],
}
});
看运行的结果:

当我们点击按钮之后可以看到页面的变化,同时我们通过控制台来查看data中parr的数据变化

可以看到页面和data中的数据都变化了,并且保持着一致,说明传值成功了,但是我们并不推荐这么做,因为porps 传递数据原则是单项数据流===>只允许父组件可以直接将值传递给子组件,不允许子组件直接操作父组件数据
那么我们如果向父组件传值呢?
1、子组件通过自定义事件向父组件传递信息
//自定义的事件必须通过$emit定义
<button @click='$emit("enlarge-text")'>扩大字体</button>
//携带参数的事件
<button @click='$emit("enlarge-text",0.5)'>扩大字体</button>
2、父组件监听子组件的事件
//监听无传递值的事件
<menu-item @enlarge-text='fontSize += 0.1'></menu-item>
//监听有传递值的事件 传递过来的值必须以$event表示
//如果组件函数是写在Vue组件中,也必须用$event表示接收的传递值
<menu-item @enlarge-text='fontSize += $event'></menu-item>
非父子组件间传值
1、单独的事件中心管理组件的通信

通过事件中心进行值的传递,需要单独new一个Vue实例作为事件中心
var eventHub = new Vue()
2、监听事件与销毁事件
eventHub.$on('add-todo',addTodo)
eventHub.$off('add-todo')
3、触发事件
eventHub.$emit('add-todo',id)
这里的id是你要传递的参数
我们通过一个实例来验证一下
<div id="app">
<div>父组件</div>
<div>
<button @click='handle'>销毁事件</button>
</div>
<test-a></test-a>
<test-b></test-b>
</div>
// 提供事件中心
var hub = new Vue();
Vue.component('test-a', {
data: function() {
return {
num: 0
}
},
template: `
<div>
<div>a:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function() {
hub.$emit('b-event', 2);
}
},
mounted: function() {
// 监听事件
hub.$on('a-event', (val) => {
this.num += val;
});
}
});
Vue.component('test-b', {
data: function() {
return {
num: 0
}
},
template: `
<div>
<div>b:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function() {
// 触发兄弟组件的事件
hub.$emit('a-event', 1);
}
},
mounted: function() {
// 监听事件
hub.$on('b-event', (val) => {
this.num += val;
});
}
});
var vm = new Vue({
el: '#app',
data: {
},
methods: {
handle: function() {
hub.$off('a-event');
hub.$off('b-event');
}
}
});
运行之后,当我们点击a按钮时,b的值会增加2,点击b按钮时,a的值会增加1,这里我们a按钮和b按钮都点击了3次


浙公网安备 33010602011771号