zoukankan      html  css  js  c++  java
  • vue plugin 插件编写以loading为例

    我们在使用vue开发的过程中,经常会遇到这两个问题:

    1. 我要使用loading(加载动画) toast(浮层提示) dialog(弹框提示)之类的全局性组件,但是用全局组件注册的话非常麻烦,还要在template标签中书写组件html代码然后参数通过在data选项中注册变量来控制组件的显示/隐藏/提示语,显得异常麻烦~
    2. 我要使用某些全局函数例如(axios)来进行某些操作,如果每次使用都需要import或者require的话,是一件不太优雅的事情

    所以我们就想到在vue的全局实例Vue或者指向这个实例的指针this的原型上添加某一方法来达到随用随取的效果。

    本文以loading为例,讲下如何编写一个Vue插件。

    首先我们编写一个普通的loading组件,作为插件的模板:

    // my-project/src/plugin/loading/loading.vue
    <template>
      <transition :name="animateName">
        <div class="loadings" v-show="isShow">
          <div class="loadings__loader">
            <div class="loadings__loader__dot"></div>
            <div class="loadings__loader__dot"></div>
            <div class="loadings__loader__dot"></div>
            <div class="loadings__loader__dot"></div>
            <div class="loadings__loader__dot"></div>
          </div>
        </div>
      </transition>
    </template>
    <script type="text/babel">

    export default {

      data() {

        return {

           isShow: false,

           hasAnimate: true,

         }

       },

       computed: {

        /** * 动画效果样式,没有返回空 * @return {String} 样式 */

         animateName() {

           return this.hasAnimate ? 'opacity' : ''

         },

       },

       methods: {

         /** * 开启动画效果 */

         opemAnimate() {

           this.hasAnimate = true

         },

        /** * 去除动画效果 * @return {Promise} 返回promise */ r

        emoveAnimate() {

           return new Promise((resolve) => {

            this.hasAnimate = false resolve()

           })

         },

         /** * 显示动画loading */

         show() {

           this.isShow = true

         },

        /** * 隐藏动画loading */

         hide() {

          this.isShow = false

         },

       },

    }

    </script>

    <style lang="stylus" rel="stylesheet/stylus" scope>

       .loadings {

        position: fixed;

         100%;

        height: 100%;

         top: 0;

         left: 0;

        background: transparent;

         &__loader {

           position absolute

           top 50%

           left 50%

           transform translate3d(-50%,-50%,0)

           &__dot {

             width 40px

             height 40px

             background #3ac

             border-radius 100%

             display inline-block

             animation slide 1s infinite

             margin-right: 6px;

             for index in (1..5) {

               &:nth-child({index}) {

                 animation-delay (0.2 + 0.1s * index)

                 // background green(#ce2424, (50 * index))

                 background lighten(#ce2424, (index * 6))

               }

             }

           }

        }

       }

      @keyframes slide

        0%

           transform scale(1)

        50%

          opacity .3 transform scale(2)

        100%

          transform scale(1)

        .opacity {

          &-enter-active, &-leave-active {

            transition: all 0.6s

          }

          &-enter, &-leave-active {

            opacity: 0

          }

         }

    </style>

    这时如果你将其注册为全局组件,也是可以使用的,但是前面我们说过,这样使用非常不优雅

    然后我们将其做成插件

    // my-project/src/plugin/loading/index.js
    import Loading from './loading.vue'

    export default {
      /**
       * 每个插件都有的install方法,用于安装插件
       * @param {Object} Vue - Vue类
       * @param {Object} [pluginOptions] - 插件安装配置
       */
      install(Vue, pluginOptions = {}) {
        // 创建"子类"方便挂载
        const VueLoading = Vue.extend(Loading)
        let loading = null

        /**
         * 初始化并显示loading
         * @returns {Promise} Promise实例
         */
        function $loading() {
          return new Promise((resolve) => {

         // 第一次调用

         if (!loading) {

           loading = new VueLoading()

           // 手动创建一个未挂载的实例

           loading.$mount()

           // 挂载

          document.querySelector(pluginOptions.container || 'body').appendChild(loading.$el)

         }

        // 显示loading

         loading.show()

         resolve()

       })

      }

     // 定义关闭loading方法

      $loading.end = (noAnimate = false) => {

          return new Promise((resolve) => {

       if (!loading || !loading.isShow) {

         resolve()

         return

       }

       // 首页判断是否在关闭时需要动画

       if (noAnimate) {

       // 默认只在此次行为下移除动画,之后的行为仍有动画

         loading.removeAnimate().then(() => {

           loading.opemAnimate()

         })

        }

       loading.hide()

      })

     }

     Vue.loading = Vue.prototype.$loading = $loading

    },

    }

    然后我们在入口文件app.js中引入并且安装插件就可以了:

    ···
    import Vue from 'vue'
    import VueLoading from './loading'
    ···

    ···
    Vue.use(VueLoading, {
      container: '.app',
    })
    ···

    接下来可以在你任意想要的地方执行this.$loading()loadingthis.$loading.end()就可以关闭咯

    不信试试~

  • 相关阅读:
    Linux编译工具:gcc入门
    Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程
    Socket编程实践(2) Socket API 与 简单例程
    Socket编程实践(1) 基本概念
    数据结构图文解析之:二分查找及与其相关的几个问题解析
    数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现
    [CG编程] 基本光照模型的实现与拓展以及常见光照模型解析
    郑重声明!本博客内容皆为原创且首发于博客园
    【原创】面试官:谈谈你对mysql联合索引的认识?
    【原创】为什么Mongodb索引用B树,而Mysql用B+树?
  • 原文地址:https://www.cnblogs.com/starrk-01/p/8004166.html
Copyright © 2011-2022 走看看