五,自定义指令
分类:全局指令,局部指令
1.自定义全局指令
用法
// 注册
Vue.directive('my-directive', {
bind: function () {},
inserted: function () {},
update: function () {},
componentUpdated: function () {},
unbind: function () {}
})
// 注册 (指令函数)
Vue.directive('my-directive', function () {
// 这里将会被 `bind` 和 `update` 调用
})
// getter,返回已注册的指令
var myDirective = Vue.directive('my-directive')
解析:自定义指令允许用户自定义指令,在指令内定义函数分别代表
bind:指令第一次绑定元素调用,只调用一次可执行初始化操作
inserted:元素插入DOM时调用
update:元素更新时调用
componentUpdated:被绑定元素完成一次更新周期调用
unbind:元素解绑时调用
示例day02/08.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义指令</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
// 定义指令使用hello使用的时候需要加前缀v-
<h3 v-hello>{{msg}}</h3>
<button @click="change">更新数据</button>
<!-- <h3 v-world>{{msg}}</h3> -->
</div>
<script>
// 自定义全局指令
// 使用指令时必须在指令名称前加v-,即v-指令名称
Vue.directive('hello',{
bind: function () { // 常用
alert('指令第一次绑定到元素上时调用,只调用一次,可执行初始化操作');
},
inserted: function () {
alert('被绑定元素插入到DOM时调用');
},
update: function () {
alert('被绑定元素所在模板更新时调用');
}, // 下面两个不常用
componentUpdated: function () {
alert('被绑定元素所在模板完成一次更新周期时调用');
},
unbind: function () {
alert('指令与元素解绑是调用,只调用一次');
}
});
// 钩子函数的参数
// Vue.directive('world',{
// bind(el,binding){
// console.log(el) // el指令所绑定的元素,DOM对象
// el.style.color='red'
// console.log(binding)
// }
// });
var vm=new Vue({
el:'#itany',
data:{
msg:'welcome to itany'
},
methods:{
change(){
this.msg='欢迎来到南京网博'
}
}
});
</script>
</body>
</html>
页面显示






钩子函数的参数
指令钩子函数会被传入以下参数
el:指令所绑定的元素,可以用来直接操作 DOM。
binding:一个对象,包含以下 property:
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 钩子中可用。
示例08.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义指令</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
<!-- 定义指令使用hello使用的时候需要加前缀v- -->
<!-- <h3 v-hello>{{msg}}</h3> -->
<button @click="change">更新数据</button>
<h3 v-world="name">{{msg}}</h3>
</div>
<script>
// 自定义全局指令
// 使用指令时必须在指令名称前加v-,即v-指令名称
Vue.directive('hello',{
bind: function () { // 常用
alert('指令第一次绑定到元素上时调用,只调用一次,可执行初始化操作');
},
inserted: function () {
alert('被绑定元素插入到DOM时调用');
},
update: function () {
alert('被绑定元素所在模板更新时调用');
}, // 下面两个不常用
componentUpdated: function () {
alert('被绑定元素所在模板完成一次更新周期时调用');
},
unbind: function () {
alert('指令与元素解绑是调用,只调用一次');
}
});
// 钩子函数的参数
Vue.directive('world',{
bind(el,binding){
console.log(el) // el指令所绑定的元素,DOM对象
el.style.color='red' // 可以对这个DOM对象进行操作例如加样式
console.log(binding) // binding一个对象
}
});
var vm=new Vue({
el:'#itany',
data:{
msg:'welcome to itany',
name:'alice'
},
methods:{
change(){
this.msg='欢迎来到南京网博'
}
}
});
</script>
</body>
</html>
页面显示

简化也可以注册一个函数,在bind和update
注册指令函数,bind和update会被调用
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义指令</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
<!-- 定义指令使用hello使用的时候需要加前缀v- -->
<!-- <h3 v-hello>{{msg}}</h3> -->
<button @click="change">更新数据</button>
<h3 v-wbs>{{msg}}</h3>
</div>
<script>
// 自定义全局指令
// 使用指令时必须在指令名称前加v-,即v-指令名称
Vue.directive('hello',{
bind: function () { // 常用
alert('指令第一次绑定到元素上时调用,只调用一次,可执行初始化操作');
},
inserted: function () {
alert('被绑定元素插入到DOM时调用');
},
update: function () {
alert('被绑定元素所在模板更新时调用');
}, // 下面两个不常用
componentUpdated: function () {
alert('被绑定元素所在模板完成一次更新周期时调用');
},
unbind: function () {
alert('指令与元素解绑是调用,只调用一次');
}
});
// 钩子函数的参数
Vue.directive('world',{
bind(el,binding){
console.log(el) // el指令所绑定的元素,DOM对象
el.style.color='red' // 可以对这个DOM对象进行操作例如加样式
console.log(binding) // binding一个对象
}
});
//传入一个简单的函数,bind和update时调用
Vue.directive('wbs',function(){
alert('wbs17022');
});
var vm=new Vue({
el:'#itany',
data:{
msg:'welcome to itany',
name:'alice'
},
methods:{
change(){
this.msg='欢迎来到南京网博'
}
}
});
</script>
</body>
</html>
页面显示
在绑定和更新数据的时候调用函数


