一、组件透传
“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute(变量,等同于property) 或者 v-on
事件监听器。
二、往后代组件传值、后代组件想修改传的数据
(父组件:App。子组件:box。孙组件:son)
父组件使用子组件时传递了数据,子组件也想将这个数据传给自己的子组件使用就需要在props中声明属性,再将这个属性值传给自己的子组件(孙组件),孙组件中又在props中声明属性,才能使用父组件的父组件传的数据。如果要修改数据就要触发事件(this.$emit),传递自己想修改后的值,告诉父组件想要修改数据,然后这个父组件就也要做相同的工作去告诉自己的父组件,让父组件去修改数据。
但这时候如果中间组件的层数多了,且传的值也有好多个,那中间的组件每一个都要声明属性,且有多少个属性就要声明多少个,就显得非常麻烦,而且如果中间的组件并不需要使用传的数据声明属性的操作就显得很多余。想要修改数据就得一个一个往上触发事件、绑定事件,过程复杂。
所以这时候就有了透传。父组件传的数据都保存在$attrs,后面层级的组件要使用就只需要第一个组件传值,最后一个组件声明属性来使用,中间的组件就只需要v-model=$attrs。父组件传递给子组件的所有事件监听器的对象都保存在$listeners,后面层级想要修改数据时触发的事件直接由最开始传值的组件来绑定。
<!-- App.vue -->
<script>
import box from "./components/out.vue"
export default {
data() {
return {
msg: '123456',
info:'app组件的信息'
}
},
components: {
box
},
methods: {
fm(arg){
console.log("app绑定自定义事件",arg)
this.msg=arg
}
}
}
</script>
<template>
<p>{{msg}}-----{{info}}</p>
<!--
把app组件的信息传给子组件。
绑定自定义事件。
-->
<box :x="msg" :y='info' @change1s='fm'></box>
</template>
<style scoped>
</style>
<!-- out.vue -->
<template>
<div>
<p>{{text}}</p>
<!-- 1、子组件要在props中定义属性,再把值传给自己的子组件 -->
<!-- <son :x='x' :y='y'></son> -->
<!--
之前绑定变量都是“v-bind:属性=‘变量’”,语法糖写法“:属性=‘变量’”,现在是必须v-bind,且后面是等号,
$attrs中保存的是父组件传递的所有值。
之前绑定事件都是“v-on:事件名=‘函数’”,语法糖写法“@事件名=‘函数’”,现在是必须v-on,且后面是等号,
$listeners中保存的是父组件传递给子组件的所有事件监听器的对象。,但Vue 将 $listeners 设计为私有属性,对于用户来说并不可见。
-->
<!-- <son v-bind='$attrs' @change1s="fn"></son> -->
<son v-bind='$attrs' v-on='$listeners'></son>
</div>
</template>
<script>
import son from './out_son.vue'
export default {
// 使用$at透传不再需要声明属性
// props:['x','y'],
data(){
return {
text:'子组件自己的信息'
}
},
mounted(){
console.log(this.$attrs)
// console.log(this.$listeners,'======')
},
components:{
son
},
methods:{
// 自己的子组件触发事件后,自己这里绑定事件,然后再触发事件,父组件绑定事件
// fn(arg){
// console.log("out绑定自定义事件",arg)
// this.$emit('change2',arg)
// }
}
}
</script>
<!-- out_son.vue -->
<template>
<div>
<p>{{own}}</p>
<!-- 孙组件要想得到app组件的信息,要app传给自己的父亲,由父亲传给自己,这样app的后代组件都要定义属性,及时中间层级的组件不适用信息 -->
<p>{{x}}----{{y}}</p>
<button @click='fn'>change</button>
</div>
</template>
<script>
export default {
props:['x','y'],
data(){
return {
own:'孙组件的信息'
}
},
methods:{
fn(){
console.log('按钮点击事件')
this.$emit('change1s',this.own)
}
}
}
</script>
<style>
</style>