vue组件间通信的几种方式
程序员文章站
2022-05-15 18:38:18
...
vue组件间的几种通信方式
方法一、props/$emit
1、父组件向子组件传值
父组件中通过v-bind绑定需要给子组件传递的值,子组件中通过props拿到父组件传递的值
//App.vue父组件
<template>
<div id="app">
<Child v-bind:username="username"/>//前者自定义名称便于子组件调用,后者要传递数据名
</div>
</template>
<script>
import Child from "./components/Child"
export default {
name: 'App',
data(){
return{
username:'张三'
}
},
components:{
Child
}
}
//child子组件
<template>
<div class="hello">
<span>{{username}}</span>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props:{
username:{ //这个就是父组件中子标签自定义名字
type:String,
default:'', //默认值
required:true
}
}
}
</script>
2、子组件向父组件传值
子组件中通过$emit给父组件传值,第一个参数为绑定的方法,第二个参数为要传递的值;父组件通过v-on监听子组件传来的方法。
// 子组件
<template>
<div>
<button @click="pushDataToParent">子组件向父组件传值</button>
</div>
</template>
<script>
export default {
name: 'app-header',
data() {
return {
title:"Vue.js Demo"
}
},
methods:{
pushDataToParent() {
this.$emit("pushDataToParent","子向父组件传值");//自定义事件 传递值“子向父组件传值”
}
}
}
</script>
// 父组件
<template>
<div id="app">
<Child v-on:pushDataToParent="receiveChildData" />//与子组件titleChanged自定义事件保持一致
// receiveChildData($event)接受传递过来的文字
<h2>{{title}}</h2>
</div>
</template>
<script>
import Child from "./components/child"
export default {
name: 'App',
data(){
return{
title:"传递的是一个值"
}
},
methods:{
receiveChildData(e){ //声明这个函数
this.title = e;
}
},
components:{
Child
}
}
</script>
方法二、$emit / $on
这种方法通过一个空的Vue实例作为*事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。
具体实现方式:
var Event=new Vue();
Event.$emit(事件名,数据);//需要传值的组件使用该方法
Event.$on(事件名,data => {});//接收数据的组件使用的方法
// 组件A
<template>
<div id="app">
<button @click="emitData">传值</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
title:"传递的是一个值"
}
},
methods:{
emitData(e){ //声明这个函数
Event.emit('pushData','传值')
}
}
}
</script>
// 组件B
<template>
<div id="app">
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
title:"传递的是一个值"
}
},
mounted(){
Event.$on('pushData',data=>{
console.log(data)
})
}
}
</script>
方法三、provide/ inject
父组件向其所有子组件注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。换句话说:父组件中通过provide来提供变量,然后在子组件中通过inject来注入变量。
provide / inject 解决了跨层级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态。
// A组件
export default {
provide: {
data: '我要给你传值了,请接好'
}
}
// B组件
export default {
inject: ['data'],
mounted () {
console.log(this.data); // 我要给你传值了,请接好
}
}
需要注意的是:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的----vue官方文档
所以,上面 A.组件 的 data如果改变了,B组件的 data是不会改变的,仍然是原来传过来的值。
那么,provide和inject如何才能实现数据响应式
答案是使用vue2.6版本最新API Vue.observable 优化响应式 provide
provide() {
this.user= Vue.observable({
username: "zhangsan"
});
return {
user: this.user
};
},
methods: {
changeUsername() {
this.user.username = 'lisi'
}
}
<template functional>
<div>
{{inject.user.username}}
</div>
</template>
<script>
export default {
inject: {
user: {
//函数式组件取值不一样
default: () => ({})
}
}
};
</script>
方法四、$attrs
继承所有的父组件属性(除了prop传递的属性、class 和 style ),通常和inheritAttrs一起使用,inheritAttrs默认值true,继承所有的父组件属性(除props的特定绑定),如果你不希望组件的根元素继承特性,设置inheritAttrs: false,但是class属性会继承
//父组件
<template>
<div class="hello">
<span>最外层组件</span>
<First :name="'张三'" :age="28" :sex="'男'" />
</div>
</template>
<script>
import First from "./first";
export default {
name: "HelloWorld",
components: {
First
},
data() {
return {};
}
};
</script>
<template>
<div class="hello">
<span>第一层组件</span>
<Second v-bind="$attrs" />
</div>
</template>
<script>
import Second from "./second";
export default {
name: "First",
components: {
Second
},
props: {
name: String
},
created() {
console.log(this.$attrs); //{age:18,sex:'男'}
}
};
</script>
<template>
<div class="hello">
<span>第二层子组件组件</span>
</div>
</template>
<script>
export default {
name: "Third",
data() {
return {};
},
props: {
age: Number
},
created() {
console.log(this.$attrs);//{sex:'男'}
}
};
</script>
方法五、vuex
此处省略一万字。。。啊哈哈哈哈
上一篇: css裁剪过于长的单行文字
下一篇: vue组件的四种写法