南妮!vue引用组件时总报错,必须得查这查那的源码

南妮!vue引用组件时总报错,必须得查这查那的源码

背景

原则上,为了便于维护和统一,我们会把可能在多个地方使用的功能做成一个组件。

而接手项目的时候,也尽量使用别人已有的组件。

这不,最近刚接手了个项目,引用别人的组件时,有些是可以使用的,但过些时间,发现就不能使用了,有的不能使用,直接报错。

本来好的,突然坏了这种就很搞事情了,要是没发现,演示是被老板看到岂不直接死翘翘?

问题现象

然后报错信息类似 [Vue warn]: Property or method "valueList" is not defined on the instance but referenced during render.

然后组件无法按预取工作,渲染不正常,功能无法使用。

问题排查

  • 检查组件是否可使用
    反正组件在自己的页面运行不正常,如果知道别人哪里有使用这个组件的情况下,先去看看这个组件在别人的页面上是不是能正常使用。

别人的页面能正常使用。

  • 确定使用方式
    那么看看是不是自己的使用方式不对。这时候就得看组件的 API 文档,这个当然一般都没有,所以就只能看源码了。源码先看入参部分,好家伙,props 该传的都传了。

搜索一下报错的东西,valueList 有匹配结果 inject:['valueList'],这是什么鬼?看起来这像是要注入一个参数,而我没有注入。

百度一下 vue inject 由于是 vue 项目所以需要添加关键字作为限定。

在父组件只要声明了provide,在其子组件,孙组件,曾孙组件等能形成上下游关系的组件中交互,无论多深都能通过inject来访问provider中的数据。

看起来在这个组件需要依赖 valueList 这个数据,可能我没有在我的页面里使用 provide

解决问题

那么问题来了, valueList 数组是什么?我该构造怎样的数据给它?

好吧,这时候就得查找别人是怎么引用这个组件的,然后根据 inject 的使用方式,需要找到引用这个组件的父级里找 provide 参数在哪声明的,需要看看构造这个参数的地方是怎样构造的。

那吧,上一层没有,再上一层……

也可以直接在代码中那家关键字 valueList 找到附近有 provide 即大概率确认。

现在,在一个上上上级 index.vue 中找到了以下代码片段:

  provide(){
    return {
      valueList:() => this.valueList
    }

  },

看起来还得再找 this.valueList 是什么东西……

知道了 valueList 是怎么构造的,这下还得思考,在自己的引用这个组件的地方,能不能构造出现这样的数据,例如这些数据可能由其他参数产生,但这个参数你所在的页面不一定能拿到。

思考问题根源

通过上面这些历程,不禁让人沉思,用个组件这么麻烦?不应该引用后传入必要的参数就好了嘛?像 antd / element-ui 这些 ui 组件库一样。

为什么看了组件本身的源码不行,还得看组件上上上层的源码?

这相当于定义了一个未知作用域的未知位置的不易追踪的“全局”变量,与 单向数据流状态可管理 截然相反。

解决问题根源

通过上面这些历程,我不认为这样的 inject 使用方式是一种优雅的使用方式。于是百度 不推荐 inject 类似的关键字,希望能找到一些大佬“喊话”,然后向人说明这样的搞法不行,这样搞得我用组件的人很难受。

果然,在官网上就有醒目的警告注明:

provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

另外在很多第三方文章中也有:

官网不建议在应用中直接使用该办法,理由很直接:他怕你"管不好"

设计项目,通常追求有清晰的数据流向和合理的组件层级关系便于调试和维护,然而这对选项支持任意层级都能访问,导致数据追踪比较困难。不知道那一层级声明了provide又或是哪些层级使用了inject。造成比较大的维护成本。因此,除组件库或高阶插件外,Vue建议用Vuex解决或其他办法处理。

果然不出所料,找到各种文献,就可能借他人之口让写组件的人处理一下这些问题了。

后记

像这种不太负责的 inject 实现已经贯穿了整个项目的五心六腑,要改的地方可能很多。在这种情况下,如何愿意改和如何改又是一门学问了。

上一篇:Vue 2.0 深入源码分析(八) 基础篇 依赖注入 provide/inject组合详解


下一篇:python安装后pip用不了 cmd命令窗口提示:Did not provide a command