经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
Vue自定义指令directive的使用方法分享
来源:jb51  时间:2023/4/14 9:17:40  对本文有异议

1. 一个指令定义对象可以提供如下几个钩子函数(均为可选)

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。

update:只要当前元素不被移除,其他操作几乎都会触发这2个生命周期,先触发update后触发componentUpdate。虚拟DOM什么时候更新:只要涉及到元素的隐藏、显示(display)值的改变、内容的改变等都会触发虚拟DOM更新.

componentUpdated:组件更新

unbind:当使用指令的元素被卸载的时候会执行,就是当前元素被移除的时候,只调用一次

Vue.directive 内置了五个钩子函数 :

bind(绑定触发)、inserted(插入触发)、update(更新触发)、componentUpdated(组件更新触发)和unbind(解绑触发)函

  1. // 注册
  2. Vue.directive('my-directive',{
  3. bind: function () {},
  4. inserted: function () {},
  5. update: function () {},
  6. componentUpdated: function () {},
  7. unbind: function() {}
  8. })

2.指令钩子函数会被传入以下参数

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 来进行。

3.使用自定义指令场景的示例

drag.js

  1. import Vue from 'vue'
  2. import { Message } from 'element-ui';
  3.  
  4.  
  5. // 自定义指令示例1:弹窗拖拽
  6. Vue.directive('dialogDrag',{
  7. bind(el,binding,vnode,oldVnode){
  8. const dialogHeader = el.querySelector('.el-dialog__header');
  9. const dialogDom = el.querySelector('.el-dialog');
  10. dialogHeader.style.cursor = 'move'
  11.  
  12. /**
  13. * 不同浏览器获取行内样式属性
  14. * ie浏览器: dom元素.currentStyle
  15. * 火狐浏览器:window.getComputedStyle(dom元素, null)
  16. */
  17. const sty = dialogDom.currentStyle || window.getComputedStyle(dialogDom, null)
  18.  
  19. dialogHeader.onmousedown = (e) => {
  20. //按下鼠标,获取点击的位置 距离 弹窗的左边和上边的距离
  21. //点击的点距离左边窗口的距离 - 弹窗距离左边窗口的距离
  22. const distX = e.clientX - dialogHeader.offsetLeft;
  23. const distY = e.clientY - dialogHeader.offsetTop;
  24.  
  25. //弹窗的left属性值和top属性值
  26. let styL, styT
  27.  
  28. //注意在ie中,第一次获取到的值为组件自带50%,移动之后赋值为Px
  29. if(sty.left.includes('%')){
  30. styL = +document.body.clientWidth * (+sty.left.replace(/%/g,'') / 100)
  31. styT = +document,body.clientHeight * (+sty.top.replace(/%/g,'') / 100)
  32. }else{
  33. styL = +sty.left.replace(/px/g,'');
  34. styT = +sty.top.replace(/px/g,'');
  35. }
  36.  
  37. document.onmousemove = function(e) {
  38. //通过事件委托,计算移动距离
  39. const l = e.clientX - distX
  40. const t = e.clientY - distY
  41.  
  42. //移动当前的元素
  43. dialogDom.style.left = `${l + styL}px`
  44. dialogDom.style.top = `${t + styT}px`
  45. }
  46.  
  47. document.onmouseup = function(e){
  48. document.onmousemove = null
  49. document.onmouseup = null
  50. }
  51. }
  52. }
  53. })
  54.  
  55. //自定义指令示例2:v-dialogDragWidth 可拖动弹窗宽度(右侧边)
  56. Vue.directive('dragWidth',{
  57. bind(el) {
  58. const dragDom = el.querySelector('.el-dialog');
  59. const lineEl = document.createElement('div');
  60. lineEl.style = 'width: 5px; background: inherit; height: 80%; position: absolute; right: 0; top: 0; bottom: 0; margin: auto; z-index: 1; cursor: w-resize;';
  61. lineEl.addEventListener('mousedown',
  62. function (e) {
  63. // 鼠标按下,计算当前元素距离可视区的距离
  64. const disX = e.clientX - el.offsetLeft;
  65. // 当前宽度
  66. const curWidth = dragDom.offsetWidth;
  67. document.onmousemove = function (e) {
  68. e.preventDefault(); // 移动时禁用默认事件
  69. // 通过事件委托,计算移动的距离
  70. const l = e.clientX - disX;
  71. if(l > 0){
  72. dragDom.style.width = `${curWidth + l}px`;
  73. }
  74. };
  75. document.onmouseup = function (e) {
  76. document.onmousemove = null;
  77. document.onmouseup = null;
  78. };
  79. }, false);
  80. dragDom.appendChild(lineEl);
  81. }
  82. })
  83.  
  84. // 自定义指令示例3:v-dialogDragWidth 可拖动弹窗高度(右下角)
  85. Vue.directive('dragHeight',{
  86. bind(el) {
  87. const dragDom = el.querySelector('.el-dialog');
  88. const lineEl = document.createElement('div');
  89. lineEl.style = 'width: 6px; background: inherit; height: 10px; position: absolute; right: 0; bottom: 0; margin: auto; z-index: 1; cursor: nwse-resize;';
  90. lineEl.addEventListener('mousedown',
  91. function(e) {
  92. // 鼠标按下,计算当前元素距离可视区的距离
  93. const disX = e.clientX - el.offsetLeft;
  94. const disY = e.clientY - el.offsetTop;
  95. // 当前宽度 高度
  96. const curWidth = dragDom.offsetWidth;
  97. const curHeight = dragDom.offsetHeight;
  98. document.onmousemove = function(e) {
  99. e.preventDefault(); // 移动时禁用默认事件
  100. // 通过事件委托,计算移动的距离
  101. const xl = e.clientX - disX;
  102. const yl = e.clientY - disY
  103. dragDom.style.width = `${curWidth + xl}px`;
  104. dragDom.style.height = `${curHeight + yl}px`;
  105. };
  106. document.onmouseup = function(e) {
  107. document.onmousemove = null;
  108. document.onmouseup = null;
  109. };
  110. }, false);
  111. dragDom.appendChild(lineEl);
  112. }
  113. })
  114.  
  115. // 自定义指令示例4:图片加载前填充背景色
  116. Vue.directive('imgUrl',function(el,binding){
  117. var color=Math.floor(Math.random()*1000000);//设置随机颜色
  118. el.style.backgroundColor='#'+color;
  119. var img=new Image();
  120. img.src=binding.value;// -->binding.value指的是指令后的参数
  121. img.onload=function(){
  122. el.style.backgroundColor='';
  123. el.src=binding.value;
  124. }
  125. })
  126.  
  127. // 自定义指令示例5:输入框聚焦
  128. Vue.directive("focus", {
  129. // 当被绑定的元素插入到 DOM 中时……
  130. inserted (el) {
  131. // 聚焦元素
  132. el.querySelector('input').focus()
  133. },
  134. });
  135.  
  136. // 自定义指令示例6:设置防抖自定义指令
  137. Vue.directive('throttle', {
  138. bind: (el, binding) => {
  139. let setTime = binding.value; // 可设置防抖时间
  140. if (!setTime) { // 用户若不设置防抖时间,则默认2s
  141. setTime = 1000;
  142. }
  143. let cbFun;
  144. el.addEventListener('click', event => {
  145. if (!cbFun) { // 第一次执行
  146. cbFun = setTimeout(() => {
  147. cbFun = null;
  148. }, setTime);
  149. } else {
  150. /*如果多个事件监听器被附加到相同元素的相同事件类型上,当此事件触发时,
  151. 它们会按其被添加的顺序被调用。如果在其中一个事件监听器中执行 stopImmediatePropagation() ,那么剩下的事件监听器都不会被调用*/
  152. event && event.stopImmediatePropagation();
  153. }
  154. }, true);
  155. },
  156. });
  157.  
  158. // 自定义指令示例7:点击按钮操作频繁给出提示
  159. Vue.directive('preventReClick', {
  160. inserted: function (el, binding) {
  161. el.addEventListener('click', () => {
  162. if (!el.disabled) {
  163. el.disabled = true
  164. Message.warning('操作频繁')
  165. setTimeout(() => {
  166. el.disabled = false
  167. //可设置时间
  168. }, binding.value || 3000)
  169. }
  170. })
  171. }
  172. })

