0
点赞
收藏
分享

微信扫一扫

Vue--provide/inject--使用/教程/实例

穆熙沐 2022-01-08 阅读 52

原文网址:Vue--provide/inject--使用/教程/实例_IT利刃出鞘的博客-CSDN博客

简介

说明

        本文用示例介绍Vue中的provide和inject的用法。

官网

Provide / Inject | Vue.js

API — Vue.js

provide和inject的简介

说明

        通过provide与inject,可以把父组件的数据和方法传递给其所有子孙后代。

        这种传递是可以跨级的。比如:父组件可以把数据传递给孙组件。

        父组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。

官方文档中有这么一句话

使用场景

        provide 和 inject 主要在开发高阶插件/组件库时使用,不推荐在应用程序中使用。

优点

解决了组件层级过多时,数据传递麻烦的问题

缺点

数据追踪困难:不确定数据注入层以及数据使用层。

用法

  • provide
    • 一个对象,或者是一个返回对象的函数。
    • 对象内包含想要传递的内容,即属性和属性值
      • 注意:子孙层的 provide 会覆盖 父辈 provide 中相同key的属性值
  • inject
    • 字符串数组,或者一个对象。
    • 属性值可以为对象,包含from,default属性
  • from
    • 可用注入内容中的key值,即 provide 传入对象中的key
  • default
    • 默认值,取值不成功时候的备选。

代码执行顺序

  1. data
  2. provide
  3. created
    1. 在这个阶段$el还未生成,在这先处理privide的逻辑,子孙组件才可以取到inject值
  4. mounted

示例:不支持响应

        provide 和 inject这种绑定不是动态响应的。即:父组件数据改变后子孙组件的数据不会改变。

代码

Parent.vue(父组件(顶层组件))

<template>
  <div class="outer">
    <h3>父组件</h3>

    名字:<input v-model="name">
    年龄:<input v-model.number="age" type="number">

    <child></child>
  </div>
</template>

<script>

import Child from "./Child";
export default {
  name: 'Parent',
  components: {Child},
  data() {
    return {
      name: 'Tony',
      age: 20,
    }
  },
  provide() {
    return {
      name: this.name,
      age: this.age
    }
  }
}
</script>

<style scoped>
.outer {
  margin: 20px;
  border: 2px solid red;
  padding: 20px;
}
</style>

Child.vue(子组件(中间组件))

<template>
  <div class="outer">
    <h3>子组件</h3>
    <div>获得顶层组件的name:{{ name }}</div>
    <div>获得顶层组件的age:{{ age }}</div>
    <grand-child></grand-child>
  </div>
</template>

<script>

import GrandChild from "./GrandChild";
export default {
  components: {GrandChild},
  inject: ['name', 'age'],
  // 详细写法
  // inject:{             // 详细指定来源以及默认值
  //   param1:{
  //     from:'Parent',   //表示从组件Parent传递过来的
  //     default:'a default msg'
  //   },
  //   reload:{
  //     from:'Parent'
  //   }
  // }
}
</script>

<style scoped>
.outer {
  margin: 20px;
  border: 2px solid blue;
  padding: 20px;
}
</style>

GrandChild.vue(孙组件(最底层组件))

<template>
  <div class="outer">
    <h3>孙组件</h3>
    <div>获得顶层组件的name:{{ name }}</div>
    <div>获得顶层组件的age:{{ age }}</div>
  </div>
</template>
<script>
export default {
  name: "GrandChild",
  inject: ['name', 'age'],
  // 详细写法
  // inject:{             // 详细指定来源以及默认值
  //   param1:{
  //     from:'Parent',   //表示从组件Parent传递过来的
  //     default:'a default msg'
  //   },
  //   reload:{
  //     from:'Parent'
  //   }
  // },

}
</script>

<style scoped>
.outer {
  margin: 20px;
  border: 2px solid green;
  padding: 20px;
}
</style>

路由(store/index.js)

import Vue from 'vue'
import Router from 'vue-router'
import Parent from "../components/Parent";
 
Vue.use(Router)
 
export default new Router({
  routes: [
    {
      path: '/parent',
      name: 'Parent',
      component: Parent,
    }
  ],
})

测试

测试1:访问

访问:http://localhost:8080/#/parent

可以看到:子组件和孙组件都能获得父组件的值。

测试2:修改父组件数据

示例:支持响应

        provide 和 inject这种绑定不是动态响应的。

        实现动态响应的方案是:将一个函数赋值给provide的一个值,这个函数返回父组件的动态数据,然后在子孙组件里面调用这个函数。

代码

Parent.vue(父组件(顶层组件))

<template>
  <div class="outer">
    <h3>父组件</h3>

    名字:<input v-model="name">
    年龄:<input v-model.number="age" type="number">

    <child></child>
  </div>
</template>

<script>

import Child from "./Child";
export default {
  name: 'Parent',
  components: {Child},
  data() {
    return {
      name: 'Tony',
      age: 20,
    }
  },
  provide() {
    return {
      name: this.name,
      age: () => this.age //这里传入的是一个function
    }
  }
}
</script>

<style scoped>
.outer {
  margin: 20px;
  border: 2px solid red;
  padding: 20px;
}
</style>

Child.vue(子组件(中间组件))

<template>
  <div class="outer">
    <h3>子组件</h3>
    <div>获得顶层组件的name:{{ name }}</div>
    <!--这里改为了使用函数来获得值-->
    <div>获得顶层组件的age:{{ age() }}</div>
    <grand-child></grand-child>
  </div>
</template>

<script>

import GrandChild from "./GrandChild";
export default {
  components: {GrandChild},
  inject: ['name', 'age'],
  // 详细写法
  // inject:{             // 详细指定来源以及默认值
  //   param1:{
  //     from:'Parent',   //表示从组件Parent传递过来的
  //     default:'a default msg'
  //   },
  //   reload:{
  //     from:'Parent'
  //   }
  // },
}
</script>

<style scoped>
.outer {
  margin: 20px;
  border: 2px solid blue;
  padding: 20px;
}
</style>

GrandChild.vue(孙组件(最底层组件))

<template>
  <div class="outer">
    <h3>孙组件</h3>
    <div>获得顶层组件的name:{{ name }}</div>
    <!--这里改为了使用函数来获得值-->
    <div>获得顶层组件的age:{{ age() }}</div>
  </div>
</template>
<script>
export default {
  name: "GrandChild",
  inject: ['name', 'age'],
  // 详细写法
  // inject:{             // 详细指定来源以及默认值
  //   param1:{
  //     from:'Parent',   //表示从组件Parent传递过来的
  //     default:'a default msg'
  //   },
  //   reload:{
  //     from:'Parent'
  //   }
  // }
}
</script>

<style scoped>
.outer {
  margin: 20px;
  border: 2px solid green;
  padding: 20px;
}
</style>

路由(store/index.js)

import Vue from 'vue'
import Router from 'vue-router'
import Parent from "../components/Parent";
 
Vue.use(Router)
 
export default new Router({
  routes: [
    {
      path: '/parent',
      name: 'Parent',
      component: Parent,
    }
  ],
})

测试

测试1:访问

访问:http://localhost:8080/#/parent

测试2:修改父组件数据

可以看到:

  1. 名字(name)没有动态更新。因为没用函数
  2. 年龄(age)动态更新。因为用了函数
举报

相关推荐

0 条评论