左小白的技术日常
Github
2020/06/29
Author: guoqzuo

vue封装组件方式的思考

在封装组件时,一般我们使用的方法是把组件单独放到一个xx.vue,然后需要引入时在components使用懒加载引入再使用

我就在想,每次引入组件都需要三步

  1. 把组件通过 components 引入
  2. 在template中写对应的代码
  3. 在data中写对应的数据,methods里写绑定的事件

会不会太麻烦了,我希望像element的组件那样,通过 this.$message.error(e.message) 这样直接调用一个组件

于是我尝试使用js的方式来调用单文件组件(.vue),在之前02/20号写过方法,除了直接挂载到body外,也可以挂载到任何地方,只要你能拿到对应的dom,可以使用ref属性,再通过this.$refs['xx']来获取其DOM 元素和组件实例。

// 引入该组件
import ShowInfo from 'showInfo.vue'

// 通过js调用
clickShow() {
  // 创建一个vue组件
  const Component = Vue.extend(ShowInfo)

  // 在文档之外渲染并且随后挂载,返回对应的Vue实例(vm)
  let showInfoVue = new Component().$mount() 

  // 将组件实例的dom,append到当前页面body下
  this.$el.appendChild(showInfoVue.$el) 
}

其实你发现没,用js直接调用vue组件可以是可以,但也要比正常情况下写更多代码,比如

  1. js调用vue的方法需要封装为一个class
  2. 以上面的示例为例子,通过js调用组件,我们需要一个成功的回调,以及传参到组件,在获取到ShowInfo时,我们需要知道我们引入的只是一个'js对象'。我们可以在对象的methods里面注入方法,用来获取传入的值,或挂载成功后的回调。这样相当于mixin,但.vue组件实现里使用这些注入的事件时会不好理解,有种默认其妙多出来全局函数的疑惑
  3. 以js方法写的组件,不能兼容默认的引用方法,如果要支持那就要写一些额外的代码
  4. 你会发现逻辑会变的不好理解,不够简单,对新手不友好,如果需要其他人维护时,可能不好理解为什么这么做

综上所述:默认的封装调用组件的方式就很好,简单、明了,你想在调用的时候轻松,那么在封装组件时,就会增加对应的工作量,整体工作量差不多。

我们再来看element组件,对于内容比较少的,比如通知类,element都提供的是js调用方法,而没有普通的组件调用方法。且一般挂载到body上。为什么dialog组件没有封装成js呢?我的理解是dialog里面的内容可扩展性很强,如果改为js调用,可能会出现把大量代码写在js的情况,或者需要写VNode的render方法。就显得不够优雅了。

总结:在封装组件时,什么时候用封装为js调用方式、什么时候采用普通的封装呢?我的理解是可以通过下面几个方面来进行评估

  1. 被封装的组件需求是否稳定,有没有可能会在后面经常变更或者进行渐进式增强,如果不稳定,不建议封装为js调用方式,对于可扩展性强的,还是建议使用普通组件封装方式,更利于维护
  2. 是否是挂载到body下,还是需要放到任意的div内? 一般普通组件更好放置。如果挂载到body下,可以考虑封装为js调用方式
  3. 是否功能相对单一简单,如果组件功能单一简单建议封装为js调用方式
  4. 该组件是否在页面里大量被调用 大量的被调用,意味着大量重复的代码,可以考虑封装为js调用方式,增加组件实现时的复杂度,来降低调用时的复杂度

总之,不管怎么样封装,当有人问你为什么这么封装时,你要能够说出你自己的理由。