【vue】vue 自定义指令directive的使用场景:_vue directives-程序员宅基地

技术标签: 前端  Vue框架  vue.js  javascript  


一、 Vue.directive钩子函数(均为可选)

Vue.directive 内置了五个钩子函数 :
bind(绑定触发)、inserted(插入触发)、update(更新触发)、componentUpdated(组件更新触发)和unbind(解绑触发)

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
update:只要当前元素不被移除,其他操作几乎都会触发这2个生命周期,先触发update后触发componentUpdate。虚拟DOM什么时候更新:只要涉及到元素的隐藏、显示(display)值的改变、内容的改变等都会触发虚拟DOM更新.
componentUpdated:组件更新
unbind:当使用指令的元素被卸载的时候会执行,就是当前元素被移除的时候,只调用一次

// 注册
Vue.directive('my-directive',{
    
  bind:  function () {
    },         
  inserted: function () {
    },
  update: function () {
    },
  componentUpdated: function () {
    },
  unbind: function() {
    }
})
二、指令钩子函数会被传入以下参数

el:指定所绑定的元素,可以用来直接操作DOM
binding:一个对象,包含以下属性:
name:指令名,不包含前缀v-
value:指令的绑定值,例如:v-my-directive="1+1"中,绑定值为2
oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子中可用,无论值是否改变都可用。
expression: 绑定值的字符串形式。 例如 v-my-directive=“1 + 1” , expression 的值是 “1 + 1”。
arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 “foo”。
modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是{ foo: true, bar: true }。
vnode: Vue 编译生成的虚拟节点
oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
vnode:vue编译生成的虚拟节点
oldVnode:上一个虚拟节点,仅在update和componentUpdated钩子中可用
除了el之外,其他参数都应该是只读的,不能修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

三、使用自定义指令场景的示例
【1】drag.js
import Vue from 'vue'
import {
     Message } from 'element-ui';


// 自定义指令示例1:弹窗拖拽
Vue.directive('dialogDrag',{
    
    bind(el,binding,vnode,oldVnode){
    
        const dialogHeader = el.querySelector('.el-dialog__header');
        const dialogDom = el.querySelector('.el-dialog');
        dialogHeader.style.cursor = 'move'

        /**
         * 不同浏览器获取行内样式属性
         * ie浏览器:       dom元素.currentStyle
         * 火狐浏览器:window.getComputedStyle(dom元素, null)
        */
        const sty = dialogDom.currentStyle || window.getComputedStyle(dialogDom, null)

        dialogHeader.onmousedown = (e) => {
    
            //按下鼠标,获取点击的位置 距离 弹窗的左边和上边的距离
            //点击的点距离左边窗口的距离 - 弹窗距离左边窗口的距离
            const distX = e.clientX - dialogHeader.offsetLeft;
            const distY = e.clientY - dialogHeader.offsetTop;

            //弹窗的left属性值和top属性值
            let styL, styT

            //注意在ie中,第一次获取到的值为组件自带50%,移动之后赋值为Px
            if(sty.left.includes('%')){
    
                styL = +document.body.clientWidth * (+sty.left.replace(/%/g,'') / 100)
                styT = +document,body.clientHeight * (+sty.top.replace(/%/g,'') / 100)
            }else{
    
                styL = +sty.left.replace(/px/g,'');
                styT = +sty.top.replace(/px/g,'');
            }

            document.onmousemove = function(e) {
    
                //通过事件委托,计算移动距离
                const l = e.clientX - distX
                const t = e.clientY - distY

                //移动当前的元素
                dialogDom.style.left = `${
     l + styL}px`
                dialogDom.style.top = `${
     t + styT}px`
            }

            document.onmouseup = function(e){
    
                document.onmousemove = null
                document.onmouseup = null
            }
        }
    }
})

