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