main.js中引入文件:

  1. import '@/assets/js/drag.js'

页面使用:

  1. <template>
  2. <div>
  3. <el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button>
  4. <div style="display:flex">
  5. <img v-imgUrl="url"></img>
  6. <img v-imgUrl="url"></img>
  7. <img v-imgUrl="url"></img>
  8. <img v-imgUrl="url"></img>
  9. <img v-imgUrl="url"></img>
  10. <img v-imgUrl="url"></img>
  11. <img v-imgUrl="url"></img>
  12. <img v-imgUrl="url"></img>
  13. </div>
  14. <div>
  15. <el-input placeholder="请选择日期" suffix-icon="el-icon-date" v-model="input1"></el-input>
  16. <el-input v-focus placeholder="请输入内容" prefix-icon="el-icon-search" v-model="input2"></el-input>
  17. </div>
  18.  
  19. <div>
  20. <el-button type="danger" v-throttle @click="throttleBtn">危险按钮</el-button>
  21. <el-button @click="submitForm()">创建</el-button>
  22. </div>
  23.  
  24. <el-dialog title="提示" v-dialogDrag v-dragWidth v-dragHeight :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
  25. <span>这是一段信息</span>
  26. <span slot="footer" class="dialog-footer">
  27. <el-button @click="dialogVisible = false">取 消</el-button>
  28. <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
  29. </span>
  30. </el-dialog>
  31. </div>
  32. </template>
  33.  
  34. <script>
  35.  
  36. export default {
  37.  
  38. data() {
  39. return {
  40. dialogVisible: false,
  41. url:'//www.baidu.com/img/flexible/logo/pc/result.png',
  42. input1: '',
  43. input2: '',
  44. }
  45. },
  46. methods: {
  47. handleClose(done) {
  48. console.log('弹窗打开')
  49. },
  50. throttleBtn(){
  51. console.log('我的用来测试防抖的按钮')
  52. },
  53. submitForm(){
  54. this.$message.error('Message 消息提示每次只能1个');
  55. }
  56. },
  57. }
  58. </script>
  59. <style>
  60. img{
  61. width: 100px;
  62. height: 100px;
  63. }
  64. </style>

看下效果吧:

首先进入页面,

1.第二个输入框会鼠标聚焦,

2.点击按钮,会有防止重复点击

3.图片加载前有默认背景色

4.弹窗 可以随处移动。右边可拖拽变宽,右下角可以整体变大

到此这篇关于Vue自定义指令directive的使用方法分享的文章就介绍到这了,更多相关Vue自定义指令directive内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号