//自定义指令示例2:v-dialogDragWidth 可拖动弹窗宽度(右侧边)
Vue.directive('dragWidth',{
    
  bind(el) {
    
      const dragDom = el.querySelector('.el-dialog');
      const lineEl = document.createElement('div');
      lineEl.style = 'width: 5px; background: inherit; height: 80%; position: absolute; right: 0; top: 0; bottom: 0; margin: auto; z-index: 1; cursor: w-resize;';
      lineEl.addEventListener('mousedown',
          function (e) {
    
              // 鼠标按下,计算当前元素距离可视区的距离
              const disX = e.clientX - el.offsetLeft;
              // 当前宽度
              const curWidth = dragDom.offsetWidth;
              document.onmousemove = function (e) {
    
                  e.preventDefault(); // 移动时禁用默认事件
                  // 通过事件委托,计算移动的距离
                  const l = e.clientX - disX;
                  if(l > 0){
    
                      dragDom.style.width = `${
     curWidth + l}px`;
                  }
              };
              document.onmouseup = function (e) {
    
                  document.onmousemove = null;
                  document.onmouseup = null;
              };
          }, false);
      dragDom.appendChild(lineEl);
  }
})

// 自定义指令示例3:v-dialogDragWidth 可拖动弹窗高度(右下角)
Vue.directive('dragHeight',{
    
  bind(el) {
    
      const dragDom = el.querySelector('.el-dialog');
      const lineEl = document.createElement('div');
      lineEl.style = 'width: 6px; background: inherit; height: 10px; position: absolute; right: 0; bottom: 0; margin: auto; z-index: 1; cursor: nwse-resize;';
      lineEl.addEventListener('mousedown',
          function(e) {
    
              // 鼠标按下,计算当前元素距离可视区的距离
              const disX = e.clientX - el.offsetLeft;
              const disY = e.clientY - el.offsetTop;
              // 当前宽度 高度
              const curWidth = dragDom.offsetWidth;
              const curHeight = dragDom.offsetHeight;
              document.onmousemove = function(e) {
    
                  e.preventDefault(); // 移动时禁用默认事件
                  // 通过事件委托,计算移动的距离
                  const xl = e.clientX - disX;
                  const yl = e.clientY - disY
                  dragDom.style.width = `${
     curWidth + xl}px`;
                  dragDom.style.height = `${
     curHeight + yl}px`;
              };
              document.onmouseup = function(e) {
    
                  document.onmousemove = null;
                  document.onmouseup = null;
              };
          }, false);
      dragDom.appendChild(lineEl);
  }
})

// 自定义指令示例4:图片加载前填充背景色
Vue.directive('imgUrl',function(el,binding){
    
    var color=Math.floor(Math.random()*1000000);//设置随机颜色
    el.style.backgroundColor='#'+color;
   
    var img=new Image();
    img.src=binding.value;// -->binding.value指的是指令后的参数
    img.onload=function(){
    
      el.style.backgroundColor='';
      el.src=binding.value;      
    }
  })

// 自定义指令示例5:输入框聚焦
Vue.directive("focus", {
    
    // 当被绑定的元素插入到 DOM 中时……
    inserted (el) {
    
        // 聚焦元素
        el.querySelector('input').focus()
    },
  });

// 自定义指令示例6:设置防抖自定义指令
Vue.directive('throttle', {
    
    bind: (el, binding) => {
    
      let setTime = binding.value; // 可设置防抖时间
      if (!setTime) {
     // 用户若不设置防抖时间,则默认2s
        setTime = 1000;
      }
      let cbFun;
      el.addEventListener('click', event => {
    
        if (!cbFun) {
     // 第一次执行
          cbFun = setTimeout(() => {
    
            cbFun = null;
          }, setTime);
        } else {
    
            /*如果多个事件监听器被附加到相同元素的相同事件类型上,当此事件触发时,
            它们会按其被添加的顺序被调用。如果在其中一个事件监听器中执行 stopImmediatePropagation() ,那么剩下的事件监听器都不会被调用*/
          event && event.stopImmediatePropagation();
        }
      }, true);
    },
  });

// 自定义指令示例7:点击按钮操作频繁给出提示
  Vue.directive('preventReClick', {
    
    inserted: function (el, binding) {
    
      el.addEventListener('click', () => {
    
        if (!el.disabled) {
    
          el.disabled = true
          Message.warning('操作频繁')
          setTimeout(() => {
    
            el.disabled = false
            //可设置时间
          }, binding.value || 3000)
        }
      })
    }
})
【2】main.js中引入文件:
import '@/utils/drag.js'
【3】页面使用:
<template>
  <div>
    <el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button>
    <div style="display:flex">
      <img v-imgUrl="url"></img> 
      <img v-imgUrl="url"></img> 
      <img v-imgUrl="url"></img> 
      <img v-imgUrl="url"></img> 
      <img v-imgUrl="url"></img> 
      <img v-imgUrl="url"></img> 
      <img v-imgUrl="url"></img> 
      <img v-imgUrl="url"></img> 
    </div>
    <div>
      <el-input  placeholder="请选择日期" suffix-icon="el-icon-date"  v-model="input1"></el-input>
      <el-input v-focus placeholder="请输入内容" prefix-icon="el-icon-search" v-model="input2"></el-input>
    </div>

    <div>
      <el-button type="danger" v-throttle @click="throttleBtn">危险按钮</el-button>
      <el-button @click="submitForm()">创建</el-button>
    </div>

    <el-dialog title="提示" v-dialogDrag v-dragWidth v-dragHeight :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
      <span>这是一段信息</span>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>

