loading效果很常见,常见到我们任何一个项目中,都可以见到他的身影。今天就以loading作为切入口,唠叨一下vuejs的插件的写法。

  看vuejs官方文档关于插件的说明,关于使用插件和写插件,Vue插件基本上都躲不开以下几种方案: 

  1. 添加全局方法或者属性,如: vue-custom-element

  2. 添加全局资源:指令/过滤器/过渡等,如 vue-touch

  3. 通过全局 mixin 方法添加一些组件选项,如: vue-router

  4. 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。

  5. 一个库,提供自己的 API,同时提供上面提到的一个或多个功能,如 vue-router

  我们以loading效果为例,添加一个全局自定义指令的方式写一个插件。使用方式如: 

  1. <div v-loading="loading"></div>

  依赖loading值,展示或者隐藏loading效果。loading值默认为false,不展示loading效果。

  loading效果的模板其实很简单,甚至可以用唯一一个div标签完成,这里我们不强求怎么写loading模板,我们将模板定义在Loading.vue文件内。

  在loading.js文件内真正写插件:

  首先看一下Vue.use这个方法:

  1. 安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。

  也就是说我们在loading.js文件中export一个对象出去的时候,如果该对象是普通的对象,则需要在对象中添加一个install的方法,而如果导出一个函数对象,可以直接导出该函数。

  就以当前的loading举例说明:

  如果导出一个对象:

  1. export default {
  2. vm: null,
  3. install: Vue => {
  4. Vue.directive(Loading.name, {
  5. // 真正的实现逻辑
  6. })
  7. },
  8. ...
  9. }

  而如果导出是一个函数,我们可以这么写:

  1. export default Vue => {
  2. Vue.directive(Loading.name, {
  3. // 真正的实现逻辑
  4. })
  5. }

  仔细观察一下,发现我们可以将install方法的函数体直接导出当做use的参数。

  我们这里就以对象方式导出,主要目的是留一个vm属性,用于保存生成的loading节点,方便删除该节点。

  在刚刚写这个插件的时候,不是插件不会写,恰恰是自定义指令的钩子函数使用不当,导致问题的产生。我们需要依赖指令的binding.value值来展示或者隐藏loading效果。基本上尝试了所有的钩子函数后,发现只有update是在所在的组件 VNode 更新时调用,也就是说binding.value的值发生变化,在update内部更新dom。

  1. update (el, binding) {
  2. const ele = window.getComputedStyle(el, null)
  3. // 添加判断,如果当前元素的高度小于60 则loading固定在整个屏幕中间 否则固定在当前元素中间
  4. LoadingComp.vm.$el.style.position = !binding.modifiers.fixed && (parseInt(ele['height']) < 60 ? 'fixed' : 'absolute')
  5. binding.value ? el.appendChild(LoadingComp.vm.$el) : el.removeChild(LoadingComp.vm.$el)
  6. }

  需要稍作解释的时候,我们有时候绑定的v-loading的dom节点高度在完全没有数据的时候,可能完全没有高度可言,那么这里就将loading的position设置为fixed,固定在屏幕中央。这里可以自行定义是否需要该判断条件。

  1.  binding.value ? el.appendChild(LoadingComp.vm.$el) : el.removeChild(LoadingComp.vm.$el)

  这么一句,就是添加和删除当前的loading节点,有点类似于v-if的处理效果。

  这里还缺少生成loading的DOM节点这一过程,是因为我认为其他的过程只要生成一次就可以了,而不会随着binding.value的值变化发生任何变化。所以需要在钩子函数inserted内实现: 

  1. inserted (el, binding) {
  2. const elem = window.getComputedStyle(el, null)
  3. el.style.position = elem['position'] === 'static' && 'relative'
  4. LoadingComp.vm = new LoadingConstructor().$mount()
  5. // 如果带修饰符fixed loading固定在屏幕中间
  6. let val = binding.modifiers.fixed && 'fixed'
  7. LoadingComp.vm.$el.style.position = val && val
  8. }

  主要实现的是,当前绑定v-loading的元素是否有定位,如果没有定位属性,则添加position:"relative"属性。并同时生成loading对象,注意这里仅仅是生成,并没有挂载到文档中。

  添加的一行注释,主要多实现了一个功能,就是如果用户就非得相对整个屏幕固定loading,那么可以使用v-loading.fixed="loading"来达成这一效果。

  这里其实可以引申出来,如果loading需要遮罩层的效果的话,也可以以类似的方法实现。

  看看完整的代码吧!

  1. import Vue from 'vue'
  2. import Loading from './Loading.vue'
  3. const LoadingConstructor = Vue.extend(Loading)
  4. const LoadingComp = {
  5. vm: null,
  6. install: Vue => {
  7. Vue.directive(Loading.name, {
  8. inserted (el, binding) {
  9. const elem = window.getComputedStyle(el, null)
  10. el.style.position = elem['position'] === 'static' && 'relative'
  11. LoadingComp.vm = new LoadingConstructor().$mount()
  12. // 如果带修饰符fixed loading固定在屏幕中间
  13. let val = binding.modifiers.fixed && 'fixed'
  14. LoadingComp.vm.$el.style.position = val && val
  15. },
  16. update (el, binding) {
  17. const ele = window.getComputedStyle(el, null)
  18. // 添加判断,如果当前元素的高度小于60 则loading固定在整个屏幕中间 否则固定在当前元素中间
  19. LoadingComp.vm.$el.style.position = !binding.modifiers.fixed && (parseInt(ele['height']) < 60 ? 'fixed' : 'absolute')
  20. binding.value ? el.appendChild(LoadingComp.vm.$el) : el.removeChild(LoadingComp.vm.$el)
  21. }
  22. })
  23. }
  24. }
  25.  
  26. export default LoadingComp

  

