渐进式、组件化、轻量级是vue的特点。可以实现组件的复用,组件之间可以互相嵌套
因为组件实例的作用域相互独立,所以不同组件之间的数据难以实现共享,所以就组件间的数据通信做以下分析:
一、组件之间的关系
- 父子组件
- 兄弟组件
- 隔代组件
二、通信方法
1、props/$emit
这种方法一般使用与父子组件之间的通信,父组件通过props向子组件传值,子组件通过$emit向父组件发送数据
父组件:
<template>
<div class="father">
我是父组件,我有一个值{{age}}<br />
我获取到了子组件的值{{sonAge}}
<Son :fatherAge="age" @sendAge="getSonAge"></Son>
</div>
</template>
<script>
import Son from './Son.vue'
export default {
name: 'name',
data() {
return {
age: 48, // 父组件的值
sonAge: 0 // 定义值存储子组件获取的值
}
},
methods: {
// 获取子组件的值并储存
getSonAge(e) {
this.sonAge = e
}
},
components: {
Son
}
}
</script>
<style lang="less" scoped>
.father {
display: flex;
flex-direction: column;
align-items: center;
width: 600px;
height: 300px;
font-size: 20px;
background-color: #ccc;
}
</style>
子组件:
<template>
<div class="son">
我是子组件,我有一个值{{age}}
<div>我拿到的父组件的值{{fatherAge}}</div>
</div>
</template>
<script>
export default {
name: 'Son',
props: ['fatherAge'], // props接收父组件传递的值
data() {
return {
age: 15
}
},
mounted() {
// emit发送事件,通过参数传递子组件的数值
this.emit('sendAge', this.age)
}
}
</script>
<style lang="less" scoped>
.son {
width: 400px;
height: 150px;
text-align: center;
font-size: 16px;
background-color: #efefef;
}
span {
margin-bottom: 10px;
}
</style>
结果:
2、事件总线(emit/on)
这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧实现任何组件间的通信,包括父子、兄弟、跨级。
安装全局事件总线
// 向Vue原型上添加实例,能够被其他vc/vm访问
new Vue({
el: '#app',
render: h=> h(App),
beforeCreate(){
Vue.prototype.$bus = this
}
})
发送事件传递数据
<template>
</template>
<script>
export default {
methods:{
this.bus.emit('sendAge',13)
}
}
</script>
<style lang="less" scoped>
</style>
监听事件接收数据
<template>
</template>
<script>
export default {
mounted(){
this.bus.on('sendAge',(data)=>{
console.log('我收到了数据',data)
})
}
}
</script>
<style lang="less" scoped>
</style>
移除事件监听
this.bus.off('sendAge')
3、vuex组件通信
Vuex 是一个专为Vue.js应用程序开发的状态管理模式+库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取State数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走Action,但Action也是无法直接修改State的,还是需要通过Mutation来修改State的数据。最后,根据State的变化,渲染到视图上。
链接待定...
4、provide/inject
vue2.2新增的API,允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效
// 祖先.vue
export default {
provide: {
name: 'ancestor'
}
}
/**************************************/
// 子孙.vue
export default {
inject: ['name'],
mounted () {
console.log(this.name); // ancestor
}
}
祖先组件提供了一个name属性,他的所有后代组件都可以通过inject访问到这个值
provide/inject因为这个API不是响应式的,主要用于高阶插件和组件库,要实现响应式需要挂载很多没必要的东西
5、parent/children
可以通过parent/children直接访问到组件实例,就可以使用该组件的方法和数据
增加了对象之间的耦合度,大型项目不建议使用
6、第三方库mitt
Vue3.0中取消emit的变动,使得没法再按vue2事件总线的方式使用了。官方建议使用第三方库mitt
。
安装
npm install --save mitt
创建一个js文件
import Mitt from 'mitt'
const eventHub = new Mitt();
eventHub.on = eventHub.on;
eventHub.off = eventHub.off;
eventHub.$emit = eventHub.emit;
export default eventHub;
注册到vue实例
import {createApp} from 'vue'
import App from "./App.vue"
import eventHub from '@/plugins/eventHub.js';
const app = createApp(App);
// 配置全局事件总线
app.config.globalProperties.eventHub = eventHub;
app.mount('#app');
监听
import { getCurrentInstance, onMounted } from 'vue';
export default {
name: 'YourComponent',
setup() {
const { eventHub } = getCurrentInstance().proxy;
eventHub.on('event-name', eventHandler);
onBeforeUnmount(() => {
eventHub.off('event-name', eventHandler);
});
},
};
派发
import { getCurrentInstance, onMounted } from 'vue';
export default {
name: '',
setup() {
const { eventHub } = getCurrentInstance().proxy;
onMounted(() => {
eventHub.$emit('event-name', 'some params');
});
},
};
文章评论