传值方式有:props和“$emit”、“$attrs”和“$listeners”、中央事件总线、v-model、provide和inject、“$parent”和“$children”、vuex、localStorage/session。

本教程操作环境:windows7系统、vue2.9.6版,DELL G3电脑。
对于vue来说,组件之间的消息传递是非常重要的,下面是我对组件之间消息传递的常用方式的总结。
props和$emit(常用)
$attrs和$listeners
中央事件总线(非父子组件间通信)
v-model
provide和inject
$parent和$children
vuex
props和$emit
父组件向子组件传递数据是通过prop传递的,子组件传递数据给父组件是通过$emit触发事件来做到的.
1 | Vue.component('child',{ data(){ return { mymessage:this.message } }, template:` <div> <input type= "text" v-model= "mymessage" @input= "passData(mymessage)" > </div> `, props:['message'],
|
登录后复制
在上面的例子中,有父组件parent和子组件child。
父组件传递了message数据给子组件,并且通过v-on绑定了一个getChildData事件来监听子组件的触发事件;
子组件通过props得到相关的message数据,最后通过this.$emit触发了getChildData事件
$attrs和$listeners
第一种方式处理父子组件之间的数据传输有一个问题:如果父组件A下面有子组件B,组件B下面有组件C,这时如果组件A想传递数据给组件C怎么办呢? 如果采用第一种方法,我们必须让组件A通过prop传递消息给组件B,组件B在通过prop传递消息给组件C;要是组件A和组件C之间有更多的组件,那采用这种方式就很复杂了。Vue 2.4开始提供了$attrs和$listeners来解决这个问题,能够让组件A之间传递消息给组件C。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | Vue.component('C',{
template:`
<div>
<input type= "text" v-model= "$attrs.messagec" @input= "passCData($attrs.messagec)" > </div>
`,
methods:{
passCData(val){
this. $emit ('getCData',val)
}
}
})
Vue.component('B',{
data(){
return {
mymessage:this.message
}
},
template:`
<div>
<input type= "text" v-model= "mymessage" @input= "passData(mymessage)" >
<!-- C组件中能直接触发getCData的原因在于 B组件调用C组件时 使用 v-on 绑定了 $listeners 属性 -->
<!-- 通过v-bind 绑定 $attrs 属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
<C v-bind= "$attrs" v-on= "$listeners" ></C>
</div>
`,
props:['message'],
methods:{
passData(val){
this. $emit ('getChildData',val)
}
}
})
Vue.component('A',{
template:`
<div>
<p>this is parent compoent!</p>
<B :messagec= "messagec" :message= "message" v-on:getCData= "getCData" v-on:getChildData= "getChildData(message)" ></B>
</div>
`,
data(){
return {
message:'hello',
messagec:'hello c'
}
},
methods:{
getChildData(val){
console.log('这是来自B组件的数据')
},
getCData(val){
console.log( "这是来自C组件的数据:" +val)
}
}
})
|
登录后复制
中央事件总线
上面两种方式处理的都是父子组件之间的数据传递,而如果两个组件不是父子关系呢?这种情况下可以使用中央事件总线的方式。新建一个Vue事件bus对象,然后通过bus.$emit触发事件,bus.$on监听触发的事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | Vue.component('brother1',{
data(){ return {
mymessage:'hello brother1'
}
},
template:` <p>
<p>this is brother1 compoent!</p>
<input type= "text" v-model= "mymessage" @input= "passData(mymessage)" >
</p> `,
methods:{
passData(val){
bus. $emit ('globalEvent',val)
}
}
})
Vue.component('brother2',{
template:` <p>
<p>this is brother2 compoent!</p>
<p>brother1传递过来的数据:{{brothermessage}}</p>
</p> `,
data(){ return {
mymessage:'hello brother2',
brothermessage:''
}
},
mounted(){
bus. $on ('globalEvent',(val)=>{ this.brothermessage=val;
})
}
})
var bus= new Vue(); var app= new Vue({
el:'#app',
template:` <p>
<brother1></brother1>
<brother2></brother2>
</p> `
})
|
登录后复制
provide和inject
在 Vue.js 的 2.2.0+
版本中添加加了 provide 和 inject 选项。他们成对出现,用于父级组件向下传递数据。
父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Vue.component('child',{
inject:[' for '],
data(){
return {
mymessage:this. for
}
},
template:`})
Vue.component('parent',{
template:`this is parent compoent!`,
provide:{
for :'test'
},
data(){
return {
message:'hello'
}
}
})
|
登录后复制
v-model
父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(‘input',val)自动修改v-model绑定的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | Vue.component('child',{
props:{
value:String,
data(){ return {
mymessage:this.value
}
},
methods:{
changeValue(){ this. $emit ('input',this.mymessage);
},
template:` <p>
<input type= "text" v-model= "mymessage" @change= "changeValue" >
</p> })
Vue.component('parent',{
template:` <p>
<p>this is parent compoent!</p>
<p>{{message}}</p>
<child v-model= "message" ></child>
</p> `,
data(){ return {
message:'hello'
}
}
}) var app= new Vue({
el:'#app',
template:` <p>
<parent></parent>
</p> `
})
|
登录后复制
$parent和$children
在组件内部可以直接通过子组件$parent对父组件进行操作,父组件通过$children对子组件进行操作.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | Vue.component('child',{
props:{
value:String,
data(){ return {
mymessage:this.value
}
},
methods:{
changeValue(){ this. $parent .message = this.mymessage;
},
template:` <p>
<input type= "text" v-model= "mymessage" @change= "changeValue" >
</p> })
Vue.component('parent',{
template:` <p>
<p>this is parent compoent!</p>
<button @click= "changeChildValue" >test</button >
<child></child>
</p> `,
methods:{
changeChildValue(){ this. $children [0].mymessage = 'hello';
}
},
data(){ return {
message:'hello'
}
}
}) var app= new Vue({
el:'#app',
template:` <p>
<parent></parent>
</p> `
})
|
登录后复制
vuex处理组件之间的数据交互
如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。
localStorage / sessionStorage
这种通信比较简单,缺点是数据和状态比较混乱,不太容易维护。
通过window.localStorage.getItem(key)
获取数据
通过window.localStorage.setItem(key,value)
存储数据
注意用JSON.parse() / JSON.stringify() 做数据格式转换
localStorage / sessionStorage可以结合vuex,实现数据的持久保存,同时使用vuex解决数据和状态混乱问题。
【相关推荐:《vue.js教程》】
以上是vue传值有哪8种方法的详细内容。更多信息请关注PHP中文网其他相关文章!