Vue组件开发小结

组件化是长期开发过程中一个提炼精华的过程,目的主要是以下几点:

  1. 提高复用性
  2. 解耦
  3. 提升未来的开发效率

那么如何达到这样的效果呢,我们可以分几步来循序渐进地完成。

下文主要是思路,想直接获取代码可转战ElementUI的Github去看源码

一 组件的定义

组件从大类上可以分为两种:

  • 基础组件:例如ElementUI
  • 业务组件:通过基础组件或者业务组件组合而成,与业务强相关甚至强绑定

二 组件的颗粒度

基础组件的颗粒度争议并不大,就是Button,Table等等 业务组件的颗粒度最大可以为一个feature,一个feature就是一个可以独立上线特性,例如文章的评论点赞功能。我们可以想象有一个开关,打开就有这个feature,关闭就没有,且不会造成联动的影响。

三 组件的接口

  1. Vue的组件基本都是通过属性来进行配置,进而控制组件的功能变化。因此开发组件之前我们就得明确定义变量是什么,明确组件需要开放的接口
  2. 我们需要理解每一个组件的核心功能是什么,可通过单一职责这样的设计模式来考虑。组件的核心功能是不能发生变化的,这也是为了接口的向后兼容
  3. 对于业务组件,我们可否直接把一些常年不发生变化的数据和UI绑定在一起,从而删减部分接口。大家不必担心耦合性,解耦的前提是有被解耦的需求。

四 开发组件

1 UI规范

UI规范是组件开发的物理依据,你得知道要做成什么样子,你才能做。UI规范要对整套组件的各个视觉元素(长,宽,padding,margin,圆角,颜色,字体,字号,边框,图标,阴影)有语意明确的定义和友好的标注,这样前端工程师们才能做到有法可依。

2 开发
举例:
1.sass或less来写样式
2.重置样式文件和样式的公共变量文件(将视觉元素翻译成代码中的常量形成的文件),这是根据自己的UI规范来决定的
3.ES6的哪些特性不使用,用哪一个stage的babel来翻译
4.需要引入的第三方包有哪些,这个也决定了最后打包出来组件js的大小
5.工程的目录结构
复制代码
3 打包

对于Vue,我们通常使用的是webpack。具体配置这里不详细讲解,可以参考入门Webpack,看这篇就够了,还有一个快速方法就是通过Vue-cli生成的模板工程来进行更改。 接着我们要定义清楚我们的打包策略:

举例:
1.所有的样式打到一个文件
2.有fonts则单独打出来
3.组件JS和VueJS不打在一起
4.非通用的第三方包需和组件打在一起
复制代码

五 最佳实践

以上四点是正式编写组件代码的前置工作。现在我们通过elementUI的源码来看一个最佳实践,我们的例子是比较简单的面包屑,先看一下怎么去使用的这个组件:

然后我们来看一下代码如何实现的

<template>
  <span class="el-breadcrumb__item">
    <span class="el-breadcrumb__inner" ref="link" role="link">
      <slot></slot>
    </span>
    <i v-if="separatorClass" class="el-breadcrumb__separator" :class="separatorClass"></i>
    <span v-else class="el-breadcrumb__separator" role="presentation">{{separator}}</span>
  </span>
</template>
<script>
  export default {
    name: 'ElBreadcrumbItem',
    props: {
      to: {},
      replace: Boolean
    },
    data() {
      return {
        separator: '',
        separatorClass: ''
      };
    },

    inject: ['elBreadcrumb'],

    mounted() {
      this.separator = this.elBreadcrumb.separator;
      this.separatorClass = this.elBreadcrumb.separatorClass;
      let self = this;
      if (this.to) {
        let link = this.$refs.link;
        link.setAttribute('role', 'link');
        link.addEventListener('click', _ => {
          let to = this.to;
          self.replace ? self.$router.replace(to)
            : self.$router.push(to);
        });
      }
    }
  };
</script>
复制代码

props中就是ElBreadcrumbItem暴露出来的两个接口,也就是上文第三点提到的内容,接口的值是从父组件传过来的。我们再看一下ElBreadcrumb,也就是父组件的代码实现。

这里简单解释一下inject:inject和provide是成对出现的,是vue@2.2.0的新特性。通过此种方法变可以直接调用提供provide的组件中的属性了,总结就是依赖注入(DI)。

<template>
  <div class="el-breadcrumb" aria-label="Breadcrumb" role="navigation">
    <slot></slot>
  </div>
</template>
<script>
  export default {
    name: 'ElBreadcrumb',

    props: {
      separator: {
        type: String,
        default: '/'
      },
      separatorClass: {
        type: String,
        default: ''
      }
    },

    provide() {
      return {
        elBreadcrumb: this
      };
    },

    mounted() {
      const items = this.$el.querySelectorAll('.el-breadcrumb__item');
      if (items.length) {
        items[items.length - 1].setAttribute('aria-current', 'page');
      }
    }
  };
</script>
复制代码

slot其实是专门留给ElBreadcrumbItem的插槽,实际上ElBreadcrumb不涉及什么UI,它也通过props暴露出来了两个接口,这个两个的值是使用者传入的。我们可以看到,默认的分隔符是'/',如果你在ElBreadcrumbItem中通过属性传入的分隔符是'+',那面包屑每一级中的分隔符也会是'+',注意一下代码中的provide和上面的inject相对应。最后就是让组件可注册

import ElBreadcrumb from './src/breadcrumb';

/* istanbul ignore next */
ElBreadcrumb.install = function(Vue) {
  Vue.component(ElBreadcrumb.name, ElBreadcrumb);
};

export default ElBreadcrumb;
复制代码

通过给组件添加install方法,让组件可被Vue.use方法在全局注册。可参考Vue官方文档API

总结

本文简单梳理了一下组件开发的思路,重点在于组件开发的这些前置条件:

  • 定义组件
  • 划分颗粒度
  • 理清组件的核心接口
  • 如何定义打包策略和UI规范

完成这几点,从代码层面只是一小部分工作,但若把整个组件作为一个产品来看,就已经完成了一半了。

转载于:https://juejin.im/post/5aa939776fb9a028d0432710

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值