Vue 综合- provide() 子或孙子组件如何调用Vue对象

155 阅读1分钟

provide() 基础使用

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

// 孙子组件
const ChildComponent = { 
  template: '<div>child - component {{value}}</div>',
  inject: ['yeye', 'value'],
  mounted () {
    console.log(this.$parent.$options.name); // comp
    console.log(this.yeye); // Vue 对象
    console.log(this.value); // 123
    
  }
}

// 子组件
const compoent = {
  name: 'comp',
  components: {
    ChildComponent
  },
  template: `
  <div :style="style">
    <slot value="456" :text="text"></slot>
    <child-component></child-component>
  </div>
`,
  data () {
    return {
      style: {
        width: '200px',
        height: '200px',
        border: '1px solid #aaa'
      },
      text: 'dzm'
    }
  },
  mounted () {
    console.log(this.$parent.$options.name); // Vue 对象
    
  }
}

// 父组件
new Vue({
  el: '#app',
  components: {
    compOne: compoent
  },
  provide () {
    return {
      yeye: this,
      value: this.value
    }
  },
  data () {
    return {
      value: '123'
    }
  },
  mounted () {
    console.log(this.$refs.comp, this.$refs.span);
    
  },
  template: `
    <div>
      <comp-one ref="comp">
        <span slot-scope="props" ref="span">{{props.value}} {{props.text}} {{value}}</span>
      </comp-one>
      <input type="text" v-model="value">
    </div>
  `
})

但是上面这种方式在使用里面 input 标签输入内容的时候会发现,子组件里面使用到的 value 值会跟着变化, 但是孙子组件里面的 value 是不会发生变化的,因为 provide() 不会去监听这个值的改变,那么就需要用到下面的这种方式:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

// 孙子组件
const ChildComponent = { 
  template: '<div>child - component {{data.value}}</div>',
  inject: ['yeye', 'data'],
  mounted () {
    console.log(this.$parent.$options.name); // comp
    console.log(this.yeye); // Vue 对象
    console.log(this.data.value); // 123
    
  }
}

// 子组件
const compoent = {
  name: 'comp',
  components: {
    ChildComponent
  },
  template: `
  <div :style="style">
    <slot value="456" :text="text"></slot>
    <child-component></child-component>
  </div>
`,
  data () {
    return {
      style: {
        width: '200px',
        height: '200px',
        border: '1px solid #aaa'
      },
      text: 'dzm'
    }
  },
  mounted () {
    console.log(this.$parent.$options.name); // Vue 对象
    
  }
}

// 父组件
new Vue({
  el: '#app',
  components: {
    compOne: compoent
  },
  provide () {
    const data = {}
    Object.defineProperty(data, 'value', {
      get: () => this.value, // 每次调用 value 的时候就会每次调用这个 get 方法, get方法就会每次取读取最新的值
      enumerable: true // 设置可以被读取
    })
    return {
      yeye: this,
      data
    }
  },
  data () {
    return {
      value: '123'
    }
  },
  mounted () {
    console.log(this.$refs.comp, this.$refs.span);
    
  },
  template: `
    <div>
      <comp-one ref="comp">
        <span slot-scope="props" ref="span">{{props.value}} {{props.text}} {{value}}</span>
      </comp-one>
      <input type="text" v-model="value">
    </div>
  `
})