组件间传值
- props、$emit
- $attrs、$listeners
- provide、inject
- vuex(暂不展开)
一、父子组件间传值
(1)父组件向子组件传值(通过 props 属性)
- 父组件直接在子组件标签上传值
<div>
<child :value='message'><child>
</div>
import Child from './Child.vue'
components: {
Child
},
- 子组件通过 this.value 来获取值
// 定义属性
props: [ 'value' ],
created() {
let msg = this.value
console.log(msg)
}
(2)子组件向父组件传值(通过 emit 事件)
- 子组件
<div @click="confirm">确定</div>
confirm() {
this.$emit('confirm', this.value);
},
- 父组件
通过 @confirm="onConfirm" 把子组件的事件传递给父组件的自定义事件
<div>
<child
:value="message"
@confirm="onConfirm">
</child>
</div>
onConfirm (value) {
let msg = value;
console.log(msg);
},
二、祖先后代组件间传值
使用【$attrs、$listeners】
或【provide、inject】
如果我们有:A组件(父) -> B组件(子) -> C组件(孙),而我们只是想把A组件的信息传递给C组件,如果使用props来传递信息,虽然能够实现,但是代码不够美观。在vue2.4中,为了解决该需求,引入了$attrs 和 $listeners
和inheritAttrs
(默认true,标签元素中是否继承父组件传递过来的属性)。
(1)$attrs、$listeners
$attrs
包含了父作用域中非 props 特性绑定的属性 (class 和 style 除外)。它可以通过 v-bind="$attrs"
将属性传入内部组件。
$props
包含了父作用域中 props 特性绑定的属性 (class 和 style 除外)。
$listeners
包含了父作用域中 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners"
将事件监听指向这个组件内的子组件。
- 父组件
<div id="app">
<!-- 父组件调用子组件 -->
<child :name="111" :age="18" :city="'北京'" @ffunc="fatherFunction"></child>
</div>
function fatherFunction() {
console.log('父组件 function!!!')
}
- 子组件
<div>
<!-- 子组件通过$attrs获取属性值 -->
姓名:{{ $props.name }} - 年龄:{{ $attrs.age }} - 城市:{{ $attrs.city }}
<!-- 子组件通过 v-bind="$attrs" 将属性传入内部组件,通过 v-on="$listeners" 将事件监听指向这个组件内的子组件 -->
<son :msg="333" v-bind="$attrs" v-on="$listeners"></son>
</div>
inheritAttrs: true, // 标签元素中是否继承父组件传递过来的属性
props: [ 'name' ],
created() {
console.log(this.$attrs, this.$props);
this.$emit('ffunc')
}
- 孙组件
<div>
<!-- 孙子组件通过$attrs获取属性值 -->
消息:{{ $props.msg }} - 年龄:{{ $attrs.age }}
</div>
inheritAttrs: false, // 标签元素中是否继承父组件传递过来的属性
props: [ 'msg' ],
created() {
console.log(this.$attrs, this.$props);
this.$emit('ffunc')
}
inheritAttrs
(默认true,标签元素中是否继承父组件传递过来的属性)
WX20210618-181158@2x.png
(2)provide、inject
假如有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。
对于这种情况,我们可以使用一对 provide 和 inject。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这些数据。
- 父组件
<div id="app">
<!-- 父组件 -->
<child></child>
</div>
data () {
return {
name: '我是父组件的数据',
age: '',
city: ''
}
},
provide() { // 父组件提供数据(只需要name字段数据)
return {
user: this.name
}
},
- 子组件
<son></son>
- 孙组件
<div>
获取父组件的数据:{{ user }}
</div>
inject: ['user'], // 子组件使用数据
created() {
console.log(this.user)
}