export default {
    

  data() {
    
    return {
    
      dialogVisible: false,
      url:'//www.baidu.com/img/flexible/logo/pc/result.png',
      input1: '',
      input2: '',
    }
  },
  methods: {
    
    handleClose(done) {
    
      console.log('弹窗打开')  
    },
    throttleBtn(){
    
      console.log('我的用来测试防抖的按钮')
    },
    submitForm(){
    
      this.$message.error('Message 消息提示每次只能1个');
    }
  },
}
</script>
<style>
img{
    
  width: 100px;
  height: 100px;
}
</style>
【4】效果:
第二个输入框会鼠标聚焦,
点击按钮,会有防止重复点击
图片加载前有默认背景色
弹窗 可以随处移动。右边可拖拽变宽,右下角可以整体变大
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_53791978/article/details/130145155

智能推荐

win10使用roLabelimg(可标注旋转矩形)保存带有汉字的label及xml转txt(含文件)_rolabellmg下载-程序员宅基地

文章浏览阅读2.2k次,点赞2次,收藏22次。win10使用roLabelimg保存带有汉字的label(含文件)简介roLabelimg可以标注旋转矩形,虽不太好用,但比不能标注强太多太多,转载请注明出处。文件地址源文件修改&编译将roLabelImg.py中的#!/usr/bin/env python# -*- coding: utf8 -*-更改为#!/usr/bin/env python# -*- coding: utf-8 -*-编译pyrcc5 -o resources.py resources.qrc_rolabellmg下载

对Neo4j导出数据做知识图谱可视化 D3库实现_neo4jd3-程序员宅基地

文章浏览阅读2.5w次,点赞52次,收藏360次。知识图谱可视化 D3库的使用引言Neo4j导出数据引言好久没用D3库作可视化了,现在主要是用百度的echarts库,在项目中做简单的图表太方便了。但像是做关系图其实用echarts也很方便,这次用D3实现主要是复习一下以前做的东西,顺便记录一下。以下是我参考到的实例代码:D3官方图实例参考echarts做关系图实例参考Neo4j导出数据我们先通过Cypher查询将数据从Neo4j中查询出来,Neo4j构建和查询可以参考我上篇博客基于Neo4j的外贸企业关系图谱做企业相似度查询查询后的结果如下_neo4jd3

拓扑空间、距离空间、向量空间和内积空间_拓扑和距离的关系-程序员宅基地

