vue2 透传
vue2透传,属性透传 v-bind=“$attrs”;事件透传 v-on=“$listeners”
·
一、什么是透传
透传是一个通讯层面的概念,指的是在通讯中不管传输的业务内容如何,只负责将传输的内容由源地址传输到目的地址,而不对业务数据内容做任何改变。
在vue2上来讲,我们的组件存在深层嵌套的场景,例如:
A -> B -> C
我们会在A
里带上业务中提供的数据,一层层的传递进去,在传递的过程中一般有两种方案:
- 通过
props
具名接收,再继续
向内层
传递 - 通过
$listeners
和$attrs
变量配合v-on
和v-bind
进行批量透传
二、属性透传:v-bind="$attrs"
& 事件透传:v-on="$listeners"
<template>
<div>
<p @click="click()">CT</p>
<p>{{ a }} - {{ c }}</p>
</div>
</template>
<script>
export default {
name: "CT",
props: {
a: {
type: String,
default: "",
},
c: {
type: String,
default: "",
},
},
data() {
return {};
},
methods: {
click() {
this.$emit("click");
},
},
};
</script>
<template>
<div>
<p>BT</p>
<CT v-bind="$attrs" v-on="$listeners"></CT>
</div>
</template>
<script>
import CT from "./CT.vue";
export default {
name: "BT",
components: { CT },
data() {
return {};
},
methods: {
click() {
this.$emit("click");
},
},
};
</script>
<template>
<div>
<p>AT</p>
<BT a="b" c="t" @click="click()"></BT>
</div>
</template>
<script>
import BT from "./BT.vue";
export default {
name: "AT",
components: { BT },
data() {
return {};
},
methods: {
click() {
console.log("AT");
},
},
};
</script>
A -> B -> C
v-bind="$attrs"
会将A组件
调用B组件
时绑定的属性
全部透传
给C组件
v-on="$listeners"
会将A组件
调用B组件
时绑定的事件
全部透传
给C组件
通过这样的方式
A组件
就可将想要
传递给C组件
的属性
和事件
传递下去了。
三、属性覆盖
<template>
<div>
<p @click="click()">CT</p>
<p>{{ a }} - {{ c }}</p>
</div>
</template>
<script>
export default {
name: "CT",
props: {
a: {
type: String,
default: "",
},
c: {
type: String,
default: "",
},
},
data() {
return {};
},
methods: {
click() {
this.$emit("click");
},
},
};
</script>
<template>
<div>
<p>BT</p>
<CT c="cc" v-bind="$attrs" v-on="$listeners" a="aa"></CT>
</div>
</template>
<script>
import CT from "./CT.vue";
export default {
name: "BT",
components: { CT },
data() {
return {};
},
methods: {
click() {
this.$emit("click");
},
},
};
</script>
结果:
AT
BT
CT
aa - cc
不管属性的位置在
v-bind前
还是在v-bind后
,具名属性
会都会覆盖
v-bind
里绑定的同名
属性。
四、事件合并
<template>
<div>
<p @click="click()">CT</p>
<p>{{ a }} - {{ c }}</p>
</div>
</template>
<script>
export default {
name: "CT",
props: {
a: {
type: String,
default: "",
},
c: {
type: String,
default: "",
},
},
data() {
return {};
},
methods: {
click() {
this.$emit("click");
},
},
};
</script>
<template>
<div>
<p>BT</p>
<CT c="cc" v-bind="$attrs" v-on="$listeners" a="aa" @click="clickBT()"></CT>
</div>
</template>
<script>
import CT from "./CT.vue";
export default {
name: "BT",
components: { CT },
data() {
return {};
},
methods: {
click() {
this.$emit("click");
},
clickBT() {
console.log("clickBT")
}
},
};
</script>
点击CT
时console
控制台输出
:
clickBT BT.vue?ec36:22
AT AT.vue?b678:19
同名事件
会合并
在一起,都会被执行
,先执行具名方法
,再执行v-on
里面绑定的同名方法
。
五、如何覆盖事件,而不做合并
<template>
<div>
<p @click="click()">CT</p>
<p>{{ a }} - {{ c }}</p>
</div>
</template>
<script>
export default {
name: "CT",
props: {
a: {
type: String,
default: "",
},
c: {
type: String,
default: "",
},
},
data() {
return {};
},
methods: {
click() {
this.$emit("click");
},
},
};
</script>
<template>
<div>
<p>BT</p>
<CT c="cc" v-bind="$attrs" v-on="{...$listeners, click: clickBT}" a="aa"></CT>
</div>
</template>
<script>
import CT from "./CT.vue";
export default {
name: "BT",
components: { CT },
data() {
return {};
},
methods: {
click() {
this.$emit("click");
},
clickBT() {
console.log("clickBT")
}
},
};
</script>
点击CT
时console
控制台输出
:
clickBT BT.vue?ec36:22
AT AT.vue?b678:19
使用扩展运算符
可以做到覆盖事件
,而不做合并
。
六、v-bind="$attrs"
& v-on="$listeners"
不是绝对的
$attrs
是一个vue的内置变量
,指的是调用本组件时上面绑定的属性
;$listeners
同样是一个vue的内置变量
,指的是调用本组件时上面绑定的事件
。
v-bind
后面不一定必须是$attrs
,v-on
后面不一定必须是$listeners
。你可以像这样:
v-bind="$props"
、 v-bind="xxx"
、 v-bind="{a: 1, b: 2}"
、v-listeners="xxx"
参考
更多推荐
已为社区贡献4条内容
所有评论(0)