前些日子我在stackoverflow社区看到一篇文章是关于表单验证抖动效果的,比如表单验证没达到要求,就可以要求表单摇摆
<template>
<div id="app">
<button :class="{ 'apply-shake': shake }" @click="shakeAnimation()">
Shake
</button>
</div>
</template>
<script>
export default {
data() {
return {
shake: false,
};
},
methods: {
shakeAnimation() {
this.shake = true;
setTimeout(() => {
this.shake = false;
}, 820); // timeout value depending on the duration of the animation
},
},
};
</script>
<style>
@keyframes shake {
10%,
90% {
transform: translate3d(-1px, 0, 0);
}
20%,
80% {
transform: translate3d(2px, 0, 0);
}
30%,
50%,
70% {
transform: translate3d(-4px, 0, 0);
}
40%,
60% {
transform: translate3d(4px, 0, 0);
}
}
.apply-shake {
animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}
</style>
现在我们考虑一个问题,如果多次重复应用该代码我们应该做什么?
复制粘贴❌
抽离代码✔️
自定义指令
<template>
<div class="container">
<input type="text" v-shake="shake" v-model="inputInner" />
<button @click="shakeAnimation">点击验证</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const shake = ref(false)
const inputInner = ref(null)
const shakeAnimation = () => {
if (!inputInner.value) {
shake.value = true
setTimeout(() => {
shake.value = false
}, 820)
}
}
return { shakeAnimation, shake, inputInner }
}
}
</script>
和组件类似,自定义指令在模板中使用前必须先注册。我们使用 directive 选项进行注册。
app.directive('shake', (el, binding) => {
/* ... */
})
那么el, binding两个参数是干嘛的呢,我们打印一下看看
官方文档中写到
el:指令绑定到的元素。这可以用于直接操作 DOM-
binding:一个对象,包含以下属性。value:传递给指令的值。例如在v-my-directive="1 + 1"中,值是2。oldValue:之前的值,仅在beforeUpdate和updated中可用。无论值是否更改,它都可用。arg:传递给指令的参数 (如果有的话)。例如在v-my-directive:foo中,参数是"foo"。modifiers:一个包含修饰符的对象 (如果有的话)。例如在v-my-directive.foo.bar中,修饰符对象是{ foo: true, bar: true }。instance:使用该指令的组件实例。dir:指令的定义对象。
vnode:代表绑定元素的底层 VNode。prevNode:之前的渲染中代表指令所绑定元素的 VNode。仅在beforeUpdate和updated钩子中可用。
emmm...,很明了了,我们只要监听shake这个值的变化,也就是把value拿过来就好了,然后你在他的DOM上操作class名就好了,具体代码如下!
const defineDirective = (app) => {
app.directive('shake', {
updated(el, binding) {
if (binding.value) {
el.classList.add('apply-shake')
} else {
el.classList.remove('apply-shake')
}
}
})
}