本文是我在学习过程中记录学习的点点滴滴,目的是为了学完之后巩固一下也顺便和大家分享一下,日后忘记了也可以方便快速的复习。
自定义指令及过度(动画)
前言
今天主要学习的是关于自定义指令。前面我们已经学习了 vue 提供的内置指令v-text、v-html、v-show 、v-if、v-else、v-else-if、v-for、v-on、v-bind、v-model、v-pre、v-cloak、v-once 等,只有一个 v-slot 没讲。如果这些指令还不能满足实际要求,Vue 也允许注册自定义指令,分为自定义全局指令和自定义局部指令。
一、自定义指令
1.1、自定义全局指令
注册一个全局自定义指令。指令取名字的时候不要用大写字母,且不要加 v-,但是使用时一定要加前缀 v。
Vue.directive('指令名', { 定义对象 })
定义对象为钩子函数,钩子函数主要有 5 个,具体看例子。为全局指令时就是表示可以在多个vue实例中使用(可以再定义一个new vue 实例,然后去使用。
总结:
1、全局指令定义完后在其他vue实例中都可以运用。
2、五个钩子函数一般只用bind和update这两个,而且当不写明确的钩子函数时默认在bind和update这两个函数中执行。
3、el时绑定的dom元素,bindingg 为一个对象,包含一些属性,比如 name(指令名,不包括 v- 前缀),value(指令的绑定到的值),expression(字符串形式的指令表达式),arg:传给指令的参数
4、binding.value.charAt(0).toUpperCase()
+binding.value.slice(1);
中charAt(0).toUpperCase()是将第一个字母转为大写,slice(1)是将获取内容从下标为1的字符开始到最后,加号是拼接。
五个钩子函数(bind()、inserted()、update()、componentUpdated()、unbind())的执行时机
<script>
/* 自定义全局指令
注意:使用指令时必须在指令 ID 名称前加前缀 v-,即 v-指令名
称
自己为指令取名字的时候不要加 v-*/
Vue.directive('my-dir',{
bind(){//常用
//此例子指令绑定到 h3 时就执行
alert('指令第一次绑定到元素上时调用,只调用一次,一般执行初始化操作')
},
inserted(){
//被绑定元素此例即为 h3,h3 插入到 div 中时执行
alert('被绑定元素插入到 dom 中调用')
},
update(){
alert('被绑定元素所在模板更新时调用')
},
componentUpdated(){
alert('被绑定元素所在模板完成一次更新周期时调用,相当于就是已经完成更新时调用')
},
unbind(){
alert('指令与元素解绑时调用,只调用一次')
}
//以上钩子函数不是都需要定义,可以根据需要定义部分。钩子函数根据需要可以有参数,如下面例子
})
</script>
以上 5 个钩子函数不是都需要定义,可以根据需要定义部分。钩子函数根据需要可以有参数
<div id="app">
<h3 v-text="msg"></h3>
<!-- xzx 为传给指令的参数 -->
<h3 v-red-text:xzx="msg"></h3>
</div>
<script>
/* 自定义全局指令
注意:使用指令时必须在指令 ID 名称前加前缀 v-,即 v-指令名
称
自己为指令取名字的时候不要加 v-*/
Vue.directive('red-text',{
bind(el){
//el 表示指令绑定的 dom 元素,上面例子即为 h3
el.style.color='red' //拿到 dom 元素之后就可以为它设置样式,放到 inserted 钩子函数里面写也可以的
},inserted(el,binding){
//console.log(binding);//第二个参数 binding 为一个对象,包含一些属性,比如 name(指令名,不包括 v- 前缀),value(指令的绑定到的值),expression(字符串形式的指令表达式),arg:传给指令的参数
// console.log(binding.name);//red-text
//console.log(binding.value);// welcome to xdz
// console.log(binding.expression);//msg
// console.log(binding.arg);//xzx
el.innerHTML=binding.value.charAt(0).toUpperCase()
+binding.value.slice(1);
//el.style.color='red' }, })
var vm = new Vue({
el: '#app', data: {
msg:'welcome to xdz' }
})
</script>
结果:
1.2、自定义局部指令
在某个 vue 实例内部定义,即是通过 vue 实例选项 directives:{}
功能:每次刷新时输入框会自动获取焦点
<div id="app">
被绑定元素自动获取焦点: <input type="text" v-myfocus>
</div>
<script>
var vm = new Vue({
el: '#app', data: {
msg: 'welcome to xdz', },directives: {
'myfocus': { //注意:指令名不能有大写字母
inserted(el) {
el.focus();
}
}
}
})
</script>
结果:
1.3、钩子函数的简写
在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如上面的自定义指令可这样写(以下内容就会默认在bind 和 update 中执行)
Vue.directive('red-text',function(el,binding){
el.innerHTML=binding.value.charAt(0).toUpperCase()+binding.value.slice(1);
el.style.color='red' }
也就是第二个参数直接传入一个函数。这个函数相当于 bind 和update 钩子函数,也就是在刚绑定到元素上会执行,在被绑定元素更新时也会执行。
二、过度效果实现
总结:
1、要将实现动态的元素放到< transition></ transition>中去。
2、就是为目标元素添加一个父元素 <trasition name=‘xxx’> , 让父元素通过自动应用 class 类名来达到效果。可以不设置此 name 属性,那么下面的类名就是以 v-开头,即下面的 xxx 换为 v。
过渡与动画时,会为对应元素动态添加的相关 class 类名:
(1)xxx-enter :定义显示前的效果。
(2)xxx-enter-active :定义显示过程的效果。
(3)xxx-enter-to : 定义显示后的效果。
(4)xxx-leave : 定义隐藏前的效果。
(4)xxx-leave-active :定义隐藏过程的效果。
(6)xxx-leave-to :定义隐藏后的效果。
3、且设置属性时xxx-enter 、xxx-leave-to要放在最后,否则可能会出错。
2.1、什么是过度
元素在显示和隐藏时,不要直接显示或隐藏,而是来一个过度或者动画的效果。常用的过渡和动画都是使用 CSS 来实现的。
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
2.2、基本用法
使用 transition 组件,将要执行的动画的元素包含在该组件内。
< transition>
想要运动的元素
</ transition>
<style>
/* 另外这里样式名不能用#,也就是下面的元素不能通过设置 id 来
设置样式 */
/* #app p {
width: 200px;
height: 200px;
background-color: red;
} */
.p1 {
width: 200px;
height: 200px;
background-color: red;
}
/* 设置动画的进入和离开时共同效果.如果 transition 组件没有
设置 name 属性,此处就是以 v-前缀 */
.fade-enter-active,.fade-leave-active{
/* transition 是设置过渡的属性。all 指的是所有属性都赋予过
渡效果,过渡时间延续 2s,ease 表示过渡类型是平滑过渡 */
transition:all 2s ease;
}
/* 以下 3.的样式还必须放在最后 */
/* 1.单独设置进入过程的过度效果 */
.fade-enter-active{
opacity:1;
width:200px;
height:200px;
}
/* 2.单独设置离开过程的过度效果 */
.fade-leave-active{
opacity:0;/* 为 0 即为隐藏 */
width:0px;
height:0px;
}
/* 3.进入刚开始的状态效果和离开之后的效果 */
.fade-enter,.fade-leave-to{
opacity:0;
width:50px;
height:50px;
}
</style>
</head>
<body>
<div id="app">
<!-- 单击【点我】下面 P 标签进行显示与隐藏 -->
<button @click="flag=!flag">点我</button>
<!-- 把要实现动画效果的标签放入 transition 组件内,一般跟组
件设置个 name 属性,名称任意,后面设置样式会用到 -->
<transition name="fade">
<p v-show="flag" class="p1">徐照兴</p>
</transition>
</div>
<script>
var vm = new Vue({
el: '#app', data: {
flag: false
}
})
</script>
</body>
运行结果:
运行分析:
运行时单击【点我】按钮从控制台中可以看到 p 标签的样式在不断的切换到不同的样式。这也就是说动画或过度效果实际上就是在不同的样式之前切换。
上面的 v-就表示上面父元素 trasition 的 name 属性值。如果没有设置 name 属性,就以 v-开头。
三、transition 组件的6个钩子函数
总结:
1、transition 组件提供了 6 个钩子函数,通过这 6 个钩子函数可以实现在动画呈现的不同时机做不同的事情。
@before-enter=“xxx”
@enter=“xxx”
@after-enter=“xxx”
@before-leave=“xxx”
@leave=“xxx”
@after-leave=“xxx”
这六个钩子函数是transition的属性,xxx方法需要在methods中定义。
transition 组件提供了 6 个钩子函数,通过这 6 个钩子函数可以实现在动画呈现的不同时机做不同的事情。
<style><!-- 和上面的一样 --></style>
<div id="app">
<button @click="flag=!flag">点我</button>
<!-- 把要实现动画效果的标签放入 transition 组件内,一般跟组
件设置个 name 属性,名称任意,后面设置样式会用到 -->
<!-- 还可以通过钩子函数来实现在动画呈现的不同时机做不同的
事情 -->
<transition name="fade" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" @before-leave="beforeLeave" @leave="leave" @after-leave="afterLeave" >
<p class="p1" v-show="flag">徐照兴</p>
</transition>
</div>
<script>
var vm = new Vue({
el: '#app', data: {
flag:false
},methods:{
beforeEnter(){
alert('动画进入之前')
},enter(){
alert('动画进入')
},afterEnter(){
alert('动画进入之后')
},beforeLeave(){
alert('动画离开之前')
},leave(){
alert('动画离开')
},afterLeave(){
alert('动画离开之后')
}
}
})
</script>
以上钩子函数根据需要可以只设置部分钩子函数,同时可以传入参数 el,表示应用动画的元素。
需求
:
对上述进行改进,要求动画进入之后背景颜色变为蓝色;每次开始进入前动画背景颜色还是红色。对钩子函数的方法做相应的修改。上述代码中的 methods 部分只保留下面的那些即可。methods:{ afterEnter(el){ el.style.background="blue" },afterLeave(el){ el.style.background="red" } }
四、动画效果的实现
总结:
1、动画用法同过渡一样,同样需要用到 transation 组件,只不过需要采用 animation 来指定动画效果。
animation: bounce-in 1s
2、@keyframes bounce-in{
0%{}
50%{}
100%{}
}
是可以使用@keyframes来为具体的动画效果来根据时间比来设置具体效果。
动画用法同过渡,同样需要用到 transation 组件,只不过需要采用 animation 来指定动画效果
需求:点击按钮后, 文本内容有放大缩小效果
<style>
/* 显示过程中的动画效果 */
.bounce-enter-active {
/* bounce-in 为引入下面定义的动画效果(弹跳) */
animation: bounce-in 1s;
}
/* 隐藏过程中的动画效果 */
.bounce-leave-active {
animation: bounce-in 3s reverse; /*reverse 表示为相反的
顺序*/
}
@keyframes bounce-in {
0% { /*持续时间的百分比,如上面设定为 1s,则 0%就表示 0
秒的时候,50%就表示 0.5 秒时候,100%就表示 1 秒的时候 */
transform: scale(0); /* 缩小为 0 */
}
50% {
transform: scale(1.5);/* 放大到 1.5 倍 */
}
100% {
transform: scale(1);/* 原始大小 */
}
}
</style>
</head>
<body>
<div id="example-2">
<button @click="show = !show">Toggle show</button>
<transition name="bounce">
<p v-if="show">Lorem ipsum dolor sit amet, consectetu
r adipiscing elit.</p>
</transition>
</div>
<script>
new Vue({
el: '#example-2', data: {
show: true
}
})
</script>
五、结合第三方动画库 animate.css 一起使用
animate官网:
https://daneden.github.io/animate.css/
animate.css 是一个使用 CSS3 的 animation 制作的动画效果的CSS 集合,里面预设了很多种常用的动画,且使用非常简单。
下载:
进入到你想要下到的项目下并打开 cmd 窗口执行
cnpm install animate.css
然后把下载下来的 animate.css 文件复制到项目的 css 文件夹下。并在项目中引入 :
<link rel="stylesheet" href="css/animate.css"></link>
<style>
/* 另外这里样式名不能用#,也就是下面的元素不能通过设置 id
来设置样式 */
.p1{
width:200px;
height:200px;
background-color: red;
margin:0 auto;
}
</style>
</head>
<body>
<div id="app">
<button @click="flag=!flag">点我</button>
<!-- enter-active-class 设置进入时的过度效果样式类
名, leave-active-class 设置离开时的过度效果样式类名,后面的类名
根据官网效果进行选择,但是前面都必须加上加上类名 animated-->
<transition enter-active-class="animated bounceInLeft" lea
ve-active-class="animated bounceOutRight">
<p class="p1" v-show="flag">徐照兴</p>
</transition>
</div>
<script>
var vm = new Vue({
el: '#app', data: {
flag:false
}
})
</script>
</body>
如果要更改为左边淡入右边淡出效果,上面对应的代码改为如下黄色底纹代码即可。
<transition enter-active-class=“animated fadeInLeft” leave-acti
ve-class=“animated fadeOutRight”>
如果要更改为放大缩小效果,改为如下即可
<transition enter-active-class=“animated zoomIn” leave-active
-class=“animated zoomOut”
六、多元素动画
如果需要多个元素一起展现动画效果,可以把多个元素用
<transition-group>包裹起来,注意,每个 <transition-group>的子节点必须有 独立的 key 。如果 v-bind:key 这种形式的话,key要为数值型数据,并且数字可以不写引号,因为认为是索引;如果直接写 key,值就可以为字符串
总结:
1、每个要展示的元素都要有一个key值且为数值型数据。
2、enter-active-class 设置进入时的过度效果样式类名,每一个设置的样式类名前都要加一个animated。
<style>
/* 另外这里样式名不能用#,也就是下面的元素不能通过设置 id
来设置样式 */
.p1{
width:100px;
height:100px;
background-color: red;
margin:20;
}
</style>
</head>
<body>
<div id="app">
<button @click="flag=!flag">点我</button>
<!-- enter-active-class 设置进入时的过度效果样式类
名, leave-active-class 设置离开时的过度效果样式类名,后面的类名
根据官网效果进行选择,但是前面都必须加上加上类名 animated-->
<transition-group enter-active-class="animated zoomIn" l
eave-active-class="animated zoomOut">
<!—下面黄色底纹可以直接使用 key,值就可以为字符串型,比如
one、two->
<p class="p1" v-show="flag" :key="1">徐照兴</p>
<p class="p1" v-show="flag" :key="2">xzx</p>
</transition-group>
</div>
<script>
var vm = new Vue({
el: '#app', data: {
flag:false
}
})
</script>
</body>
运行效果:
6.1、列表的进入/离开过渡【官网的】
<style>
.list-item {
transition: all 1s;
margin-right: 10px;
display: inline-block;
}
.list-enter,
.list-leave-to {
opacity: 0;
transform: translateY(30px);
/* 垂直向下移动 30px */
}
.list-leave-active {
position: absolute;
}
</style>
</head>
<body>
<div id="list-demo" class="demo">
<button v-on:click="add">Add</button>
<button v-on:click="remove">Remove</button>
<transition-group name="list" tag="p">
<span v-for="item in items" v-bind:key="item" class="li
st-item">
{{ item }}
</span>
</transition-group>
</div>
<script>
new Vue({
el: '#list-demo', data: {
items: [1, 2, 3, 4, 5, 6, 7, 8, 9], nextNum: 10
},methods: {
randomIndex: function () {
// 随机返回数组内的一个索引,作为插入新值的位置
return Math.floor(Math.random() * this.items.length)
}, // Math.floor 返回小于参数的最大整数
add: function () {
// 把获取的随机数作为位置插入新元素,0 表示当前位置,第 3 个参数表示要插入的数
this.items.splice(this.randomIndex(), 0, this.nextNu
m++)
},remove: function () {
// 随机删除某个位置的元素,第 2 个参数 1 指删除 1 项
this.items.splice(this.randomIndex(), 1)
}, }
})
</script>
</body>
结果: