33.Vue自定义指令(函数式)_vue自定义函数_未来@音律的博客-CSDN博客还有一种就是,我们去定义指令的时候,也不要去写v-前缀,定义指令的时候需要给指令起名字,那么这个指令的名字直接就叫big,而用的时候还是要规规矩矩的写v-big。像需求一这种问题,我们就使用函数的写法就能实现,需求二,我特意设置了一个细节问题,是函数实现不了的,我们就需要用对象的写法去实现。我们可以看到,当修改和v-big毫不相干的值name,都会引起big的调用,则充分说明了指令所在的模板被重新解析时,也会引起指令的重新调用。就靠big函数中收到的参数,它收到的参数中有两个比较常用,这里打印出来看一下。_vue自定义函数,并用它实现了第一个需求,这里我们接着实现第二个需求。
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点
根据我们上一节所学的,fbind直接写成函数,函数会收到,指令所在的元素,以及本次绑定的信息。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><h2>{{name}}</h2><h2>当前的n值是:<span v-text="n"></span></h2><h2>放大10倍的n值是:<span v-big="n"></span></h2><button @click="n++">点我n+1</button><hr><input type="text" v-fbind:value="n"></div></body>
<script&fig.productionTip = false;new Vue({el:'#root',data:{name:'zhangsan',n:1},directives:{big(element,binding){console.log('big被调用');element.innerText = binding.value * 10;},fbind(element,binding){element.value = binding.value;}}})</script>
</html>
我们来看下运行效果:
写到这里就差一个功能了,就是一进这个页面,让它能够自动获取焦点。
按理来说,我们只要调用element.focus();即可,那我们来看看效果。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><h2>{{name}}</h2><h2>当前的n值是:<span v-text="n"></span></h2><h2>放大10倍的n值是:<span v-big="n"></span></h2><button @click="n++">点我n+1</button><hr><input type="text" v-fbind:value="n"></div></body>
<script&fig.productionTip = false;new Vue({el:'#root',data:{name:'zhangsan',n:1},directives:{big(element,binding){console.log('big被调用');element.innerText = binding.value * 10;},fbind(element,binding){element.value = binding.value;element.focus();}}})</script>
</html>
实现效果:
我们可以看到,这个页面一进来,并没有获取焦点,但是在点击n+1以后,却又获取了焦点。这是怎么回事呢?
接下来,我们不使用Vue,用一个原生的例子,来说明这个问题。
我们先实现一个点击创建input框的例子:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"/><title></title></head><body><button id="btn"> 点我创建一个输入框 </button><script type="text/javascript">const btn = ElementById('btn');lick = () => {const input = ateElement('input');document.body.appendChild(input);}</script></body></html>
实现效果:
接下来我们实现,让这个input创建的时候,就获得焦点。还是使用刚刚的focus方法。
<!DOCTYPE html>
<html><head><meta charset="UTF-8"/><title></title></head><body><button id="btn"> 点我创建一个输入框 </button><script type="text/javascript">const btn = ElementById('btn');lick = () => {const input = ateElement('input');document.body.appendChild(input);input.focus();}</script></body></html>
实现效果:
这里的focus在一开始就生效了,那为什么刚刚Vue也使用了同样的方法,却没有在一开始就获得焦点,而是要在点击了n+1以后才获得焦点呢?
这里就要注意,focus方法并不是放在哪里都可以生效的。 如果我们把focus方法放在document.body.appendChild(input);之前就不会起作用了。
<!DOCTYPE html>
<html><head><meta charset="UTF-8"/><title></title></head><body><button id="btn"> 点我创建一个输入框 </button><script type="text/javascript">const btn = ElementById('btn');lick = () => {const input = ateElement('input');input.focus();document.body.appendChild(input);}</script></body></html>
实现效果:
这是因为,input这个元素,只有放在页面上,才能有资格让它去获取焦点。所以像input.focus()这种方法,一定要在input已经存在于页面之上才能操作。
那么再回到刚刚的问题, 这个页面一进来,并没有获取焦点,但是在点击n+1以后,却又获取了焦点。这是怎么回事呢?
代码没问题,那就是执行的时机有问题。那我们就需要分析一下fbind到底是什么时候被调用的。
我们上一节其实已经说过了。
1.指令与元素成功绑定时会被调用。
2.指令所在的模板被重新解析时
问题就出在第一条,指令与元素成功绑定时会被调用
请注意,这里说的是成功绑定,而不是成功放入页面时。Vue在干活时其实是分好几步的,像上面的例子。Vue在拿到input和fbind时,会先做一次绑定,这里绑定成功之后,仅仅代表着在内存里建立了关系,此时你的input元素并没有跑到页面上。所以此时去调用element.focus();当然是不奏效的。
那这个问题该怎么解决呢?我们怎么才能让这个input一进来就获取焦点呢?
我们就需要在Vue不仅把自定义指令与元素绑定成功了,而且也将input放入页面的时候,去调用
element.focus();,也就是说我们希望把Vue的时间点再划分的细一点。
只要我们把fbind写成一个函数,那这个功能就是无法实现的。因为一旦fbind被我们写成函数,那他就只有两个时机才会调用
1.指令与元素成功绑定时会被调用。
2.指令所在的模板被重新解析时
所以使用函数式,我们根本就拿不到Vue将元素放入页面的时间点。那这个时候就需要使用完整的对象写法才能实现。使用了对象写法,Vue就可以帮我们在特定的时间点执行特定的函数。
一共有3个特定函数:bind(); inserted(); update();
bind:当指令与元素成功绑定时调用
inserted:当指令所在元素被插入页面时调用
update:指令所在模板被重新解析时
我们可以把这些指令都做输出,看下实际的执行顺序。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><h2>{{name}}</h2><h2>当前的n值是:<span v-text="n"></span></h2><h2>放大10倍的n值是:<span v-big="n"></span></h2><button @click="n++">点我n+1</button><hr><input type="text" v-fbind:value="n"></div></body>
<script&fig.productionTip = false;new Vue({el:'#root',data:{name:'zhangsan',n:1},directives:{big(element,binding){console.log('big被调用');element.innerText = binding.value * 10;},fbind:{//指令与元素成功绑定时bind(){console.log('bind');},//指令所在元素被插入页面时inserted(){console.log('inserted');},//指令所在模板被重新解析时update(){console.log('update');}}}})</script>
</html>
实现效果:
写到这里,我们就将完整的对象式的代码写一下
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><h2>{{name}}</h2><h2>当前的n值是:<span v-text="n"></span></h2><h2>放大10倍的n值是:<span v-big="n"></span></h2><button @click="n++">点我n+1</button><hr><input type="text" v-fbind:value="n"></div></body>
<script&fig.productionTip = false;new Vue({el:'#root',data:{name:'zhangsan',n:1},directives:{big(element,binding){console.log('big被调用');element.innerText = binding.value * 10;},fbind:{//指令与元素成功绑定时bind(element,binding){element.value = binding.value;},//指令所在元素被插入页面时inserted(element,binding){element.focus();},//指令所在模板被重新解析时update(element,binding){element.value = binding.value;element.focus();}}}})</script>
</html>
实现效果:
本文发布于:2024-01-28 21:13:23,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170644760810323.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |