provide/inject 是 Vue 在 2.2.0 版本新增的 API,官网介绍以下:css
这对选项须要一块儿使用,以容许一个祖先组件向其全部子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。若是你熟悉 React,这与 React 的上下文特性很类似。
在官网文档中关于 provide/inject 有这么一个提示:html
提示:provide
和inject
绑定并非可响应的。这是刻意为之的。然而,若是你传入了一个可监听的对象,那么其对象的属性仍是可响应的。
也就是说,Vue 不会对 provide 中的变量进行响应式处理。因此,要想 inject 接受的变量是响应式的,provide 提供的变量自己就须要是响应式的。vue
因为组件内部的各类状态就是可响应的,因此咱们直接在根组件中将组件自己注入 provide,此时,咱们能够在后代组件中任意访问根组件中的全部状态,根组件就成为了全局状态的容器,仔细想一想,是否是很像 React 中的 context 呢?vuex
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>provide/inject实现状态管理</title> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js"></script> </head> <body> <div id="app"></div> </body> </html> <script> Vue.component('A', { template: ` <div> <p><label>name: </label><span>{{ data.name }}</span></p> <p><label>age: </label><span>{{ data.age }}</span></p> <B></B> <C></C> </div> `, data() { return { data: { name: '', age: '' } } }, provide() { return { // 由于data属性是响应式的(vue2使用Object.defineProperty/vue3使用proxy) data: this.data } } }) Vue.component('B', { template: ` <div> <button @click="changeName">changeName</button> </div> `, inject: ['data'], methods: { changeName() { this.data.name = 'tom' } } }) Vue.component('C', { template: ` <div> <button @click="changeAge">changeAge</button> </div> `, inject: ['data'], methods: { changeAge() { this.data.age = 20 } } }) var app=new Vue({ el: '#app', template: ` <div> <A /> </div> ` }); </script>
vuex状态能够分模块管理,provide/inject也能够实现,使用根组件包裹每个模块,每一个模块的根组件管理该模块的状态。app
既然 provide/inject 如此好用,那么,为何 Vue 官方还要推荐咱们使用 Vuex,而不是用原生的 API 呢?ide
Vuex 和 provide/inject 最大的区别在于,Vuex 中的全局状态的每次修改是能够追踪回溯的,而 provide/inject 中变量的修改是没法控制的,换句话说,你不知道是哪一个组件修改了这个全局状态。post