组件通信【vue 知识汇点5】

613 阅读1分钟

props/$emit

父组件通过 props 的方式向子组件传递数据,子组件通过 $emit 向父组件通信

// parent.vue
<child :data-list="tableData" @close="handleClose"/>

data() {
	return {
    	tableData: []
    }
},
methods: {
	handleClose(val) {
    	console.log('子组件触发事件,向父组件传值',val)
    }
}

//  child.vue
<div v-for="item in tableData" :key="item">{{item}}</div>
<button @click="handleClick">向父组件传值</button>
props: {
	tableData: {
    	type: Array
    }
},
methods: {
	handleClick() {
    	this.$emit('close', 'test')
    }
}

⚠️ props 只可以从父组件传递到子组件,即所谓的单向数据流,而且 props 只读,不可被修改,所有修改都会失效并警告。

$children/$parent

$parent 访问父实例, 子实例被推入父实例的 $children 数组中。$parent是个对象,$children 是个数组。在顶层元素上,它的$parent得到的是 undefined,在最底层的子组件拿$children 的值是个数组。

$refn/$refs

ref: 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素,如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据,

爷孙组件通信

provide / inject

provide / inject 是 vue 2.2.0 新增的 api,简单来说就是父组件通过 provide 来提供变量,然后再子组件中通过 inject 来注入变量。

⚠️注意:这里不论子组件嵌套有多深,只要调用 inject 那么就可以注入 provide 中的数据,而不局限于只能从当前父组件的 props 属性中获取数据

// parent.vue
<template>
	<div>
    	<child><child>
    </div>
</template>
<script>
	import child from 'xxx'
    export default {
    	name: 'Parent',
        provide: {
        	for: 'demo'
        },
        components: {
        	child
        }
    }
</script>

// child.vue
<template>
	<div>
    	{{demo}}
        <grand-child/>
    </div>
</template>
<script>
	import grandChildren from 'xxx';
    export default {
    	name: 'child',
        inject: ['for'],
        data() {
        	return {
            	demo: this.for
            }
        },
        components: {
        	grandChild
        }
    }
</script>

// grandChild.vue
<template>
	<div>
    	{{demo}}
    </div>
</template>
<script>
    export default {
    	name: 'grandChild',
        inject: ['for'],
        data() {
        	return {
            	demo: this.for
            }
        }
    }
</script>

跨级通信 + 兄弟通信

emit / on

通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙地实现了任何组件间的通信,包括父子、兄弟、跨级等。

// 第一步:在src 新建 emit/emit.js
import Vue from 'vue';
const Emit = new Vue({});
export {Emit}

// 第二步: 在 src/main.js 下引入
import {Emit} from './emit/emit.js';
vue.prototype.Emit = Emit;

// 第三步:父组件在 mounted 里通过 this.Emit.$on() 监听,在 destroyed 生命周期里通过 this.Emit.$off() 解除绑定(一定要解除)
<template>
	<div class="indexpageWrap">
    	<header></header>
        <footer></footer>
    </div>
</template>
<script type="text/javascript">
import Header from './header.vue';
import Footer from './footer.vue';
export default {
	data() {
    	return {
        	index: 0
        }
    },
    mounted() {
    	this.Emit.$on('fromHeader', this.indexFormHeader)
        this.Emit.$on('fromFooter', this.indexFromFooter)
    },
    destoryed() {
    	this.Emit.$off('fromHeader')
		this.Emit.$off('fromFooter')
    },
    methods: {
    	indexFormHeader(value) {
        	console.log(value)
        },
        indexFromFooter(value) {
        	console.log(value)
        }
    }
}
</script>

// 第四步:通过 this.Emit.$emit 传递数据
<template>
	<div>
    	<div @click="headerEmit">Emit</div>
    </div>
</template>
<script type="text/javascript">
	export default {
    	data() {
        	return {}
        },
        methods: {
        	HeaderEmit() {
            	this.Emit.$emit('fromHeader')
            }
        }
    }
</script>

Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 Vuex 解决了多个视图依赖于同一状态来自不同视图的行为需要变更同一状态的问题,将开发者的精力聚焦于数据的更新而不是数据在组件之间的传递上。

localStorage / sessionStorage

通过 window.localStorage.getItem(key) 获取数据,通过 window.localStorage.setItem(key, value) 存储数据

attrsattrs 和 listeners

在 v2.4 中,为了解决该需求,引入了 attrsattrs 和 listeners,

  • $attrs: 包含了父作用域中,不被 prop 所识别的特性绑定,当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定,并且可以通过 v-bind 传入内部组件。通常配合 inheritAttrs 选项一起使用。
  • $listeners: 包含了父作用域中 v-on 事件监听器,它是一个对象,里面包含了作用在这个组件上的所有事件监听器。