第4章:自定义指令与过渡
五,自定义指令
分类:全局指令,局部指令
1.自定义全局指令
用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // 注册 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <! 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 > |
页面显示
钩子函数的参数
指令钩子函数会被传入以下参数
1 2 3 4 5 6 7 8 9 10 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <! 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会被调用
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | <! 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实例内部定义
示例:页面刷新获得焦点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | <! 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | <! DOCTYPE html> < html lang="en"> < head > < meta charset="UTF-8"> < title >练习:自定义指令</ title > < script src="js/vue.js"></ script > < style > #itany div{ width: 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | <! DOCTYPE html> < html lang="en"> < head > < meta charset="UTF-8"> < title >动画</ title > < script src="js/vue.js"></ script > < style > p{ width: 300px; height: 300px; background-color: red; } .fade-enter-active,.fade-leave-active{ transition:all 1s ease; } .fade-enter-active{ opacity: 1; width: 300px; height: 300px; } .fade-leave-active{ opacity: 0; width: 0px; height: 0px; } .fade-enter{ opacity: 0; width: 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | <! DOCTYPE html> < html lang="en"> < head > < meta charset="UTF-8"> < title >动画</ title > < script src="js/vue.js"></ script > < style > p{ width: 300px; height: 300px; background-color: red; } .fade-enter-active,.fade-leave-active{ transition:all 1s ease; } .fade-enter-active{ opacity: 1; width: 300px; height: 300px; } .fade-leave-active{ opacity: 0; width: 0px; height: 0px; } .fade-enter{ opacity: 0; width: 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执行一些样式等操作
例如想要进入之后显示为蓝色
1 2 3 4 | afterEnter(el){ alert('动画进入之后'); el.style.background='blue'; }, |
4,结合第三方动画库animate..css一起使用
示例day02/11.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <! 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{ width: 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <! 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{ width: 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <! 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{ width: 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列表里面的元素。
页面显示
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2020-12-15 CentOS7设置密码提示过于简单化的快速解决办法