天天看点

Vue里面的provided,inject实现响应式数据探索

 这种传递数据的方式不是响应式的,官方文档说是刻意为之,那么我们要实现响应式的传递,那该怎么处理呢?

首先来看我们正常的使用方式:

import Son from './Son'
  export default {
    provide () {
      return {
        text: this.test
      }
    },
    data () {
      return {
        test: "parent-text"
      }
    },
    created () {
      setTimeout(() => {
        this.test = 'new-parent-text' //这里test变化了,但是子组件接收到的未变
        this._provided.text = 'new-provided-text' //provide里面的变化了,但是子组件接收到还是未变化
        window.console.log(this._provided)
      }, 1000)
    },
    components: {
      Son
    }
  }

           

子组件

export default {
    inject: ['text'],
    data () {
      return {
        childText: this.text  //此时的数据并未更新
      }
    },
    computed: {

    },
  }
           

尝试一:

export default {
    inject: ['text'],
    data () {
      return {
        childTextOld: this.text
      }
    },
    created () {
      setTimeout(() => {
        // 子组件获得的foo 依旧是old words
        window.console.log(this.text)
      }, 2000)
    },
    computed: {
      childText () {
        return this.text //通过computed,我们知道data中有get/set,数据也是响应式的,但是现在还是没有更新
      }
    },
           

尝试二:

我们把父组件里面provide里面传入一个返回要暴露出去的函数,这个函数返回父组件的动态数据,然后在子孙组件里面调用这个函数。实际上这个函数存储了父组件实例的引用,所以每次子组件都能获取到最新的数据。

/*  provide () {
       return {
         text: this.test
       }
     }, */
    provide: function () {
      return {
        text: this.test,
        getReaciveNameFromParent: () => this.test
      }
    },
    data () {
      return {
        test: "parent-text"
      }
    },
    created () {
      setTimeout(() => {
        this.test = 'new-parent-text' //这里test变化了,但是子组件接收到的未变
        this._provided.text = 'new-provided-text' //
        window.console.log(this._provided)
      }, 1000)
    },
    components: {
      Son
    }
           

子组件的改造

inject: ['text', 'getReaciveNameFromParent'],
    data () {
      return {
        childTextOld: this.text,
      }
    },
    created () {
      setTimeout(() => {
        // 子组件获得的foo 依旧是old words
        window.console.log(this.text)
      }, 2000)
    },
    computed: {
      childText () {
        return this.text //通过computed,我们知道data中有get/set,数据也是响应式的,但是现在还是没有更新
      },
      reactiveNameFromParent () {
        return this.getReaciveNameFromParent()
      }
    },
    watch: {
      'reactiveNameFromParent': function (val) {
        window.console.log('来自Parent组件的name值发生了变化', val)
      }
    },
    mounted () {
      window.console.log(this.text, 'nameFromParent')
    }
           

这样就实现了想要的效果!

尝试三:

也是在第二种尝试的基础上进去的,就是利用传入的是引用地址,对象,实现数据的响应式接收

provide () {
      return {
        text: this.test
      }
    },

    data () {
      return {
        test: {
          a: "parent-text"
        }
      }
    },
    created () {
      setTimeout(() => {
        this.test.a = 'new-parent-text' //这里test变化了,但是子组件接收到的未变
        this._provided.text = 'new-provided-text' //
        window.console.log(this._provided)
      }, 1000)
    },
    components: {
      Son
    }
           

然后子组件正常接收即可

inject: ['text'],
    data () {
      return {
        childTextOld: this.text.a,
      }
    },
    created () {
      setTimeout(() => {
        // 子组件获得的foo 依旧是old words
        window.console.log(this.text)
      }, 2000)
    },
    computed: {
      childText () {
        return this.text.a //通过computed,我们知道data中有get/set,数据也是响应式的,但是现在还是没有更新
      },

    },