vue provide/inject详解和用法

2019-12-30 16:48:41

参考地址 小菜鸟之Vue - provide/inject不归路

前言

为什么我要写这么一篇文章,网上不是一堆关于provide/inject的技术文章吗? 原因在于网上的那些博客大牛文章能完美避开坑,而我这篇文章描述是挖坑和埋坑的一个过程

provide/inject是什么

依赖注入,官网的描述并不能阻止我不写这个文章,原因很简单,官网只是老菜鸟的随手备忘录,小菜鸟还需要成长磨砺,它不能解决我一些问题。

何时使用

父子组件交互方式多种,props、vuex、emit、localStorage还有就是这个provide/inject了。它适合层级比较深的组件,比如子,子孙,子孙后代的组件有好几个用到父组件的某个属性,就可以用到这个provide/inject,它可以避免写大量繁琐的传值代码
我这里为什么要使用它? 我一个知识库详情父组件中包含了大量的子组件,每个子组件都需要父组件的知识库ID,这时候我不想写大量props,就用到provide/inject进行传值了

响应式传值最终版

急躁的改写这个代码结构就可以完成provide/inject响应传值

   data() {      return {
        knowledge: {
          knowledgeId: ''
        }
      }
    },
    provide() {      return {        // 直接传对象
        kData: this.knowledge
      }
    },
    created() {      // 变更data属性knowledge下的knowledgeId元素值
      this.knowledge.knowledgeId = 2
    }

子组件使用

    inject: ['kData'],
    mounted() {
      console.error('yc:' + this.kData.knowledgeId)
    }

坑在哪

坑在于provide,子组件inject没什么难度

  • 第一版尝试

下面代码并不能在子组件获取这个kId的值,但网上有provide: {}这样定义的写法,他们之所以能够成功是kId: 'xxx'后面定义的是一个静态的字符串而不是动态的获取data中的knowledgeId属性

    data() {      return {
        knowledgeId: 1
      }
    },
    provide: {
      kId: this.knowledgeId
    }
  • 第二版尝试

上面第一版的问题很好解决,网上有另外一种写法就是通过provide函数返回一个对象,这种是可以获取到data中的属性内容

    data() {      return {
        knowledgeId: 1
      }
    },
    provide() {      return {
        kId: this.knowledgeId
      }
    }
  • 第三版尝试

第二版看起来没问题,但是如果我要在某个地方改变这个data中的knowledgeId属性,子组件是获取不到的,怎么解决? https://www.jianshu.com/p/ae0...,这篇文章提到了:

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

虽然上面讲到了本质,老菜鸟都明白,小菜鸟茫然不解,所以它不能阻止我不写下这篇文章,原因在于它没有说起这个可监听对象是怎么个回事。传入的对象是指provide中的对象还是data的对象?第三版改写成在provide传入对象

   data() {      return {
        knowledgeId: ''
      }
    },
    provide() {      return {
        pData: {
          kId: this.knowledgeId
        }
      }
    },
    mounted() {      // 更改data中的knowledgeId的值
      this.knowledgeId = 2
    }
  • 第四版尝试

第三版的写法在子组件中是无法获取变更后的knowledgeId的内容,那么就在data中包装一个对象,但是还是不行,第五版改写马上开始

    data() {      return {
        knowledge: {
          knowledgeId: ''
        }
      }
    },
    provide() {      return {
        kId: this.knowledge.knowledgeId
      }
    },
    mounted() {      this.knowledge.knowledgeId = 2
    }
  • 第五版尝试

很高兴的说,这版就是终结版,它可以在子组件获取到knowledgeId了,原理是什么? 谁在乎呢,用别人的工具,用的开心就好

    data() {      return {
        knowledge: {
          knowledgeId: ''
        }
      }
    },
    provide() {      return {        // 直接传对象
        kData: this.knowledge
      }
    },
    mounted() {      this.knowledge.knowledgeId = 2
    }

存在的小问题

正如文章:https://www.jianshu.com/p/ae0... 第三点提到的,执行顺序的问题,上面在mounted中处理provide的数据有时会导致子组件获取到的是父属性knowledge.knowledgeId的默认属性'',所以把provide数据生成的处理逻辑放到created里面就可以避免这个问题的发生

题外话

上面变更knowledgId采用了从路由获取参数,但刷新页面导致参数丢失,这是因为路由是:
path: 'detail'而不是path: 'detail/:knowledgeId',虽然前者通过
this.$router.push({ name: 'knowledgeDetail', params: { knowledgeId: knowledgeId } }) 也能传,但刷新就参数丢失了,同时webstorm更改后时不时抽筋不立即更新页面,只能手动删除html样式来告诉IDE更新,这些无疑加大了对provide/inject刚才是出问题的排查难度,索性写下这篇文章指引那些用别人工具还用这么辛苦,写尼玛代码的人找到出路

    mounted() {
      this.knowledge.knowledgeId = this.$route.params.knowledgeId
    }


  • 2021-01-24 10:25:00

    iOS中的加号和减号方法

    在OC中,方法分为类方法和实例方法。 前置加号(+)的方法为类方法,这类方法是可以直接用类名来调用的,它的作用主要是创建一个实例。有人把它称为创建实例的工厂方法。 前置减号(-)的方法为实例方法,必须使用类的实例才可以调用的。

  • 2021-02-02 09:42:14

    nuxt.js抽去css文件css代码过多不利于seo

    关于nuxt.js的资料并不是很多,有时候遇到个很简单的问题,百度或者谷歌都不是很容易找到。 其实这个问题就很简单,但是也让我浪费了很多时间,所以在此共勉。

  • 2021-02-03 16:43:11

    Hbase简介

    HBase是一个开源的非关系型分布式数据库,它参考了谷歌的BigTable建模,实现的编程语言为Java。它是Apache软件基金会的Hadoop项目的一部分,运行于HDFS文件系统之上,为 Hadoop 提供类似于BigTable 规模的服务。因此,它可以容错地存储海量稀疏的数据。 作者:Michaelhbjian 链接:https://www.jianshu.com/p/53864dc3f7b4 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 2021-02-03 16:47:05

    use_framework头文件不提示

    1、之前没有用use_frameworks!添加swift库,其他库引用使用#import <xxxx.h> 2、使用use_frameworks!添加swift库后,其他库引用使用#import "xxxx.h"

  • 2021-02-03 16:52:27

    ios静态库和动态库区别

    Framework 是 Cocoa/Cocoa Touch 程序中使用的一种资源打包方式,可以将代码文件、头文件、资源文件(nib/xib、图片、国际化文本)、说明文档等集中在一起,方便开发者使用。Framework 其实是资源打包的方式,和静态库动态库的本质是没有什么关系。

  • 2021-02-03 16:57:34

    iOS中的动态库和静态库分析

    由于最近研究组件化后调试时二进制映射源码的功能,发现需要对开发中的动态库和静态库需要有一些了解。所以就有了这篇文章,由于只是了解,并没有深入到编译层面,所以本篇文章只是简单了解一些库的知识,并不深入。

  • 2021-02-03 16:58:39

    iOS静态库与动态库的区别与打包

    这篇主要是记录一下 iOS 下静态库与动态库的打包流程,以便以后用到时快速查阅,供自己也供大家学习记录。同时也简述了一下 动态库 与 静态库 的区别。