1. 程式人生 > 實用技巧 >Vue.js中provide/inject實現響應式資料更新的方法示例

Vue.js中provide/inject實現響應式資料更新的方法示例

vue.js官方文件:https://cn.vuejs.org/v2/api/#provide-inject

首先假設我們在祖輩時候傳入進來是個動態的資料,官方不是說如果你傳入了一個可監聽的物件,那麼其物件還是可響應的麼?

parent父頁面:

export default {
 provide() {
  return  { foo: this.fonnB }
 },
 data(){
  return { fonnB: 'old word '} 
 }
created() {
  setTimeout(()=>{
   this.fonnB = 'new words';  // 這裡僅僅foonB變化了,foo沒有變化
   this._provided.foo="new words"; // 這裡foo變化了,但子元件獲得的foo 依舊是old words
   console.log( this._provided);
  },1000)
 },
}

child子頁面:

export default {
 inject:['foo'],
 data(){
  return { chilrfoo: this.foo } 
 },
 created() {
  setTimeout(()=>{
   // 子元件獲得的foo 依舊是old words
   console.log( this.foo)
  },2000)
 }
}

結果:

通過上面方式,經過驗證,子元件頁面都沒辦法實現響應更新this.foo的值。可能我們對官方理解還是有誤,下面通過網上資料和自己構思實現了響應式資料更新

示例(結果仍不可行)


很明顯上面再父元件定時器內我們是改變了資料來源,這個時候我們就在想,我們改變的資料到底有沒有傳入到子孫元件中,那麼要驗證這個問題,我們不妨可以在子孫元件中手動寫set 函式,computed 本身就只相當於一個get函式,當然,你也可以試試watch

parent父頁面:

export default {
provide() {
   return  { foo: this.fonnB }
  },
  data(){
   return {
    fonnB: 'old word'
   } 
  }
   created() {
   setTimeout(()=>{
    this.fonnB = "new words";  
    // 這裡foo變化了,但子元件獲得的foo 依舊是old words
   },1000)

  },

 }

child子頁面:

export default {
  inject:['foo'],
  data(){
   return {
    childfooOld: this.foo
   } 
  },
  computed:{
    chilrdfoo() {
      return this.foo
    }
  },
 created () {
    console.log(this.foo)
    // -> 'old word'
    setTimeout(() => {
      console.log(this.chilrdfoo); // 這裡計算屬性依舊是old words
    }, 2000);
   }
 }

通過computed,我們都知道data中有get/set,資料也是響應式的,但為什麼沒更新,有點疑惑,如果有大佬知道能解釋清楚的可以探討。

但是,但是,但是!實際需求肯定沒有這麼簡單,往往我們需要的是共享父元件裡面的動態資料,這些資料可能來自於data 或者 store。 就是說父元件裡面的資料發生變化之後,需要同步到子孫元件裡面。這時候該怎麼做呢?
我想的是將一個函式賦值給provide的一個值,這個函式返回父元件的動態資料,然後在子孫元件裡面呼叫這個函式。
實際上這個函式儲存了父元件例項的引用,所以每次子元件都能獲取到最新的資料。程式碼長下面的樣子:

Parent元件:

<template>
  <div class="parent-container">
   Parent元件
   <br/>
   <button type="button" @click="changeName">改變name</button>
   <br/>
   Parent元件中 name的值: {{name}}
   <Child v-bind="{name: 'k3vvvv'}" />
  </div>
</template>

<style scoped>
 .parent-container {
  padding: 30px;
  border: 1px solid burlywood;
 }
</style>

<script>
import Child from './Child'
export default {
 name: 'Parent',
 data () {
  return {
   name: 'Kevin'
  }
 },
 methods: {
  changeName (val) {
   this.name = 'Kev'
  }
 },
 provide: function () {
  return {
   nameFromParent: this.name,
   getReaciveNameFromParent: () => this.name
  }
 },
 // provide: {
 // nameFromParent: this.name,
 // getReaciveNameFromParent: () => this.name
 // },
 components: {
  Child
 }
}
</script>

Child元件

<template>
 <div class="child-container">
  Child元件
  <br/>
  <GrandSon />
 </div>
</template>
<style scoped>
 .child-container {
  padding: 30px;
  border: 1px solid burlywood;
 }
</style>
<script>
import GrandSon from './GrandSon'
export default {
 components: {
  GrandSon
 }
}
</script>

GrandSon元件:

<template>
 <div class="grandson-container">
  Grandson元件
  <br/>
  {{nameFromParent}}
  <br/>
  {{reactiveNameFromParent}}
 </div>
</template>
<style scoped>
 .grandson-container {
  padding: 30px;
  border: 1px solid burlywood;
 }
</style>
<script>
export default {
 inject: ['nameFromParent', 'getReaciveNameFromParent'],
 computed: {
  reactiveNameFromParent () {
   return this.getReaciveNameFromParent()
  }
 },
 watch: {
  'reactiveNameFromParent': function (val) {
   console.log('來自Parent元件的name值發生了變化', val)
  }
 },
 mounted () {
  console.log(this.nameFromParent, 'nameFromParent')
 }
}
</script>

結果:

來自於reactiveNameFromParent ,隨著祖先元件變化而變化了

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援碼農教程。