当前位置: 首页 > Web前端 > vue.js

Vue自定义指令的一个小例子

时间:2023-03-31 22:48:01 vue.js

学过前端开发的同学应该对ElementUI不陌生,但是在日常开发中,可能有些组件并不能完全满足我们的需求,或者我们想在原有组件的基础上增加一些功能,这时我们需要增加一些不特别的对于小而复杂的东西,使用Vue的自定义指令会很优雅。我们知道ElementUI的el-input组件类型是text。获取textarea时,可以设置show-word-limit属性,显示字数统计。但是我们现在项目使用的ElementUI版本是2.5.21,没有这个属性,暂时不方便我们升级ElementUI版本,产品经理硬要这个小东西,那么让我们看看如何解决这个问题。其实这个小功能很简单,如下手动添加父元素设置定位属性,然后添加span元素设置定位和样式显示动态限长效果,可以实现和新版本的show-word-limit效果一模一样,只是总有点麻烦。每次用到都要做,提取封装组件也不容易,可以考虑用自定义指令做吗?羊毛布?思路最终效果是通过一个命令实现上面的效果,比如和之前相比少了什么?我们需要做什么?1.创建父元素设置定位属性。这一步是显示文本是否位于输入框右下角的关键。2.创建一个span元素,为展示效果设置样式。3.el-input绑定的值的长度填写span元素4.el-input绑定的值的长度每次变化,更新span元素的值的思路就到位了。这不是很复杂。那我们看看这段代码怎么写。实际代码首先创建一个js文件showWordLimit.js,然后导出一个可以注册指令的对象,然后在插入钩子函数的时候,我们会实现第一步,创建一个父元素,并设置定位属性exportdefault{inserted:function(){letwrap=document.createElement('div')wrap.style.position='relative'}}既然是父元素,我们还需要使用这条指令将el-input元素插入到父元素,通过hook的参数来获取dom元素parentNode.replaceChild(wrap,el)wrap.appendChild(el)}}这样第一步就完成了。接下来继续创建一个span元素,设置样式,插入到刚刚创建的父元素中。exportdefault{inserted:function(el){letwrap=document.createElement('div')wrap.style.position='relative'el.parentNode.replaceChild(wrap,el)wrap.appendChild(el)letoSpan=document.createElement('span')oSpan.style.lineHeight=1.5oSpan.style.color='#909399'oSpan.style.position='absolute'oSpan.style.background='#FFF'oSpan.style.fontSize='12px'oSpan.style.bottom='5px'oSpan.style.right='10px'oSpan.innerText='0/30'wrap.appendChild(oSpan)}}注意innerText的值,它应该是一个变量,根据el-input是由value值的长度决定的,这里需要用到动态指令的方法,在使用指令的时候,传入这个值,比如回到showWordLimit.js,如何接收这个值?也可以通过钩子的参数绑定获取。如果不清楚,可以参考Vue官方文档。一篇,写的很清楚,拿到之后,替换掉span元素的值el.parentNode.replaceChild(wrap,el)wrap.appendChild(el)letoSpan=document.createElement('span')oSpan.style.lineHeight=1.5oSpan.style.color='#909399'oSpan.style.position='absolute'oSpan.style.background='#FFF'oSpan.style.fontSize='12px'oSpan.style.bottom='5px'oSpan.style.right='10px'//binding.value等于el使用thisdirective-输入组件值的长度,这里使用的ES6字符串模板拼接itout,在man.js中导入并注册这个指令//main.js如果没有使用vue-cli脚手架,需要找到对应的入口文件导入并注册importshowWordLimitfrom'@/directive/showWordLimit'Vue.directive('limit',showWordLimit)这时候你会发现显示效果的值不会随着输入框内容长度的变化而更新,虽然文本框是通过Length处理的,但是在inserted中,只会执行一次,如果文本框默认长度为10,那么会显示10/30,然后我们编辑内容,长度发生变化,还是10/30,如果你想每次编辑内容时更新显示效果的值,那么你需要用到另外一个钩子函数updateexportdefault{inserted:function(el,binding){letwrap=document.createElement('div')wrap.style.position='relative'el.parentNode.replaceChild(wrap,el)wrap.appendChild(el)让oSpan=document.createElement('span')oSpan.style.lineHeight=1.5oSpan.style。color='#909399'oSpan.style.position='absolute'oSpan.style.background='#FFF'oSpan.style.fontSize='12px'oSpan.style.bottom='5px'oSpan.style.right='10px'//绑定ing.value等于使用该指令的el-input组件的值的长度,此处使用的ES6字符串模板拼接而成oSpan.innerText=`${binding.value}/30`//以便于使用在update生命周期函数中,为了方便获取,添加一个idoSpan.setAttribute('id','oSpan')wrap.appendChild(oSpan)},update:function(el,binding){letoSpan=document.getElementById('oSpan')oSpan.innerText=`${binding.value}/30`}}现在显示效果的值应该是实时更新的。细心的同学应该会发现有一个地方有遗漏,就是显示效果的最大字符数限制,目前固定为30,所以如果要限制字符为其他值,会不行。解决这个问题也很简单。将传递的值改为可以是数组形式exportdefault{inserted:function(el,binding){letwrap=document.createElement('div')wrap.style.position='relative'el.parentNode.replaceChild(wrap,el)wrap.appendChild(el)letoSpan=document.createElement('span')oSpan.style.lineHeight=1.5oSpan.style.color='#909399'oSpan.style.position='绝对'oSpan.style。background='#FFF'oSpan.style.fontSize='12px'oSpan.style.bottom='5px'oSpan.style.right='10px'//binding.value等于el-input组件使用的值thisdirectiveLength,这里使用ES6字符串模板拼接oSpan.innerText=`${binding.value[0]}/${binding.value[1]}`//为了方便在更新生命周期函数中获取,添加一个idoSpan.setAttribute('id','oSpan')wrap.appendChild(oSpan)},update:function(el,binding){letoSpan=document.getElementById('oSpan')oSpan.innerText=`${binding.value[0]}/${binding.value[1]}`}}至此,这条自定义指令就完成了搞定了,当然不难,这篇文章的主要目的是指导一些没有接触过自定义命令应用的同学,讲一个完整的应用过程和思路,希望对一些人有所帮助,留在我的笔记