vue 组件传值(一)$attrs,$listeners
$attrs:包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
$listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="../node_modules/vue/dist/vue.min.js"></script>
<title>父子传值</title>
</head>
<body>
<div id="app"></div>
<script>
Vue.component('C',{
data(){
return {
msg : 'CCCCCCCC',
cdata : '哈哈哈哈'
}
},
methods : {
changedata(val){
this.$emit('test2',val);
this.$emit('btest',val);
}
},
template : `<div class="C">
<p>C组件:{{$attrs.app_data_c}}-{{$attrs}}</p>
输入:<input v-bind="$attrs" v-on="$listeners" @click="changedata(msg)" v-model="msg"></input>
<div>`,
created(){
console.log('C组件的$listeners:');
console.log(this.$listeners); // 包含父级所有绑定的方法
}
});
Vue.component('B',{
data(){
return {
message_child : '我是子组件的值'
}
},
template : `<div class="B">
<p>B组件:{{$attrs.app_data_b}}-{{$attrs}}</p>
<C v-bind="$attrs" v-on="$listeners" ></C>
<div>`,
created(){
console.log('B组件的$listeners:');
console.log(this.$listeners); // 包含父级所有绑定的方法
}
});
Vue.component('A',{
data(){
return {
a : 'A的数据a',
b : 'A的数据b'
}
},
methods : {
changedata(val){
console.log('触发了btest事件'+val)
}
},
// 包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。
// 当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class和 style 除外),
// 并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
// $listener:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。
// 它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
template : `<div class="A">
<p>A组件:{{$attrs.app_data_a}}-{{$attrs}}</p>
<B v-bind="$attrs" v-on="$listeners" :A_data_a="a" :A_data_b="b" @btest="changedata"></B>
<div>` ,
created(){
console.log('A组件的$listeners:');
console.log(this.$listeners); // 包含父级所有绑定的方法
}
});
Vue.component('Parent',{
data(){
return {
message_parent : '我是Parent组件的数据'
}
},
props : ['app_data_a'],
template : `<div class="parent">
<p>Parent组件:{{$attrs.app_data_a}}-{{$attrs}}</p>
<A v-bind="$attrs" v-on="$listeners"></A>
<div>`,
created(){
console.log('Parent组件的$listeners:');
console.log(this.$listeners); // 包含父级所有绑定的方法
}
});
var App = {
data(){
return {
a : '数据a',
b : '数据b',
c : '数据c',
message_app : '我是App组件的数据'
}
},
methods : {
changedata_a(val){
},
changedata_b(val){
this.b = val
},
changedata_c(val){
}
},
template : `<div>
App中:
<span>a:{{a}}</span>
<span>b:{{b}}</span>
<span>c:{{c}}</span>
<Parent :app_data_a="a" :app_data_b="b" :app_data_c="c" @test1="changedata_a" @test2="changedata_b" @test3="changedata_c">
</Parent>
</div>`
};
new Vue({
el : '#app',
components : {
App
},
template : '<App></App>'
});
</script>
</body>
</html>
为了便于理解,我画了个图:
注意
运行截图
总结
该传值方法适合直接嵌套多层的组件之间传值,$attrs用于父向子传值,$listeners用于通过触发父组件事件和传值来实现从子向父传值。