「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」。
年后的第三天工作,当我的脑子还没有从要打工的悲伤中走出来,产品的需求就已经追着我跑了
产品:“你看这个搜索能不能让它进入页面就自动对焦呢,提升一下用户的体验感”
我:“应该可以(实际是完全可以,就是不想改)”
但是,答应了就得干啊,打开vscode,开始搞
Step One
脑子灵光一现,Vue中不是有个自定义指令嘛,快速且方便,说干就干 打开代码,思考了一下是写在全局呢还是写在局部呢 为了后续其他人使用,我当然选择写在全局了,代码如下
<input v-focus class="search_input" v-model="search" type="text" placeholder="搜索分销员名字/手机号" @keyup.13="searchClick" />
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素 el.focus()
}
})
上面这段代码也是官网提供的参考代码,当我兴高采烈的打算提交代码的时候,问题也就出现了,输入框并不聚焦
Step Two
我开始找问题出在了哪里,通过打debug发现v-focus进来的el参数并非是input元素,而是父级div元素,找到问题开始解决,这里我将全局定义的自定义指令改为了局部使用
官网给出的代码示例如下:
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
},
参照官网的示例,我将代码修改为以下代码
directives: {
inserted (el) {
if (el.tagName.toLocaleLowerCase() == 'input') {
el.focus()
} else {
if (el.getElementsByTagName('input')) {
el.getElementsByTagName('input')[0].focus()
}
}
}
}
这个时候进入页面聚焦就已经生效了。
Step Three
为了之后能更轻松的插入图片,我有写了一个图片的自定义指令,代码如下
Vue.directive('fail-img', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function inserted(el, binding) {
let url = default_img_url
switch (binding.value) {
case 1:
url = 'https://scdn.yourbay.net/tst/img/tstMinScanImg.jpg'
break
case 2:
url = ''
break
case 3:
url = ''
break
}
setTimeout(function() {
var img = new Image()
img.src = el.src
img.onload = function() {
el.__loadImg = true
}
if (!el.__loadImg) {
img.onerror = function() {
setTimeout(function() {
console.log('error load img:', el.src)
el.src = url
}, 300)
}
}
}, 600)
}
})
这里在说说为什么,这段代码里使用的setTimeout定时器,再写这段代码的时候,我验证的过程中,发现图片src在赋值的时候,组件的DOM并没有生成,挂载不上去,所以采用了定时器的方法延长时间。
Step Four
上述代码采用定时器的方法并不是一个合格的代码,我们可以使用自定义指令的生命周期完善代码
自定义指令的三个参数
在了解生命周期之前,先研究三个参数是什么
- el: 指令所绑定的元素,可以用来直接操作DOM。
- binding: 一个对象,包含指令的很多信息。
- vnode: Vue编译生成的虚拟节点。
自定义指令的生命周期
自定义指令有五个生命周期(也叫钩子函数),分别是 bind,inserted,update,componentUpdated,unbind
- bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作。
- inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)。
- update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
- componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
- unbind:只调用一次,指令与元素解绑时调用。