1、自定义指令
1.1、定义指令
-
作用:帮助我们实现对于一些原生DOM的操作。比如说,页面一进入输入框就获取焦点;比如焦点离开输入框就开始验证。
-
定义自定义指令:
-
全局注册
Vue.directive('指令名',{ 配置项 }) // 全局注册要放在Vue实例化之前
-
局部注册
new Vue({ el:"", ... directives:{ 指令名:{ 配置项 } } })
-
1.2、指令的配置项
-
指令的生命周期钩子
-
bind 绑定 只触发一次
-
inserted 插入 只触发一次
-
update 更新 可能内部没更新完就触发了 反复触发
-
componentUpdated 内部的组件更新结束,本身也更新结束才触发 反复触发
-
unbind 解绑 只触发一次
-
钩子函数的参数
-
el 指令所挂载的节点
-
binding 挂载的信息
- binding.value 就是指令的值
- binding.name 指令的名字, 没有v-
- binding.expression 指令的表达式
-
vnode 虚拟节点
-
oldVnode 原来的虚拟节点
-
1.3、代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h3 v-myhtml="'天下第一美男子'"></h3>
<input type="text" v-focus>
</div>
</body>
<script>
// 全局注册、 局部注册
// Vue.directive('指令名',{配置对象})
// v-test
Vue.directive('myhtml',{
bind(el,binding){ // 绑定指令 触发一次
console.log("bind");
},
inserted(el,binding){ // 节点插入的时候触发
console.log('inserted');
console.log(el);
console.log(binding.value);
el.innerHTML = '武哥'+binding.value
},
update(el,binding){ // 所在节点更新的时候触发,可能在子节点更新之前就被触发
console.log('update');
},
componentUpdated(el,binding){ // 所在节点及子节点都更新完成之后才触发
console.log('componentUpdated');
},
unbind(el,binding){
console.log('unbind');
}
})
new Vue({
el:"#app",
data:{
nums:100
},
directives:{ // 局部注册
focus:{
inserted(el,binding){
el.focus();
console.log(el);
}
}
}
})
</script>
</html>
2、过滤器
2.1、定义过滤器
-
作用:对于需要展示的数据进行一定的处理;比如: 我们在展示价格数据的,需要保留两位小数,需要的英文单字首字母大写,这个时候我们就可以定义过滤器来进行处理。
-
如何定义过滤器:
-
全局注册
Vue.filter('过滤器名',function(参数){ // 一定要有 return })
-
局部注册
new Vue({ el:"", ... filters:{ 过滤器名:function(参数){ // 一定要有return } } })
-
2.2、过滤器使用、传参
-
简单实用
{{ 变量 | 过滤器名 }}
-
多个过滤器一起使用
{{ 变量 | 过滤器名A | 过滤器名B }}
-
过滤器传参
{{ 变量 | 过滤器名A | 过滤器名B(参数1,参数2) }}
2.3、代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{ price.toFixed(2) }}
<br>
{{ price2.toFixed(1) }}
<hr>
{{ nums | toFix }}
<br>
{{ price | toFix }}
<br>
{{ price2 | toFix(1) }}
<br>
{{ price3 | toFix(3) | addstr }}
<br>
{{ price3 | toFix(3) | addstr('过滤的结果是:') }}
</div>
</body>
<script>
// 希望有一个可以对价格进行过滤的东西 过滤器
// 全局注册,局部注册
// 全局注册
// console.log(Vue.filter);
// 定义:Vue.filter('过滤器名',过滤器函数)
// 过滤器函数一定要有返回值
/*
Vue.filter('过滤器名',functon(变量值,传入的参数){
// 过滤处理
return 处理后的结果
})
*/
// 局部注册:
/*
new Vue({
el:""
...,
filters:{
过滤器名:function(变量值,传入的参数=参数默认值){
// 过滤处理
return 处理后的结果
}
}
})
*/
// 使用: {{ 变量 | 过滤器名 }}
// 使用: {{ 变量 | 过滤器名(参数1,参数2) }}
// 使用: {{ 变量 | 过滤器名1 | 过滤器名2 | 过滤器名3 |... }}
Vue.filter('toFix',function(val,num=2){
if(isNaN(val)){ // isNaN 是true 不是数字
console.log('不是数字');
return '不是数字';
}
return val.toFixed(num)
})
new Vue({
el:"#app",
data:{
price:300.421,
price2:400.246,
price3:10.834539745,
nums:'aaaa'
},
filters:{
addstr:function(val,str='结果是:'){
console.log(val);
return str+val
}
}
})
// 函数的默认参数
// function add(num){
// // var num = num || 20
// if(num){
// var num = num;
// }else{
// num = 20
// }
// console.log(num);
// }
// add();
function add(num=20){
console.log(num);
}
add();
add(100)
</script>
</html>
3、插槽
-
插槽是什么: 组件的标签之前放入一些html内容。那这些html内容被称为插槽。这些内容将会被渲染到组件的模板内部。
-
插槽的作用:提供给了开发者自己去定义插槽内部的一些局部结构。
3.1、默认插槽
-
组件调用时候
<组件名> html标签内容 </组件名>
<组件名> <template v-slot:default> html标签内容 </template> </组件名>
-
组件模板内部
//组件的模板内 <template> <div> <h3>我是组件模板</h3> <slot></slot> // 就可以将上面的html标签内容放在这里 </div> </template>
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <myalert> <h3>我是h3</h3> <p>2333333333</p> </myalert> </div> <template id="myalert"> <div class="myalert"> <slot></slot> 我是myalert组件 </div> </template> </body> <script> Vue.component('myalert',{ template:"#myalert" }) new Vue({ el:"#app" }) // 插槽的使用: // 我们在组件运用的时候: <myalert>标签内容</myalert> // 组件的模板里面: 使用slot标签获取上面的标签内容 <slot></slot> </script> </html>
3.2、具名插槽
-
定义: 我们希望标签之间的HTML,不同的内容放在组件模板内部的不同地方。
-
实现:
- 组件调用的时候
<组件名> <template v-slot:插槽名A> HTML内容 </template> <template v-slot:default> // 默认插槽 HTML内容 </template> <template v-slot:插槽名B> HTML内容 </template> </组件名>
- 组件模板内部
//组件的模板内 <template> <div> <h3>我是组件模板</h3> <slot name="default"></slot> // 默认插槽 <slot></slot> // 默认插槽 可以省略 name <slot name="插槽名A"></slot> <slot name="插槽名B"></slot> </div> </template>
-
代码实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <myalert> <h3>我是h3</h3> <p>2333333333</p> <template v-slot:aaa> <h3>我是aaa的部分内容</h3> </template> <template v-slot:bbb> <h3>我是bbb的部分内容</h3> </template> </myalert> </div> <template id="myalert"> <div class="myalert"> <slot name="default"></slot> 我是myalert组件 <slot name="aaa"></slot> <slot name="bbb"></slot> </div> </template> </body> <script> Vue.component('myalert',{ template:"#myalert" }) new Vue({ el:"#app" }) </script> </html>
3.3、作用域插槽
-
目的:在插槽的内容html里面可以直接渲染父组件的变量 ,却无法直接渲染该组件自己的变量。作用域插槽就可以帮我们实现 在插槽内部 调用 组件里的数据
-
实现:
-
在组件调用的时候
<组件名> <template v-slot:插槽名A="作用域变量"> // 作用域变量就是该插槽slot标签上面的所有属性 {{ 作用域变量 }} // 渲染出 { 属性名A:变量A,属性名B:变量B, } HTML内容 </template> <template v-slot:default> // 默认插槽 HTML内容 </template> <template v-slot:插槽名B> HTML内容 </template> </组件名>
-
组件模板内部
//组件的模板内 <template> <div> <h3>我是组件模板</h3> <slot name="default"></slot> // 默认插槽 <slot></slot> // 默认插槽 可以省略 name <slot name="插槽名A" :属性名A="变量A" :属性名B="变量B"></slot> <slot name="插槽名B"></slot> </div> </template> // 组件的JS内部 { template:"", data(){ return{ 变量A:值A, 变量B:值B } } }
-
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style> .box{ width: 800px; background-color: #ccc; margin: 0 auto; } .header{ height: 200px; background-color: red; } .main{ height: 400px; border: 2px solid blue; } .footer{ height: 100px; background-color: orange; } </style> </head> <body> <div id="app"> <page> <template v-slot:tou="slotProps"> <h3>我是头部</h3> {{slotProps}} <p> <a href="" v-for="(item,index) in slotProps.navdata" :key="index">{{item}}</a> </p> </template> <template v-slot:default="defaultPorps"> <p>我是内容</p> {{defaultPorps}} <ul> <li v-for="(item,index) in defaultPorps.list" :key="index">{{item}}</li> </ul> </template> <template v-slot:jiao="slotProps"> <h3>我是脚步</h3> {{slotProps}} <p>{{slotProps.copy}}</p> </template> </page> </div> <!-- 页面内容模板 --> <template id="page"> <div class="box"> <div class="header"> <slot name="tou" :navdata="navdata"></slot> </div> <div class="main"> <slot :list="list"></slot> </div> <div class="footer"> <slot name="jiao" :copy="copy"></slot> </div> </div> </template> </body> <script> Vue.component('page',{ template:"#page", data(){ return{ navdata:['首页','关于我们','公司新闻','等等'], list:['新闻1','新闻2','新闻3','新闻4'], copy:"版权所有@翻版必究" } } }) new Vue({ el:"#app", data:{} }) </script> </html>
3.4、旧语法
-
为什么要学习旧语法: 因为很多一些成熟的UI框架,在封装的时候使用的是旧语法。比如element-ui
-
区别:
-
组件调用的时候
<组件名> <template v-slot:插槽名A="作用域变量"> <!--新语法--> <template slot="插槽名A" slot-scope='作用域变量' > <!--旧语法--> {{ 作用域变量 }} // 渲染出 { 属性名A:变量A,属性名B:变量B, } HTML内容 </template> <template v-slot:default> // 默认插槽 HTML内容 </template> <template v-slot:插槽名B> HTML内容 </template> </组件名>
-
组件内部,和新语法一致。
-
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <myalert> <!-- <template slot="default"> --> <template slot-scope="props"> <h3>我是h3</h3> <p>2333333333</p> {{props}} </template> <!-- 新语法: v-slot:插槽名="插槽的作用域变量" --> <!-- <template v-slot:aaa> --> <!-- 旧语法: slot="插槽名" slot-sope="插槽的作用域变量" --> <template slot="aaa" slot-scope="myprops"> <h3>我是aaa的部分内容</h3> {{ myprops }} </template> <!-- <template v-slot:bbb> --> <template slot="bbb"> <h3>我是bbb的部分内容</h3> </template> </myalert> </div> <template id="myalert"> <div class="myalert"> <slot name="default" yest="3234" yerrf="3333"></slot> 我是myalert组件 <slot name="aaa" :tttmsg="msg"></slot> <slot name="bbb"></slot> </div> </template> </body> <script> Vue.component('myalert',{ template:"#myalert", data(){ return{ msg:"1111111111" } } }) new Vue({ el:"#app" }) </script> </html>
4、动画
4.1、动画状态
-
进入
- 进入前: v-enter
- 进入中: v-enter-active
- 进入后: v-enter-to
-
离开
-
离开前: v-leave
-
离开中: v-leave-active
-
离开后: v-leave-to
-
4.2、定义动画
-
定义class
.动画名-enter{ css样式 } /*进入前*/ .动画名-enter-active{ css样式 } /*进入中 过渡。一般是transition */ .动画名-enter-to{ css样式 } /*进入后*/ .动画名-leave{ css样式 } /*离开前*/ .动画名-leave-active{ css样式 } /*离开中 过渡。一般是transition */ .动画名-leave-to{ css样式 } /*离开后*/ /* 动画如果自然: 进入中和离开中是一样的内容 */
-
使用动画
<transition name="动画名"> <html内容> </transition>
-
注意: 动画显示,你得实现html内容 显示 隐藏的切换
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style> .over{ width: 304px; height: 304px; margin: 0 auto; border: 4px solid #000000; overflow: hidden; } .box{ width: 300px; height: 300px; border: 2px solid orange; position: relative; left: 0; } .myfade-enter{ /* 进入的开始 */ background-color: red; opacity: 0; position: relative; left: 500px; } .myfade-enter-active{ /* 进入过程中 */ transition: all 1s ease-in; } /* .myfade-enter-to{ */ /* 进入之后 */ /* background-color: #fff; */ /* opacity: 1; */ /* } */ /* .myfade-leave{ background-color:#000; } */ .myfade-leave-active{ /* 离开过程中 */ transition: all 1s ease-in; } .myfade-leave-to{ /* 离开之后 */ opacity: 0; background-color: red; position: relative; left: -500px; } </style> </head> <body> <div id="app"> <button @clicK="state=!state">切换</button> <div class="over"> <transition name="myfade"> <div class="box" v-if="state"> <h3>你好</h3> <h3>你好</h3> <h3>你好</h3> <h3>你好</h3> <h3>你好</h3> <h3>你好</h3> </div> </transition> </div> </div> </body> <script> // v-enter 进入的时候 // v-enter-active 进入的过程中 // v-enter-to 进入后 【舍弃】 其实就是v-leave // v-leave 离开之前 // v-leave-active 离开过程 // v-leave-to 离开后 【舍弃】 其实就是v-enter new Vue({ el:"#app", data:{ state:true } }) // 动画组件: <transition name="动画名称"></transition> </script> </html>
4.3、结合animate.css
-
认识animate.css : 是一个css库,实现了很多动画效果
-
传统使用:
-
第1步:引入animate.css
-
第2步: 给要用动画的标签 上面添加上 animated 和 动画名称 class
<标签 class="animated bounceInDown"></标签>
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="https://daneden.github.io/animate.css/animate.min.css"> <style> .box{ width: 300px; height: 300px; background-color: red; } </style> </head> <body> <!-- 那个需要动画 加上 animated 的class 再添加上对应的动画class就好了--> <div class="box animated bounceInDown"></div> </body> </html>
-
-
如何结合Vue实现效果
-
第1步:引入animate.css
-
第2步:给我们的transition标签添加上 enter-active-class 和 leave-active-class 属性。 每个的值就是animate里面的动画class.
<transition enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight" > html内容 </transition>
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <link rel="stylesheet" href="https://daneden.github.io/animate.css/animate.min.css"> <style> .over{ width: 304px; height: 304px; margin: 0 auto; border: 4px solid #000000; overflow: hidden; } .box{ width: 300px; height: 300px; border: 2px solid orange; position: relative; left: 0; } </style> </head> <body> <div id="app"> <button @clicK="state=!state">切换</button> <div class="over"> <transition enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight" > <div class="box" v-if="state"> <h3>你好</h3> <h3>你好</h3> <h3>你好</h3> <h3>你好</h3> <h3>你好</h3> <h3>你好</h3> </div> </transition> </div> </div> </body> <script> new Vue({ el:"#app", data:{ state:true } }) // 动画组件: <transition name="动画名称"></transition> </script> </html>
-