前言
最近一直在从头开始学习vue,顺手整理一下vue组件化的相关通信方式,分析不到之处,还望各位指正。
组件化
vue组件系统提供了⼀种抽象,让我们可以使⽤独⽴可复⽤的组件来构建⼤型应⽤,任意类型的应⽤界⾯都可以抽象为⼀个组件树。组件化能提⾼开发效率
,⽅便重复使⽤
,简化调试步骤
,提升项⽬可维护性
,便于多⼈协同开发
等。
组件之间常见的通信方式
1. props / $emit
父子组件通信
// 父组件
<template>
<div>
<span>{{ desc }}</span>
<child1 :msg="msg" @getEmit="getEmit"></child1>
</div>
</template>
<script>
import child1 from "@/components/child1";
export default {
components: { child1 },
data() {
return {
msg: "我是父组件的msg",
desc:"default"
};
},
methods: {
getEmit(data) {
this.desc = data;
}
}
};
</script>
复制代码
// 子组件 => child1
<template>
<div>
<span>我是父组件传来的{{ msg }}</span>
<button @click="getEmit"></button>
</div>
</template>
<script>
export default {
props: {
msg: String
},
data() {
return {
msg: "我是父组件的msg",
childMsg:"我是child1的msg"
};
},
methods: {
getEmit(data) {
this.$emit("getEmit",this.childMsg)
}
}
};
复制代码
2. eventBus
兄弟组件通信
准备条件可以分为两种方式
1. npm install vue-bus / main.js中引用
import Vue from 'vue';
import VueBus from 'vue-bus';
Vue.use(VueBus);
组件中直接使用this.$bug.on()和this.$bus.emit()来做相应的处理
2. 创建bus.js,该文件内写入
import Vue from "vue";
export default new Vue();
复制代码
// 子组件 => child2
// 这里采用了第二种创建bus.js的方法,然后在该组件内引用
<template>
<div>
<button @click="handleSendToChild3">{{ msg }}</button>
</div>
</template>
<script>
import Bus from "@/components/bus.js";
export default {
data() {
return {
msg: "点我向child3组件传参",
childMsg:"我是child1的msg"
};
},
methods: {
handleSendToChild3(data) {
Bus.$emit("getData",this.childMsg)
}
}
};
复制代码
// 子组件 => child3
// 这里采用了第二种创建bus.js的方法,然后在该组件内引用
<template>
<div>
<span>{{ msg }}</span>
</div>
</template>
<script>
import Bus from "@/components/bus.js";
export default {
data() {
return {
msg: "",
};
},
methods: {
handleSendToChild3(data) {
Bus.$on("getData",(data)=>{
this.msg = data
})
}
}
};
复制代码
3. $attrs / $listeners
父 => 子 => 孙组件通信
其中子组件只做数据传递
多级组件嵌套需要传递数据时,如果仅仅是传递数据,而不做中间处理,可以使用这种方法
$attrs:没有被子组件组册prop,$listener:子组件可以触发父组件的非.native事件
复制代码
// 父组件
<template>
<div>
<span>{{ desc }}</span>
<child1 :msg="msg" @getEmit="getEmit" v-on="$listener"></child1>
</div>
</template>
<script>
import child1 from "@/components/child1";
export default {
components: { child1 },
data() {
return {
msg: "我是父组件的msg",
desc:""
};
},
methods: {
getEmit(data) {
this.desc = data;
}
}
};
</script>
复制代码
// 子组件 => child1 => 相对于child2组件,该组件为兄弟组件
<template>
<div>
<child2 v-bind="$attrs"></child2>
</div>
</template>
<script>
import child2 from "@/components/child2
export default {
// inheritAttrs:false,不会把未被注册的 prop 呈现为普通的 HTML 属性 ,也就是:prop="data" prop不会作为html的新属性
inheritAttrs: false,
components: { child2 },
data() {
return {
msg: "我是父组件的msg",
childMsg:"我是child1的msg"
};
},
mounted(){
this.$emit("getEmit",this.childMsg);
}
};
复制代码
// 子组件 => child2 => 相对比child1组件,该组件为兄弟组件
<template>
<div>
<span>{{ msg }} {{ $attrs.msg }}</span>
</div>
</template>
<script>
export default {
data() {
return {
msg: "该组件拿到父组件通过child1组件传递过来的值 => ",
};
},
};
复制代码
4. provide / inject
父 => 子、父 => 孙组件通信
这种官方不推荐使用,但是,在我们写UI组件库的时候就往往很有用了,详见elementUI的部分源码(如form表单),这里我准备后续在此基础之上再进一步展开
复制代码
// 父组件
<template>
<div>
<span>{{ desc }}</span>
<child1 :msg="msg"></child1>
</div>
</template>
<script>
import child1 from "@/components/child1";
export default {
provide:{
desc:this.desc // 这里不接收动态传参,但是可以直接传this过去,从而实现动态响应式
}
components: { child1 },
data() {
return {
msg: "我是父组件的msg",
desc:"我是父组件的desc"
};
}
};
</script>
复制代码
// child1部分代码上面已经赘述过多,此处省略
复制代码
// 孙组件 => grandson1
<template>
<div>
<span>{{ desc }}</span>
</div>
</template>
<script>
export default {
inject:['desc'],
};
</script>
复制代码
5. $ref
父子组件通信
// 父组件
<template>
<div>
<child1 ref="sendMsg"></child1>
</div>
</template>
<script>
import child1 from "@/components/child1";
export default {
components: { child1 },
data() {
return {
msg: "我是父组件的msg",
};
},
mounted() {
this.refs.sendMsg.handleSendToChild1(this.msg)
}
};
</script>
复制代码
// 子组件 => child1
<template>
<div>
<span>{{ msg }} </span>
</div>
</template>
<script>
export default {
data() {
return {
msg: "",
};
},
methods: {
handleSendToChild1(data) {
this.msg = data;
}
},
};
复制代码
6. vuex
vue的状态管理器,可以集中式储存各组件之间的状态
// 该小节,我准备留在以后补充....
复制代码
讲在最后
这篇文章从开头到结尾,虽然篇幅不多,但是完成度是比较坎坷的,原因是因为我的时间管理不够强,写着写着就又开始去学习其他的技术了(源码这种东西看多了,真的会上瘾),总是想着玉米西瓜一把抓,而忽略了一件事情从开始到闭环到重要性,希望总结于此,以后应当引以为戒。