精华内容
下载资源
问答
  • provideinjectVue中使用 应用背景 大家在写vue项目中不知道遇到过组件嵌套比较深的情况?你是不是还在使用props和$emit一层一层的传?或者使用vuex呢?但是有可能有些项目中用不到vuex的,咋整呢? 我也不知道,你去...

    provide和inject在Vue中使用

    应用背景

    大家在写vue项目中不知道遇到过组件嵌套比较深的情况?你是不是还在使用props和$emit一层一层的传?或者使用vuex呢?但是有可能有些项目中用不到vuex的,咋整呢? 我也不知道,你去别处找找吧!

    官网描述

    类型:

    • provide:Object | () => Object

    • inject:Array | { [key: string]: string | Symbol | Object }

    • 详细:
      provideinject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

    这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。

    provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 SymbolReflect.ownKeys 的环境下可工作。

    inject 选项应该是:

    • 一个字符串数组,或

    • 一个对象,对象的 key 是本地的绑定名,value 是:

      • 在可用的注入内容中搜索用的 key (字符串或 Symbol),或

      • 一个对象,该对象的:

        • from property 是在可用的注入内容中搜索用的 key (字符串或 Symbol)
        • default property 是降级情况下使用的 value
    提示:c这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

    看代码吧
    这是文件目录
    在这里插入图片描述
    祖师爷: index.vue

    <template>
      <div class="grandPa">
        祖师爷 : <span>姓名: {{ nameObj.name }}, 年龄: <i>{{ age }}</i>, 性别: <i>{{ city }}</i></span>
        <child />
        <br>
        <br>
        <el-button type="primary" plain @click="changeName">变化场景</el-button>
    
      </div>
    </template>
    
    <script>
    import child from './com/exampleCom/parent'
    export default {
      name: 'ProvideGrandPa',
      components: { child },
      data: function () {
        return {
          nameObj: {
            name: '曹操'
          },
          age: 23,
          city: '男'
        }
      },
      // 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的property。
      provide () {
        return {
          nameObj: this.nameObj, // 传入一个可监听的对象
          cityFn: () => this.city, // 通过computed来计算注入的值
          age: this.age // 直接传值
    
        }
      },
      methods: {
        changeName () {
          if (this.nameObj.name === '曹操') {
            this.nameObj.name = '蔡文姬'
            this.city = '女'
            this.age = 24
          } else {
            this.nameObj.name = '曹操'
            this.city = '男'
            this.age = 23
          }
        }
      }
    }
    </script>
    <style lang="scss" scoped>
    .grandPa{
     	width: 600px;
    	height:100px;
    	line-height: 100px;
    	border: 2px solid  #f99;
    	padding:0 10px;
    	text-align: center;
    	margin:50px auto;
    	span{
    	  font-size: 20px;
    	}
    	.blue{
    	    color: blue;
    	}
    }
    </style>
    

    bus: parent

    <template>
    	<div class="parent">
    	  bus: <strong>中转</strong>
    	  <son />
    	</div>
    </template>
    
    <script>
    import Son from './son'
    export default {
      name: 'ProvideParent',
      components: { Son }
    }
    </script>
    
    <style lang="scss" scoped>
    .parent{
    height:100px;
    line-height: 100px;
    border: 2px solid  #feafef;
    padding:0 10px;
    margin-top: 20px;
    strong{
      font-size: 20px;
    }
    
    }
    </style>
    

    孙子: son

    <template>
    	<div class="son">
    	  孙子 : <strong>姓名: {{ nameObj.name }}, 年龄: <i class="blue">{{ age }}</i>, 性别: <i class="yellow">{{ city }}</i></strong>
    	</div>
    </template>
    
    <script>
    export default {
      name: 'ProvideSon',
      // inject 来获取的值 可以是一个字符串数组、也可以是一个对象
      inject: ['nameObj', 'age', 'cityFn'],
      // inject: {
      //   nameObj: 'nameObj',
      //   age: 'age',
      //   cityFn: 'cityFn'
      // },
      computed: {
        city () {
          return this.cityFn()
        }
      },
      created () {
        console.log('nameObj', this.nameObj, this.age, this.cityFn)
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .son{
      height:100px;
      line-height: 100px;
      padding:0 10px;
      margin: 20px;
      border: 1px solid #49e2af;
    strong{
      font-size: 20px;
    }
    .blue{
        color: blue;
    }
    }
    </style>
    

    运行结果: 点击前
    在这里插入图片描述
    运行结果: 点击后
    在这里插入图片描述
    大家点击后是不是就验证了一个问题,通过观察年龄就可以得出上文提到的: provide 和 inject 绑定并不是可响应的。

    game over,再会!

    展开全文
  • vue进阶实战课目录

    vue进阶实战课目录

    provide inject跨多组件通讯

    ref$parent / $children` 在跨级通信时是有弊端的。当组件 A 和组件 B 中间隔了数代(甚至不确定具体级别)时,以往会借助 Vuex 这样的解决方案,不得不引入三方库来支持。本次介绍一种无依赖的组件通信方法:Vue.js 内置的 provide / inject 接口。
    provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

    vue的组件传值常用三种方式,1.prop传值2.$parent / $children传值3.provide inject

    注意!provide和inject只能传值或提供方法给子组件,子组件不能调用父组件方法和数据!!例如 父组件的provide 子组件都能获取到,但子组件provide 父组件是拿不到的。

    <!--  -->
    <template>
      <div>
        <div class="alert alert-primary" v-show="show">
          消息提示
        </div>
        <div class="btn btn-primary" @click="rename(123)">edit children</div>
        <demo></demo>
      </div>
    </template>
    
    
    <script>
      import demo from './demo-item.vue';
      export default {
        // 无法获取子组件方法和数据
        inject:['title','rename'],
        provide() {
          return {
            show: this.show,
            showHide: this.showHide
          }
        },
        components: {
          demo
        },
        data() {
          return {
            show: false
          };
        },
        methods: {
    		showHide(data){
    			this.show = data
    		}
        },
        watch: {
    
        },
        computed: {
    
        },
        created() {
        console.log(this.title)
        },
        mounted() {
    
        }
    
    
      };
    </script>
    <style>
    
    </style>
    
    

    子组件

    <!--  -->
    <template>
      <div>
        <h5>{{title}}</h5>
        <button class="btn btn-danger" @click="showHide(true)">
        	显示main组件里的消息提示框
        </button>
        <button class="btn btn-warning" @click="showHide(false)">
        	隐藏main组件里的消息提示框
        </button>
      </div>
    </template>
    
    <script>
      export default {
        inject:['show','showHide'],
        provide(){
          return {
            title:this.title,
            rename:this.rename
          }
        },
        components: {},
        data() {
          return {
            title: "我是父组件的标题"
          };
        },
        methods: {
          rename(data) {
            this.title = data
          }
        },
        watch: {
    
        },
        computed: {
    
        },
        created() {
          // console.log(this.show)
        },
        mounted() {
    
        }
    
    
      };
    </script>
    <style>
    
    </style>
    
    

    代码

    展开全文
  • 不论组件层次有多深,这个简直太爽了,不用再关心dom层级,只要在祖先组件内部就可以一直使用祖先组件提供的provide 用法 下面贴出一部分select的实现: provide:Object | () => Object inject:Array | { [key: ...

    案例

    UI美眉说咱家的选项菜单太丑了,小哥哥能不能美化一下呀,洒家自然是说小意思啦~

    自定义一个select组件,so easy~

    简单粗暴型:

    option作为数据进来就ok啦。

    然后发现下列问题:

    key-value,不是所有的接口都是id-name

    option要disabled 怎么办?

    option存在几种情况怎么办?

    ...

    回头看看原生的写法是这样:

    Vue

    React

    Angular

    还要加个el-option组件,灵活自由型:

    Vue

    React

    Angular

    好啦,这样设计就能完美解决之前的几个问题。

    接着要解决选择了某一个el-option,怎么告诉el-select,$parent是一种选择,那么el-select当前的值又怎么告诉el-option你被选中了呢~ 笔者没有继续去深究,因为看到了APIprovide/inject

    官方说明:

    允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深(这也是使用$parent不好实现的地方),并在起上下游关系成立的时间里始终生效。

    不论组件层次有多深,这个简直太爽了,不用再关心dom层级,只要在祖先组件内部就可以一直使用祖先组件提供的provide

    用法

    下面贴出一部分select的实现:

    provide:Object | () => Object

    inject:Array | { [key: string]: string | Symbol | Object }

    el-select

    export default {

    name: "el-select",

    provide() {

    return {

    select: this

    };

    }

    }

    el-option

    export default {

    name:'el-option',

    inject:['select'],

    created(){

    if(this.select.value===this.value){

    this.select.label=this.label;

    }

    }

    }

    总结

    provide/inject 是解决组件之间的通信问题的利器,不受层级结构的限制。

    但也不是随便去滥用,通信代表着耦合:

    展开全文
  • provide/inject深入学习本文深入探究provide,inject在官网porivide, inject的介绍中, 有这样的一段话:provideinject绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性...

    provide/inject深入学习

    本文深入探究provide,inject

    在官网porivide, inject的介绍中, 有这样的一段话:

    provide和inject绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

    本文将深入探究这句话的意思.

    父引用和子引用

    在无provide和inject时代, 一般通过组件中$parent(父引用)和$children(子组件列表)来实现在组件树上进行跨组件状态或者属性的引用, 在子组件中通过递归或者循环获取$parent的方式的得到祖先组件的数据, 由于获取到的数据是可响应的,使用时自然也就是响应式的。如在子组件中有代码:

    computed: {

    count() {

    return (this.$parent || {}).count;

    },

    user() {

    return (this.$parent || {}).user;

    },

    },

    当父组件的count(基本类型)或者user(引用类型)发生改变时, 会自动更新子组件的computed。这在组合组件(类似select和option)中非常有用, 可以把一些子组件共有的特性抽取到父组件中去进行统一设置, 如el-form中的label-width就可以为所有的子组件el-form-item设置一个默认的label-width。

    实际使用时,不会直接对this.$parent获取目标组件, 因为这样耦合性太高, 一般通过循环或者递归查找某种特征的组件,具体可以查看element-ui的emitter中冒泡中是如何查找目标组件触发事件.

    $children是不支持响应式的.

    provide/inject传递数据

    利用provide/inject机制也可以在组件树中数据自上而下进行传递: 在祖先组件中通过provide中暴露一些数据, 子组件获取这些数据. 如祖先组件中:

    props: {

    count: Number,

    user: Object,

    },

    data() {

    return {

    grade: {

    number: 12,

    },

    };

    },

    provide() {

    return {

    count: this.count,

    user: this.user,

    grade: this.grade,

    };

    },

    其中, user是外部组件通过props传递给父组件的数据, 结构为:

    {

    name: ''.

    age: 0,

    address: {

    number: 0,

    }

    }

    在子组件中, 通过inject获取这些数据:

    {

    inject: ['count', 'user', 'grade'],

    created () {

    console.log(this.count);

    }

    // ...

    }

    provide/inject响应式特性深入探究

    对上章节中provide/inject的案例进行响应式研究, 可以发现user,grade都是响应式数据结构,count不是。接着依次改变grade.number,user.address.number,user.age,user.address, 会发现子组件能接受到的响应式数据,但当改变了grade,user,count时, 子组件不能响应式渲染页面, 且改变grade,user`的属性也会发现不会响应式渲染。

    其中count由于是一个不可监听的对象, 没有在子组件中动态渲染, 符合期望。其后在改变grade.number, user.address.number, user.age, user.address时, 子组件可以动态渲染改变值,这是由于这些属性都在一个可监听对象中。改变grade, user的后,发现子组件没有动态渲染, 证明grade, user是不可响应的,这是由于grade, user不在一个可监听的对象里面。 grade, user在哪呢? 在provide的声明中, 返回了一个对象:

    provide() {

    return {

    count: this.count,

    user: this.user,

    grade: this.grade,

    };

    }

    grade, user就在这个对象里面, 该对象不是可监听对象, 所以导致grade, user不是响应式的. 首先的解决方案就是, 将这个对象作为一个响应式的,可以在data中声明一个容器字段, 用于包装需要传递的数据, 如:

    data() {

    return {

    context: {

    user: '',

    count: 0,

    grade: '',

    },

    grade: {

    number: 12,

    },

    };

    },

    watch: {

    user(val) {

    this.context.user = val;

    },

    count(val) {

    this.context.count = val;

    },

    grade(val) {

    this.context.grade = val;

    },

    },

    created() {

    this.context.user = this.user;

    this.context.count = this.count;

    this.context.grade = this.grade;

    },

    为什么这样写, 是由于provide/inject机制不支持响应式编程的,后续对provide返回的对象直接修改不会重新刷新provide/inject机制, 也就是provide返回的对象的最顶层的响应机制会失效,且无法对对象顶层属性进行操作。这个机制会导致以下三种方式不能实现响应式传递:

    上文中的context不能在computed中声明。因为每次computed都会返回一个新的值(引用),而provide只会记录一开始的context的那个引用, 后续数据发生变更, 新的context不会被刷新到provide中去。

    上文中的context就算data中声明的, 但如果在某个地方执行了this.context = {...}, 新的context也不会被更新在provide, provide中的context永远是在初始化时复制给他的那个引用。这会导致在父组件中context可以动态刷新, 但是子组件中的context不会动态刷新。

    直接在provide函数中返回上文中的context,那么user, grade就会成为顶层属性,在created中进行的重新赋值操作和后续的重新赋值操作都不会响应到provide中, 将会失去响应式。

    按照上面的写法, 发现grade, user已经能够动态在子组件中渲染了。由上得到结论:要想provide传递的数据一直是可响应的, 需要provide传递的每一个属性的值都是一个引用不变的可监听对象。

    每次维护context太麻烦了, 有没有简便方法? 可以这样写:

    provide() {

    return {

    group: this,

    };

    }

    直接将父组件的引用放在provide返回对象的一个属性中, this代表当前实例, 引用实不会发生变化的, 且this中大多数属性都是响应式的。但需要注意带$前缀的属性大多数都不是响应式属性,如$el,子组件在使用这些属性时, 不会动态渲染。如果父组件有更大的作用域时,比如同时为多种类型子组件服务,或者允许第三方子组件inject使用时, 建议不要直接传递this, 而是在provide中暴露特定的api。但是按照上文中维护一个特定的context对象太繁琐了,可以使用函数来保证引用不变(推荐使用该方式):

    provide() {

    return {

    getContext: () => ({

    user: this.user,

    grade: this.grade,

    })

    };

    }

    在子组件中:

    inject: ['getContext'],

    computed: {

    context() {

    return this.getContext();

    }

    }

    原理

    本章节从源码的角度来解密provide为什么有如此怪异的特性.

    provide/inject为什么具备响应式, 因为它的实现机制也是通过$parent实现的。provide会在初始化时放到一个_provided的属性中,子组件在访问inject的值时, 会通过$parent属性向上查找所有祖先节点的_provided获取第一个有目标属性的值, 因此子组件跟父组件是共享一个变量,如果这个变量是引用类型的话, 在子组件中改变这个值, 父组件中该值也会发生了变化。

    为什么provide返回的对象的最顶层的响应机制会失效? 在查找inject的值时, 会将目标_provide的单个属性拿出来, 放在一个不是响应式的对象中。从设计上也是合理的,provide的是一个数据集, 而不是一个数据,子组件inject到的数据可能从多个provide中挑选的集合, 故父组件的provide没有必要维持这个数据集的响应式 。

    展开全文
  • 官网给出实例,说本身是不支持数据响应式的, 但是可以传入响应式数据,那么provide,inject就可以实现响应式。我这里理解应该没错哈我自己写的demo,做了如下更改parent 页面:export default {provide(){return {foo...
  • 要点: app.vue //模板: <router-view v-if="isRouterAlive"></router-view> //Vue代码: export default { name: "App", data() { return { isRouterAlive: true ...provide() { ...
  • vue provide inject

    2021-04-09 18:50:49
    vue中祖先组件传递 后代组件层层传递 过于麻烦 可以用provide inject 祖先中 provide(){ return{ namess:this.name } }, data(){ return{ name:'provide inject' } }, 后代组件 props: { numActive: ...
  • 父组件与子组件的传参,使用的是props,如果是父组件与孙子组件传参,大部分可能会采用递归的方式,也就是子组件props...provide有父组件设置,inject由子组件接收,他们的特性:祖先组件不需要知道哪些后代组件使...
  • Vue.js中provide/inject实现响应式数据更新的方法示例发布于 2020-4-17|复制链接摘记: vue.js官方文档:https://cn.vuejs.org/v2/api/#provide-inject首先假设我们在祖辈时候传入进来是个动态的数据,官方不是说如果...
  • vue provide / inject

    2019-06-12 09:56:44
    vue 使用 provideinject。2.2.0 新增provide / inject 介绍provide 用法inject 用法实现 provide / inject 可监听 provide / inject 介绍 1. provideinject 主要为高阶插件/组件库提供用例。并不推荐直接用于...
  • vue3 provide inject

    2021-04-13 17:19:15
    ## provide inject方法一 事件在父组件执行 父组件 import {provide} from "vue"; setup(){ let provideName = ref(100) provide('name',provideName) //事件来控制 const changevals = () => { ...
  • Vue provide&inject

    2019-05-10 11:39:40
    通过学习element ui collapase 组件,来学习provideinject provide 提供出来 inject 注入进来 由父级组件提供出来,子级组件注入 a.el-collapse 父组件, 提供provide <template> <div class="el-...
  • vue provide inject传值

    2020-08-05 11:14:49
    1、parent组件使用provide提供一个injectData,son组件通过inject获取到parent注入的数据,以上就是它的最简用法 2、provide/inject这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论...
  • 那最终的方案就是Vue的eventbus了 效果图 只展示部分功能,实际原型要复杂的多; 原型大体是这样的 实现原理 其实就是各个组件独立维护自己的状态,组件的默认值从外部传入; 而内部通过watch在immediate立即...
  • 众所周知,在组件式开发中,最大的痛点就在于...今天,我们就来聊聊 Vueprovide/inject 的应用。 何为 provide/inject provide/injectVue 在 2.2.0 版本新增的 API,官网介绍如下: 这对选项需要一起使用,
  • provide/injectVue.js2.2.0版本后新增的API: provide:Object | () => Object//一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。 inject:Array<string> | { [key: string]: string | Symbol | ...
  • 处理Vuex 还有一种数据存储传递方案 ...provide / inject 2.2.0 新增 类型: provide:Object | () => Object inject:Array<string> | { [key: string]: string | Symbol | Object ...
  • vue的组件通讯方式我们熟知的有props $emit bus vuex,另外就是provide/inject provide/injectVue.js 2.2.0 版本后新增的 API,在文档中这样介绍 : 这对选项需要一起使用,以允许一个祖先组件向其所有子孙...
  • 阅读element-ui源码,发现在设计子组时件用到了inject属性,随即查了一下官方文档,得知vue在2.2.0版本里新增了provide / injectprovideinject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序...
  • vue 单页面刷新方法一( provide inject )路由跳转(不太推荐使用。本质就是跳转空白页之后再回来,地址栏会有一个快速的切换) 方法一( provide inject ) 修改app.vue中的代码 //HTML 部分 //原本 <router-...
  • 1、provide/inject有什么用?...vue提供了provideinject帮助我们解决多层次嵌套嵌套通信问题。在provide中指定要传递给子孙组件的数据,子孙组件通过inject注入祖父组件传递过来的数据。其实,...
  • vue3.0 provideinject

    千次阅读 2020-07-25 21:55:51
    import {provide,inject} from 'vue'; setup() { provide('xx','1234') const data=inject('xx',该参数为默认值); 使用ref来保证provided和injected之间值的响应: 如果注入一个响应式对象,则它的...
  • 这次给大家带来Vue多级组件provide/inject使用详解,Vue多级组件provide/inject使用的注意事项有哪些,下面就是实战案例,一起来看一下。provide / inject 是 2.2 新增的方法,可以以一个祖先组件向所有子孙后代注入...
  • vueprovideinject特性

    2019-07-10 15:57:50
    注意: provideinject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。 参考: vueprovideinject特性 provideinject实用技巧
  • vue provideinject使用

    2018-11-21 16:35:00
    provideinject使用场景也是组件传值,尤其是祖父组件--孙组件等有跨度的组件间传值,单向传值(由provide的组件传递给inject的组件)。 provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,290
精华内容 516
关键字:

injectprovidevue

vue 订阅