Skip to content

这是一个同事遇到的bug

问题是:

  1. 他希望动态显示几个表单元素,通过一个radio控制,【是】就显示这几个表单元素,【否】就不显示
  2. 这个功能别人以前就做好了,做得比较难看(字面意思),属于屎山代码
  3. 现在的情况是,这个功能坏掉了,即使选【是】也是没有展示这几个表单元素
  4. 上一个版本还是可用的,这个版本他改了几行代码,这个功能就坏掉了

功能其实还是挺简单的,困难是屎山代码,比较难看。 他向我展示了,他的改动点,认为没有改动到这个地方(也就是控制显示v-if变量及逻辑),我看也确实没有改动

我首先确认的是,它这个动态的表单元素是通过具名插槽放进这个自定义form组件的 再通过v-if控制是否有这个几个具名插槽,这部分是没有改动的,具名插槽名字是写死的,渲染不出来的话,一定不是template的问题,v-if也没有改动,所以v-if的判断也没问题。

他这个组件,外面导入了一个配置文件js,里面配置了有哪些插槽,这几个动态表单元素也是配置在里面的。 所以可以断定,导入的这个配置,在组件渲染运行的某个过程中,这个配置数据被修改了,导致配置数据缺了这几个配置项,自然也显示不出来了。

页面上打印这个配置数据,确实那几项配置数据丢失了。但是我去搜索他导入的配置项,没有发现任何显示修改配置项的地方。但是经过debug,显示配置项在一处修改"不相关"变量前是正确的,修改之后就丢失了。

可以断定,“不相关”的变量一定在某处跟这个import导入的数据发生了关系,遂全局搜索这个“不相关”变量,发现了他改动了一处内部封装的组件,在组件created生命周期里,判断“不相关”变量值,并对prop传进来的另一个名字的数据进行了变更,而这“另一个名字”的数据,正是没有经过任何处理,直接导入的配置项,不过在这个嵌套颇深的子组件里,它陡然换了另外一个名字

总结他的问题和几点经验:

  1. import导入配置文件,配置文件的内容是不可以在程序运行期间被修改的,他的配置,在程序运行的期间被动态修改了(导入的配置应该要冻结,一来本身配置就是不能通过js操作改的,二来配置作为data,既然不能改,也不需要vue去作为响应式数据处理)
  2. import导入的是引用类型,他把引用类型传入了另一个子组件,因为是引用类型,无论在哪一个传入的子组件修改了,源数据都被改了(要小心引用类型的直接传递,因为一处的不小心修改,可能将导致其他消费的组件出问题)
  3. 不要去直接修改传入的prop的数据(数据要保持单向流动性,不能你也改,我也改,即使去改,也要通过显式的方法去修改,保证能通知到依赖这些数据的组件)
  4. 谨慎修改屎山代码,尤其屎山代码里的公共组件,不能保证哪里有一个坑在等着(程序的架构很重要,如果每一次的功能迭代都要破坏性修改,那代码很快就会成为屎山)