vue2.0插件--loading的更多相关文章

  1. vue2.0插件

    1.better-scroll 参考网址:https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/ better-scroll 是什么 firs ...

  2. 干货分享:vue2.0做移动端开发用到的相关插件和经验总结(2)

    最近一直在做移动端微信公众号项目的开发,也是我首次用vue来开发移动端项目,前期积累的移动端开发经验较少.经过这个项目的锻炼,加深了对vue相关知识点的理解和运用,同时,在项目中所涉及到的微信api( ...

  3. vue2.0做移动端开发用到的相关插件和经验总结

    最近一直在做移动端微信公众号项目的开发,也是我首次用vue来开发移动端项目,前期积累的移动端开发经验较少.经过这个项目的锻炼,加深了对vue相关知识点的理解和运用,同时,在项目中所涉及到的微信api( ...

  4. vue-swiper 基于Vue2.0开发 轻量、高性能轮播插件

    vue-swiper 基于 Vue2.0 开发,基本满足大部分功能 轻量.高性能轮播插件.目前支持 无缝衔接自动轮播.无限轮播.手势轮播 没有引入第三方库,原生 js 封装,打包之后只有 8.2KB ...

  5. vue2.0实现倒计时的插件(时间戳 刷新 跳转 都不影响)

    我发现好多倒计时的插件,刷新都会变成从头再来,于是自己用vue2.0写了一个,测试通过,直接上代码 如下是组件代码: <template> <span :endTime=" ...

  6. vue2.0 移动端,下拉刷新,上拉加载更多 插件

    本人正在基于 vue2.0 + webpack + es6 搭建前端架构,整理了部分插件,下面这个是下拉更新 上拉更多的,挺好用的,分享给大家. 直接上代码,不懂的多看几遍,下面我换会告诉大家如何使用 ...

  7. Vue2.0 分页插件pagination使用详细说明

    Vue2.0 分页pagination使用 插件下载地址:Vue_Pagination 插件描述:基于jQuery的分页插件大家都用过很多了吧,今天分享一下基于Vue的分页插件pagination.j ...

  8. vue2.0做移动端开发用到的相关插件和经验总结1.0

    最近在用vue2.0做微信公众号相关的前端开发,经过这次开发实践,现将项目中用到的相关比较实用的插件及遇到的相关问题进行整理,希望和大家共同交流...... cssrem:一个CSS值转REM的VSC ...

  9. vue2.0 移动端,下拉刷新,上拉加载更多插件,修改版

    在[实现丰盛]的插件基础修改[vue2.0 移动端,下拉刷新,上拉加载更多 插件], 1.修改加载到尾页面,返回顶部刷新数据,无法继续加重下一页 2.修改加载完成文字提示 原文链接:http://ww ...

随机推荐

  1. 本博客不再更新和维护,后续文章会在掘金和GitHub发布,感兴趣的小伙伴可以掘金搜索王振宇,谢谢

    本博客不再更新和维护,后续文章会在掘金和GitHub发布,感兴趣的小伙伴可以掘金搜索王振宇,谢谢

  2. Sails -初级学习配置

    新建一个命名为sails的文件夹1.安装 npm -g install sails || cnpm -g install sails 注意:安装必须是全局安装 cnpm install sails - ...

  3. 【bug记录】OS Lab3 踩坑记

    OS Lab3 踩坑记 Lab3在之前Lab2的基础上,增加了进程建立.调度和中断异常处理.其中测试包括进程建立以及进程调度部分. 由于是第一次做bug记录,而且是调试完bug后再做的记录,所以导致记 ...

  4. 为什么使用消息队列? 消息队列有什么优点和缺点? Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景?

    https://blog.csdn.net/Iperishing/article/details/86674084

  5. 【javaScript基础】异常处理

             理解异常在javaScript面向对象编程是非常重要的,异常是一种非常强大的处理错误的方式. 错误处理          首先我们来看一个有问题的代码: nonexistant(); ...

  6. Win10无法访问网上邻居电脑共享的文件夹怎么办

    Win10无法访问网上邻居电脑共享的文件夹怎么办 现在许多电脑上装的都是Win系统,Win10无法访问网上邻居电脑共享的文件夹怎么办呢?下面小编为大家介绍下解决的方法吧! 1点击桌面上的“此电脑”图标 ...

  7. C# EnumHelper Enum的值,Description,ToString()的相互转换

    首先定义枚举类型,如下: /// <summary> /// 板块 /// </summary> public enum Plate {         [Descriptio ...

  8. Devexpress之LayoutControl的使用及其控件布局设计

    引言 Devexpress给我们提供了更加美观.更加丰富控件,但在学习和使用的同时经常会遇到诸多麻烦.今天在使用Devexpress的LayoutControl控件进行界面控件的布局设计时遇到了如下的 ...

  9. Python之 操作 MySQL 数据库

    什么是MySQLdb? MySQLdb 是用于Python链接Mysql数据库的接口,它实现了 Python 数据库 API 规范 V2.0,基于 MySQL C API 上建立的. 安装 Pytho ...

  10. centos7 时间自动同步

    设置开机自动同步Internet时间,并作定时同步任务1.修改时区 rm -rf /etc/localtime ln -s /usr/share/zoneinfo/Asia/Shanghai /etc ...