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"
参考
更多推荐



所有评论(0)