文章浏览阅读7.5k次。拓扑空间是最基本的,是集合+开集构成,这个空间里没有距离。就像人群+关系=社会一样。距离空间=拓扑空间+距离。这个距离的来源主要是定义出来的。距离空间是拓扑空间的一个子集,也可以理解为是一个子概念。同理向量空间又是距离空间的一个子集,子概念。对拓扑向量空间来说,它是一个度量空间当且仅当其有可数局部拓扑基(见Rudin的泛函分析,对一般拓扑空间来说的充要条件还要多一个,这就是NS度量化定理,见Munk_拓扑和距离的关系

dubbo实战之一:准备和初体验,Java进阶-程序员宅基地

文章浏览阅读923次,点赞21次,收藏15次。Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

20来行的Python拼写检查器_拼写检查 专有名词 python-程序员宅基地

文章浏览阅读3.1k次,点赞3次,收藏8次。介绍了一个基于贝叶斯方法的Python写的20来行的拼写检查器_拼写检查 专有名词 python

matlab仿真三相不平衡度,matlab调用openDSS进行三相不平衡潮流计算-程序员宅基地

文章浏览阅读2k次。应用介绍这是使用matlab调用openDSS进行三相不平衡潮流计算过程和方法步骤,OpenDSS是由美国电科院(EPRI)开发的开源配电系统仿真工具。 用户可以在使用COM接口的同时使用OpenDSS仿真任何配电网系统(有关详细信息,请参见OpenDSS手册)。 在这里,OpenDSS使用Matlab COM接口用于配电系统的潮流计算。 以下讲述了从安装到openDSS潮流计算,如何定义各个分布..._opendss matlab安装

随便推点

洛谷3356火星探险问题-程序员宅基地

文章浏览阅读91次。题目链接:火星探险问题这一题类似于深海机器人问题唯一的区别是这一题的资源不再位于边上而位于点上,由于资源只能开采一次所以需要考虑拆点接下来就和那一道问题一样了接下来又是喜闻乐见的输出方案了我们从源点出发,每一次dfs向东走还是向南走,记录一个当前枚举方案时的流量,当某条边的记录流量与原本应当流的流量相同时则说明不能再从这里走,否则就顺着这里向下dfs注意及时return#i..._洛谷 u90034 题目 神秘岛探险

python写一个类600行代码_带你领略算法的魅力,一个600行代码的分词功能实现(二)...-程序员宅基地

文章浏览阅读127次。从大学毕业到工作的开始几年,一直觉得大学期间学的线性代数,离散数学,概率论简直是浪费时间。那时候实际做的代码,大部分都是数据进销存。数据输入到数据库介质中的转换,CS,BS架构都写过一些。总觉得现实生活中的逻辑,基本就是柴米油盐那么点东西,根本不需要复杂的算法。最多用点排序算是最给面子了。真正接触算法的魅力,是在写游戏的时候。那时候写寻路算法,第一次听说A*,不喜欢用别人写好的,于是自己实现了一遍..._python中型游戏600行代码

java智慧农业系统-农业云端农产品仓储子系统_农产品货运客体子系统-程序员宅基地

文章浏览阅读1.9k次。下载地址:https://download.csdn.net/download/kzpqi88/80784670项目介绍:java智慧农业系统-农业云端农产品仓储子系统系统说明:1、主要功能计费配置、仓库配置、基础配置、计费管理、基础资料、仓库管理、月台管理、进货管理、出货管理、退货管理、库内管理、盘点管理、库存查询、PDA功能、分析报表、分析图表、域验证。2、主要流程收货流程,上架流程,移货作业、拣货流程:批量拣货,按单拣货、盘点流程、计费流程。1,开发环境:开发工具:IDEA(强烈_农产品货运客体子系统

总结 XSS 与 CSRF 两种跨站攻击_restclient测试xss-程序员宅基地

文章浏览阅读1k次。在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式。在这个年代, 参数化查询 [1] 已经成了普遍用法,我们已经离 SQL 注入很远了。但是,历史同样悠久的 XSS 和 CSRF 却没有远离我们。由于之前已经对 XSS 很熟悉了,所以我对用户输入的数据一直非常小心。如果输入的时候没有经过 Tidy 之类的过滤,我一定会在模板输出时候全_restclient测试xss

分享一个在线生成微信跳转链接实现微信内跳转浏览器打开URL的工具-程序员宅基地

文章浏览阅读2.5k次。前言现如今微信对第三方推广链接的审核是越来越严格了,域名在微信中分享转发经常会被拦截,一旦被拦截用户就只能复制链接手动打开浏览器粘贴才能访问,要不然就是换个域名再推,周而复始。无论是哪一种情况都会面临一个非常严重的问题,那就是用户体验差,用户量无法有效地累积起来,从而导致推广成本一直在增加,推广效率却无法有明显的提升。所以针对这个问题,特写这篇文章来分享如何正常从微信内访问已..._mailijump

使用Monkey进行Android手机应用的压力测试_monkey压力测试-程序员宅基地

文章浏览阅读547次。由于monkey太过随机,最后根本无法控制,很容易陷于一个页面无法出来,或者陷入某个无关紧要的地方无法出来,导致测试结果并不具有很好的意义。在monkey测试中,由于事件的随机性,使得monkey容易卡在某些简单页面,比如登陆页面这种可操作内容很少的页面。***执行100个伪随机用户事件流,事件间隔为300毫秒: adb shell monkey -p 包名 --throttle 300 100。由于Monkey的随机性,如果Bug是由于事件发生的特定序列产生的,往往很难复现Bug。_monkey压力测试

推荐文章

热门文章

相关标签