自定义指令
自定义全局指令
- 第一个参数:指令名称。
- 第二个参数:一个对象,该对象有一下指令相关的钩子函数。
- 注意:定义的时候,指令的名称前面不需加
v-
前缀,但调用的时候需要。
Vue.directive('指令名称', {
/*钩子函数*/ });
自定义私有指令(directives属性)
- 在声明vm对象中通过
directives
选项定义。
directives: {
// focus为指令名
focus: {
// 指令的定义,inserted为钩子函数
inserted: function (el) {
el.focus();
}
}
}
使用自定义指令
- 与官方定义指令使用一样,也可传参数。
<input v-focus>
<!-- 带参数 -->
<div id="app" v-demo="message"></div>
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。与JS行为相关的操作,最好在inserted去执行。update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是可以通过比较更新前后的值来忽略不必要的模板更新。componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind
:只调用一次,指令与元素解绑时调用。
钩子函数参数
指令钩子函数会被传入以下参数: (加粗为重要(或常用)属性)
- el:指令所绑定的元素,可以用来直接操作 DOM 。
- binding:一个对象,包含以下属性:
- name:指令名,不包括 v- 前缀。
- value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
- arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
- modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
- vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
除了
el
之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的dataset
来进行。
<div id="app" v-demo="message"></div>
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify;
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ');
};
})
new Vue({
el: '#app',
data: {
message: 'hello!'
}
});
函数简写
在很多时候,可能想在 bind
和 update
时触发相同行为,而不关心其它的钩子。可以采用以下方式:
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value;
});
对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color); // => "white"
console.log(binding.value.text); // => "hello!"
})
Vue中的动画 <transition>
使用<transition>
包裹需要动画的元素。
过渡类名
v-enter
:定义进入过渡的开始状态。在元素被插入之前生效 。v-enter-active
:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。v-enter-to
:2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时v-enter
被移除),在过渡/动画完成之后移除。v-leave
:定义离开过渡的开始状态。v-leave-active
:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。v-leave-to
: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时v-leave
被删除),在过渡/动画完成之后移除。
使用过渡类名
对于这些在过渡中切换的类名来说,**如果使用一个没有定义name
属性的 <transition>
,则 v-
是这些类名的默认前缀。**如果你使用了 <transition name="fade">
,那么 v-enter
会替换为 fade-enter
。
<style>
/* 定义进入和离开时候的过渡状态 */
.fade-enter-active,
.fade-leave-active {
transition: all 0.2s ease;
position: absolute;
}
/* 定义进入过渡的开始状态 和 离开过渡的结束状态 */
.fade-enter,
.fade-leave-to {
opacity: 0;
transform: translateX(100px);
}
</style>
<div id="app">
<input type="button" value="动起来" @click="myAnimate">
<!-- 使用 transition 将需要过渡的元素包裹起来 -->
<transition name="fade">
<div v-show="isshow">动画哦</div>
</transition>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
isshow: false
},
methods: {
myAnimate() {
this.isshow = !this.isshow;
}
}
});
</script>
过渡模式mode
in-out
:新元素先进行过渡,完成之后当前元素过渡离开。out-in
:当前元素先进行过渡,完成之后新元素过渡进入。
例:
<transition name="fade" mode="out-in">
<!-- ... the buttons ... -->
</transition>
使用第三方css动画库(自定义过渡的类名)
enter-class
enter-active-class
enter-to-class
(2.1.8+)leave-class
leave-active-class
leave-to-class
(2.1.8+)- 他们的优先级高于普通的类名,含义对应上面的过渡类名 。
<link href="https://cdn.jsdelivr.net/npm/[email protected]" rel="stylesheet" type="text/css">
<div id="example-3">
<button @click="show = !show" value="Toggle render"></button>
<transition
name="custom-classes-transition"
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
>
<p v-if="show">hello</p>
</transition>
</div>
<script>
new Vue({
el: '#example-3',
data: {
show: true
}
});
</script>