《Vue选项-provide inject》

140 阅读2分钟

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深

provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。

inject 选项应该是: 一个字符串数组

举例

需求

一键换肤:点击一个按钮,整个页面的按钮和文字颜色变化。

结构

我们采用一个三层嵌套的组件。

最上层是App.vue,它包含五个Child组件。

第二层是Child1.vue(2/3/4/5),它包含一段文本Child1,和切换颜色组件。

第三层是ChangeThemeButton.vue,它只有一个“换肤”按钮。

App.vue

通过类名的改变,切换颜色。data里有一个 themeName 数据,默认是 blue 。当变为 red 时,通过CSS样式变成红色。

<template>
  <div :class="`app theme-${themeName}`">
    <Child1/>
    ...
  </div>
</template>

<script>
    import Child1 from "./components/Child1.vue";
    ...
    export default {
      name: "App",
      data() {
        return {
          themeName: "blue", // 'red'
          fontSize: "normal" // 'big' | 'small'
        };
      },
      components: {
        Child1,
        ...
      }
    };
</script>

Child1.vue

<template>
  <div>Child 1
    <change-theme-button/>
  </div>
</template>

<script>
    import ChangeThemeButton from "./ChangeThemeButton.vue";
    export default {
      components: {
        ChangeThemeButton
      }
    };
</script>

ChangeThemeButton.vue

<template>
  <div>
    <button>换肤</button>
  </div>
</template>

我们需要在第三层组件里改变最上层组件的一个data。

需要用到 provide ,在最上层组件里把需要用到的数据提供出来。即 themeName

//App.vue
provide(){
    return {
      themeName:this.themeName,
      changeTheme:this.changeTheme,
    }
  },
methods:{
    changeTheme(){
      if(this.themeName==='blue'){
        this.themeName='red'
      }else{
        this.themeName='blue'
      }
    }
},

因为this.themeName是一个字符串,所以提供出去的themeName是原本字符串的复制品。即,如果在其他地方修改themeName,是不会影响原本的数据的

所以在按钮组件里,注入这个变量后,不能点击按钮直接修改 this.themeName

那怎么办呢?

在你这里修改不好使,那我(App.vue)在我自己身上写一个函数,修改我自己的数据,然后把这个函数提供给你,你注入这个函数,就可以使用了。

//ChangeThemeButton.vue
<template>
  <div>
    <button @click='x'>换肤</button>
  </div>
</template>

<script>
export default {
  inject:['themeName','changeTheme'],
  methods:{
    x(){
      this.changeTheme()
    },
  }
}
</script>

可以看到,provide/inject选项类似于祖先栽树,后人乘凉。

在最上边把我的方法,数据都提供好,下边的子孙们谁都可以用,谁想用就inject,注入到自己身上,就是this上。

作用:大范围的data和methods共用。

不能只传themeName,不传changeTheme方法。因为我提供出去的时候,themeName的值是被复制给provide的,和原来的不是同一个,所以改变复制出去的值,并不会影响原本的值。

也可以在定义这个data的时候,把字符串改成对象,提供出去的就是引用。所以在按钮组件里直接修改是可以改变原本的值的。但是不推荐这样做。容易失控