前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue全局指令:如何添加全局指令?(附2个常用自定义指令)

Vue全局指令:如何添加全局指令?(附2个常用自定义指令)

作者头像
Javanx
发布2019-09-04 15:27:15
3.4K0
发布2019-09-04 15:27:15
举报
文章被收录于专栏:web秀web秀

Vue全局指令:如何添加全局指令?(附2个常用自定义指令)

前言

前面有专门的文字,讲过Vue指令,以及如何使用指令,今天就来讲讲如何添加全局指令,并且附上2个非常适用的例子。

《Vue如何创建自定义指令?》

Vue全局指令:如何添加全局指令?(附2个常用自定义指令)
Vue全局指令:如何添加全局指令?(附2个常用自定义指令)

如何添加全局指令?

在上面文章中,提到过一种方法,在main.js(入口JS文件)中引入你已经写好的指令文件,可以省略文件后缀:

代码语言:javascript
复制
// main.js
import focus from 'xxx/directive'

如果你有多个指令文件了?怎么引入?

代码语言:javascript
复制
Vue.use((Vue) => {
  ((requireContext) => {
    const arr = requireContext.keys().map(requireContext);
    (arr || []).forEach((directive) => {
      directive = directive.__esModule && directive.default ? directive.default : directive;
      Object.keys(directive).forEach((key) => {
        Vue.directive(key, directive[key]);
      });
    });
  })(require.context('../directives', false, /^\.\/.*\.js$/));
});

这里用到了require.context函数,require.context是webpack中,用来创建自己的(模块)上下文。 require.context函数接收三个参数:

1、要搜索的文件夹目录 2、是否还应该搜索它的子目录 3、以及一个匹配文件的正则表达式

我们搜索directives目录下的所有js文件,遍历装载指令。

下面我们来看看2个实用的自定义指令。

Vue全局指令:如何添加全局指令?(附2个常用自定义指令)
Vue全局指令:如何添加全局指令?(附2个常用自定义指令)

vue非本元素点击事件指令

这个指令的的作用是什么?

比如:一个按钮点击后弹出一个浮层,然后点击按钮外的所有事件,都关闭浮层。

代码语言:javascript
复制
export default {
  clickOut: {
    // 初始化指令
    bind(el, binding, vnode) {
      function clickHandler(e) {
        // 这里判断点击的元素是否是本身,是本身,则返回
        if (el.contains(e.target)) {
          return false;
        }
        // 判断指令中是否绑定了函数
        if (binding.expression) {
          // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
          binding.value(e);
        }
      }
      // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
      el.__vueClickOutside__ = clickHandler;
      document.addEventListener('click', clickHandler);
    },
    update() {},
    unbind(el, binding) {
      // 解除事件监听
      document.removeEventListener('click', el.__vueClickOutside__);
      delete el.__vueClickOutside__;
    }
  }
}

然后,在main.js中这个指令,就可以使用了。

代码语言:javascript
复制
<span @click="showDialog" v-click-out="hideDialog">点击我打开否则关闭</span>

vue倒计时指令

代码语言:javascript
复制
var toZeroStr = (val, num = 2) => {
  num = num || 2;
  return (new Array(num)
      .join('0') + val)
    .slice(-num);
}
var milliseconds2HMS = (diff) => {
  const millisecond = diff % 1000;
  diff = diff - millisecond;
  return seconds2HMS(diff / 1000);
}
var seconds2HMS = (diff) => {
  const seconds = diff % 60;
  const minutes = (diff - seconds) % 3600;
  // const hours = (diff - minutes - seconds) % 86400;
  const hours = diff - minutes - seconds;
  return [hours / 3600, minutes / 60, seconds];
}

export default {
  // 倒计时
  countdown: {
    bind(el, binding, vnode) {
      const { componentOptions, data } = vnode;
      const listeners = componentOptions ? componentOptions.listeners : null;
      const on = data ? data.on : null;
      const events = listeners ? listeners : on ? on : null;
      if (events && typeof events === 'object' && Object.keys(events).length) {
        binding.customListeners = events;
      }
    },

    inserted(el, binding, vnode) {
      let val = +binding.value;
      if (!val) {
        return;
      }
      const formatter = vnode.data.attrs.formatter;
      let timer = null;
      window.clearInterval(el.timer);
      const tFunction = () => {
        val -= 1000;
        let instance = milliseconds2HMS(val);
        if (val <= 0) {
          if (timer) {
            window.clearInterval(timer);
            timer = null;
            if (binding.customListeners) {
              binding.customListeners.complete && binding.customListeners.complete();
            }
          }
          el.innerHTML = '0';
          return;
        }
        el.innerHTML = formatter.replace(/(HH.+)(mm.+)(ss.+)/g, (str, $1, $2, $3) => {
          return str.replace(new RegExp($1, 'g'), !instance[0] ? '' : $1.replace(/HH/g, toZeroStr(instance[0])))
            .replace(new RegExp($2, 'g'), !instance[0] && !instance[1] ? '' : $2.replace(/mm/g, toZeroStr(instance[1])))
            .replace(new RegExp($3, 'g'), !instance[1] && !instance[2] ? '' : $3.replace(/ss/g, toZeroStr(instance[2])));
        });
      };
      tFunction();
      timer = window.setInterval(tFunction, 1000);
      el.timer = timer;
    },

    update(el, binding, vnode) {
      if (binding.oldValue !== binding.value) {
        window.clearInterval(el.timer);
        binding.def.inserted(el, binding, vnode);
      }
    },

    unbind(el, binding, vnode) {
      window.clearInterval(el.timer);
      el.timer = null;
      delete el.timer;
      const customListeners = binding.customListeners;
      if (customListeners) {
        delete binding.customListeners;
      }
    }
  }
}

使用方法

代码语言:javascript
复制
<span v-countdown="10000" formatter='HH小时mm分ss秒'></span>

这里的v-countdown参数就是剩余秒数,如果你只有2个时间(起始结束时间),需要先行计算;formatter参数是时间格式。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年5月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 如何添加全局指令?
  • vue非本元素点击事件指令
  • vue倒计时指令
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档