美文网首页Vue.jsH5前端技术分享
如何优雅的开发一个Vue插件

如何优雅的开发一个Vue插件

作者: 胡哥有话说 | 来源:发表于2019-06-25 18:31 被阅读2次

    前言

    vue.jsReact.js是前端开发框架的两架马车,React是扎哥
    的Facebook推广开源的,Vue是尤雨溪(Evan You)个人主要进行开源维护的,目前在GitHub上Vue的star数已经超过了React的star数。

    github-2019-06-25项目star数排名.png

    对于异军突起的996.ICU -- 工作996,生病ICU,你难道不想star一下吗?!

    在如此丰富的Vue社区生态中,有很多像vue-routervuexelement-ui等优秀的Vue插件、Vue UI组件框架,给开发者提供了更多、更丰富、更方便的Vue能力。

    问题来了

    1. 如何开发自己的Vue插件呢?
    2. 如何结合公司项目,搭建可复用、易维护的UI组件库呢?

    一、了解Vue插件

    Vue插件通常是为Vue添加全局功能:

    1. 添加全局的属性和方法;
    2. 添加全局资源:指令/过滤器/过渡等;
    3. 通过全局混入(mixin)来添加一些组件选项;
    4. 添加Vue实例的方法,基于Vue.prototype实现;
    5. 一个库,提供自己的API,提供以上的一个或多个功能

    二、开发Vue插件

    Vue的插件需要暴露一个install方法,该方法第一个参数是Vue构造器,第二个参数是可选配置项对象

    /**
    * 以下代码基于cli生成项目,亦可使用其他方式,解析Vue即可
    * 考虑插件功能的完整性与独立性,可设置独立文件目录,以供移植或发布npm包
    * 以开发常用功能Loading组件为例
    * /
    
    /**
    * 目录结构
    * src/
    *     whoui
    *       assets
    *           loading.png 
    *       Loading
    *           Loading.vue
    *           index.js
    *       index.js
    *     App.vue
    *     main.js
    */ 
    

    Loading组件分析

    1. 功能需求

      • 展示/隐藏Loading状态
      • 显示Loading状态文字
    2. 调用Loading组件方式

      • 使用组件的形式调用 <who-loading></who-loading>
      • 使用实例方法调用 this.$whoLoading()

    使用组件形式调用-源码

    // src/who-ui/Loading/Loading.vue
    <template>
      <div class="who-loading-wrap" v-if="visible">
        <div class="who-loading">
          <div class="who-loading-img">
            <img class="rotate" src="../assets/loading.png" alt="">
          </div>
          <div class="who-loading-text">
            {{ text }}
          </div>
        </div>
      </div>
    </template>
    <script>
    export default {
      // 定义组件名称
      name: 'WhoLoading',
      data () {
        return {
        }
      },
      props: {
        // 是否展示
        visible: {
            reuqired: true,
            type: Boolean
        },
        // 描述的文字
        text: {
          type: String,
          default: '正在加载中.....'
        }
      }
    }
    </script>
    
    <style scoped>
    .who-loading-wrap {
      position: fixed;
      width: 100%;
      height: 100%;
      left: 0;
      top: 0;
      background: rgba(0, 0, 0, 0.6);
      display: flex;
      align-items: center;
      justify-content: center;
      color: #409eff;
      font-size: 14px;
    }
    .who-loading-img {
      display: flex;
      align-items: center;
      justify-content: center;
      margin-bottom: 10px;
    }
    .who-loading-img img {
      display: block;
    }
    @keyframes rotate {
      from {
        transform: rotate(0deg)
      }
      to {
        transform: rotate(360deg);
      }
    }
    .rotate {
      transform-origin: center;
      animation: rotate linear 2s infinite;
    }
    </style>
    

    // src/whoui/Loading/index.js
    import Loading from './Loading'
    
    export default Loading
    

    // src/whoui/index.js
    import Vue from 'vue'   
    // 引入UI组件
    import Loading from './Loading'
    
    // 定义组件列表
    const components = [
      // 可列出更多的组件
      Loading
    ]
    
    const whoUI = {
      // 必须导出的install方法
      install (Vue) {
        components.map(component => {
          Vue.component(component.name, component)
        })
      } 
    }
    
    // 导出whoUI 
    export default whoUI
    

    // src/main.js -- 加载whoUI
    import Vue from 'vue'
    // 加载使用whoUI组件
    import whoUI from './whoui'
    
    // 使用插件
    Vue.use(whoUI)
    

    // src/helloworld.vue 任意其他组件
    <template>
      <div class="hello">
        // 调用Loading组件
        <who-loading :visible="visible"></who-loading>
      </div>
    </template>
    <script>
    export default {
      data () {
        return {
          visible: true
        }
      },
      created () {
        settimeout(() => {
          // 隐藏Loading
          this.visible = false
        }, 1000)
      }
    }
    </script>
    

    使用实例方法调用-源码

    // src/who-ui/Loading/Loading.vue
    <template>
      <div class="who-loading-wrap" v-if="visible">
        <div class="who-loading">
          <div class="who-loading-img">
            <img class="rotate" src="../assets/loading.png" alt="">
          </div>
          <div class="who-loading-text">
            {{ text }}
          </div>
        </div>
      </div>
    </template>
    <script>
    export default {
      // 定义组件名称
      name: 'WhoLoading',
      data () {
        return {
          visible: false,
          text: '正在加载中.....'
        }
      },
      methods: {
        close () {
          this.visible = false
        }
      }
    }
    </script>
    
    // css样式同上 - 自行复制即可
    

    // src/whoui/Loading/index.js
    import Vue from 'vue'
    import Loading from './Loading'
    
    // 创建基于Loading组件的构造器
    const LoadingConstructor = Vue.extend(Loading)
    
    // 默认配置
    const defaults = {
      visible: false,
      text: '正在加载中.....'
    }
    
    // 定义whoLoading方法
    const whoLoading = (options) => {
      options = {
        ...defaults,
        ...options
      }
      // 创建实例
      const instance = new LoadingConstructor({
        // 创建绑定的元素
        el: document.createElement('div'),
        data: options
      })
    
      // 将绑定的元素插入到body中
      document.body.appendChild(instance.$el)
    
      // 返回实例
      return instance
    }
    
    export default whoLoadings
    

    // src/whoui/index.js
    // 引入UI组件
    import Loading from './Loading'
    
    const whoUI = {
      // 必须导出的install方法
      install (Vue) {
        // 创建实例方法
        Vue.prototype.$whoLoading = Loading
      } 
    }
    
    // 导出whoUI 
    export default whoUI
    

    // src/main.js -- 加载whoUI
    import Vue from 'vue'
    // 加载使用whoUI组件
    import whoUI from './whoui'
    
    // 使用插件
    Vue.use(whoUI)
    

     // src/helloworld.vue 任意其他组件
    <template>
      <div class="hello"></div>
    </template>
    <script>
    export default {
      data () {
        return {
          visible: true
        }
      },
      created () {
        let loading = this.$whoLoading({
          visible: true,
          text: '数据正在加载...'
        })
        
        // 设置隐藏Loading组件
        setTimeout(() => {
          loading.close()
        }, 1000)
      }
    }
    </script>   
    

    后记

    以上就是胡哥今天给大家分享的内容,喜欢的小伙伴记得收藏、转发、点击在看呦,欢迎多多留言交流...

    胡哥有话说,一个有技术,有情怀的胡哥!京东开放平台首席前端攻城狮。与你一起聊聊大前端,分享前端系统架构,框架实现原理,最新最高效的技术实践!

    长按扫码关注,更帅更漂亮呦!

    胡哥有话说

    相关文章

      网友评论

        本文标题:如何优雅的开发一个Vue插件

        本文链接:https://www.haomeiwen.com/subject/xdyzqctx.html