2,自定义局部指令
在vue实例内部定义
示例:页面刷新获得焦点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义指令</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
<!-- 定义指令使用hello使用的时候需要加前缀v- -->
<!-- <h3 v-hello>{{msg}}</h3> -->
<button @click="change">更新数据</button>
<!-- <h3 v-wbs>{{msg}}</h3> -->
<input type="text" v-model="msg" v-focus>
</div>
<script>
// 自定义全局指令
// 使用指令时必须在指令名称前加v-,即v-指令名称
Vue.directive('hello',{
bind: function () { // 常用
alert('指令第一次绑定到元素上时调用,只调用一次,可执行初始化操作');
},
inserted: function () {
alert('被绑定元素插入到DOM时调用');
},
update: function () {
alert('被绑定元素所在模板更新时调用');
}, // 下面两个不常用
componentUpdated: function () {
alert('被绑定元素所在模板完成一次更新周期时调用');
},
unbind: function () {
alert('指令与元素解绑是调用,只调用一次');
}
});
// 钩子函数的参数
Vue.directive('world',{
bind(el,binding){
console.log(el) // el指令所绑定的元素,DOM对象
el.style.color='red' // 可以对这个DOM对象进行操作例如加样式
console.log(binding) // binding一个对象
}
});
//传入一个简单的函数,bind和update时调用
Vue.directive('wbs',function(){
alert('wbs17022');
});
var vm=new Vue({
el:'#itany',
data:{
msg:'welcome to itany',
name:'alice'
},
methods:{
change(){
this.msg='欢迎来到南京网博'
}
},
directives:{ // 自定义指令
//当被绑定元素插入到DOM中时获取焦点
focus:{
inserted(el){
el.focus();
}
}
}
});
</script>
</body>
</html>
3,练习
拖动页面中的元素,使其移动,松开鼠标不移动
onmouseover onmouseout
09.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>练习:自定义指令</title>
<script src="js/vue.js"></script>
<style>
#itany div{
100px;
height: 100px;
position:absolute;
}
#itany .hello{
background-color:red;
top:0;
left:0;
}
#itany .world{
background-color:blue;
top:0;
right:0;
}
</style>
</head>
<body>
<div id="itany">
<div class="hello" v-drag>itany</div>
<div class="world" v-drag>网博</div>
</div>
<script>
Vue.directive('drag',function(el){
el.onmousedown=function(e){
//获取鼠标点击处分别与div左边和上边的距离:鼠标位置-div位置
var disX=e.clientX-el.offsetLeft;
var disY=e.clientY-el.offsetTop;
// console.log(disX,disY);
//包含在onmousedown里面,表示点击后才移动,为防止鼠标移出div,使用document.onmousemove
document.onmousemove=function(e){
//获取移动后div的位置:鼠标位置-disX/disY
var l=e.clientX-disX;
var t=e.clientY-disY;
el.style.left=l+'px';
el.style.top=t+'px';
}
//停止移动
document.onmouseup=function(e){
document.onmousemove=null;
document.onmouseup=null;
}
}
});
var vm=new Vue({
el:'#itany',
data:{
msg:'welcome to itany',
username:'alice'
},
methods:{
change(){
this.msg='欢迎来到南京网博'
}
}
});
</script>
</body>
</html>
页面显示

六,动画(过渡)
1.简介
Vue在插入,更新或者移除DOM时,提供多种不同方式的应用过滤效果
本质上还是使用CSS3动画:transition,animation
2.基本用法
使用transition组件,将要执行动画的元素包含在该组件内
<transtion></transtion>
示例,演示淡入淡出效果,网页上的一个标签正常显示与不显示的效果是立即生效的,没有渐渐的过程下面演示动画效果
day02/10.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动画</title>
<script src="js/vue.js"></script>
<style>
p{
300px;
height: 300px;
background-color: red;
}
.fade-enter-active,.fade-leave-active{
transition:all 1s ease;
}
.fade-enter-active{
opacity: 1;
300px;
height: 300px;
}
.fade-leave-active{
opacity: 0;
0px;
height: 0px;
}
.fade-enter{
opacity: 0;
50px;
height: 50px;
}
</style>
</head>
<body>
<div id="itany">
<button @click="flag=!flag">点我</button>
<transition name="fade">
<p v-show="flag">网博</p>
</transition>
</div>
<script>
var vm=new Vue({
el:'#itany',
data:{
flag:false
}
});
</script>
</body>
</html>
3,钩子函数
解析:需要演示效果的<p>标签包含在标签<transition>内,这个标签自定义名称fade,然后在样式里定义过渡的类名状态来实现动画效果
在进入/离开的过渡中,会有 6 个 class 切换。
-
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被删除),在过渡/动画完成之后移除。
代码解析

页面显示

注意:fade-enter要放在最后位置,否则动画效果不实现
可以在 attribute 中声明 JavaScript 钩子,在动画执行的各个过程绑定一些方法
示例 day02/10.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动画</title>
<script src="js/vue.js"></script>
<style>
p{
300px;
height: 300px;
background-color: red;
}
.fade-enter-active,.fade-leave-active{
transition:all 1s ease;
}
.fade-enter-active{
opacity: 1;
300px;
height: 300px;
}
.fade-leave-active{
opacity: 0;
0px;
height: 0px;
}
.fade-enter{
opacity: 0;
50px;
height: 50px;
}
</style>
</head>
<body>
<div id="itany">
<button @click="flag=!flag">点我</button>
<transition name="fade"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
>
<p v-show="flag">网博</p>
</transition>
</div>
<script>
var vm=new Vue({
el:'#itany',
data:{
flag:false
},
methods:{
beforeEnter(){
alert('动画进入之前');
},
enter(){
alert('动画进入');
},
afterEnter(){
alert('动画进入之后');
},
beforeLeave(){
alert('动画即将之前');
},
leave(){
alert('动画离开');
},
afterLeave(el){
alert('动画离开之后');
// el.style.background='red';
}
}
});
</script>
</body>
</html>
页面显示

省略其他几张截图
本次使用alert只是演示执行的过程,有什么用呢,这几个钩子函数传递参数el可以对这个DOM执行一些样式等操作
例如想要进入之后显示为蓝色
afterEnter(el){
alert('动画进入之后');
el.style.background='blue';
},
4,结合第三方动画库animate..css一起使用
示例day02/11.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动画</title>
<link rel="stylesheet" href="css/animate.css">
<script src="js/vue.js"></script>
<style>
p{
300px;
height: 300px;
background-color:red;
margin:0 auto;
}
</style>
</head>
<body>
<div id="itany">
<button @click="flag=!flag">点我</button>
<transition enter-active-class="animated fadeInLeft" leave-active-class="animated fadeOutRight">
<p v-show="flag">网博</p>
</transition>
</div>
<script>
var vm=new Vue({
el:'#itany',
data:{
flag:false
}
});
</script>
</body>
</html>
页面显示

注意:需要引入animate.css样式,需要加入初始样式animated否则不生效
可以在https://www.dowebok.com/demo/2014/98/ 查看anmiated演示效果

5,多元素动画
多元素动画需要使用标签<transition-group>,还需要给内部的每一个元素使用关键字:key指定唯一的key
示例day02/12.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>多元素动画</title>
<link rel="stylesheet" href="css/animate.css">
<script src="js/vue.js"></script>
<style>
p{
100px;
height: 100px;
background-color:red;
margin:20px auto;
}
</style>
</head>
<body>
<div id="itany">
<button @click="flag=!flag">点我</button>
<transition-group enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight">
<p v-show="flag" :key="1">itany</p>
<p v-show="flag" :key="2">网博</p>
</transition-group>
</div>
<script>
var vm=new Vue({
el:'#itany',
data:{
flag:false
}
});
</script>
</body>
</html>
页面显示

6,练习
要求在输入框输入字符,然后根据字符显示元素
day02/13.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>练习:多元素动画</title>
<link rel="stylesheet" href="css/animate.css">
<script src="js/vue.js"></script>
<style>
p{
100px;
height: 100px;
background-color:red;
margin:20px auto;
}
</style>
</head>
<body>
<div id="itany">
<input type="text" v-model="name">
<transition-group enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight">
<p v-for="(v,k) in arr2" :key="k">
{{v}}
</p>
</transition-group>
</div>
<script>
var vm=new Vue({
el:'#itany',
data:{
flag:true,
arr:['tom','jack','mike','alice','alex','mark'],
name:''
},
computed:{
arr2:function(){
var temp=[];
this.arr.forEach(val => {
if(val.includes(this.name)){
temp.push(val);
}
});
return temp;
}
}
});
</script>
</body>
</html>
解析:
定义一个计算属性arr2,输入框绑定的元素是name,如果输入框的字符出现在arr列表中,则把这个字符投入temp列表中,最后返回temp列表就是包含输入框字符的所有arr里面的元素的一个列表,arr2是计算属性,依赖于返回的temp,然后显示包含输入框字符的所有arr列表里面的元素。
页面显示
