1. directives-自定义指令
a.简介
除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。举个聚焦输入框的例子,如下:
当页面加载时,该元素将获得焦点 (注意:autofocus 在移动版 Safari 上不工作)。事实上,只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在让我们用指令来实现这个功能:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
如果想注册局部指令,组件中也接受一个 directives 的选项:
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
然后你可以在模板中任何元素上使用新的 v-focus 属性,如下:
<input v-focus>
b. 案例
directives ---- vue自定义指令
作用
1. 要操作dom时候
2. 使用集成第三方插件时候
定义:
directives:{
img:{
inserted(el,binding){
// el 当前指令所在的html节点
// binding.value 指令的值
}
}
}
使用
<div v-img="xxxxx">
单词:
- directives 指令
- inserted 已插入
- binding 绑定
案例1-自定义指令 v-img
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义指令</title>
<style>
.box{width: 180px;height: 320px;}
</style>
</head>
<body>
<div id="app">
<div class="box" v-img="pics[0]"></div>
<div class="box" v-img="pics[1]"></div>
<div class="box" v-img="pics[2]"></div>
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{pics:[
"http://images.entgroup.cn/group2/M00/02/96/wKgAS13gt0WAS3CjAABoTRx_PZ8927.jpg",
"http://images.entgroup.cn/group1/M00/05/2C/wKgASV34PqSAQliYAABmxNg1oI0829.jpg",
"http://images.entgroup.cn/group2/M00/02/93/wKgAS12lOvCAP93oAACEwKNAR90206.jpg"]},
// 自定义指令 最大作用可以获取到自定义指令所在的 html 元素节点
directives:{
img:{
// bind update inserted 当被插入到父节点
inserted(el,binding){
// el 自定义指令所再的元素
// binding 绑定的数据 value 自定义指令的值
let color = Math.floor(Math.random()*1000000);
el.style.backgroundColor="#"+color;
// 加载图片
let img = new Image();
// 创造一个新的图片;
img.src = binding.value;
console.log(el,binding);
img.onload=function(){
el.style.backgroundImage=`url(${binding.value})`;
// 赋值背景图片
}
}
}
}
})
</script>
</body>
</html>
2. class绑定
a. 简介
- 属性绑定
:class="'red blue'" - 动态绑定
:class="{'red':flag}"
<div :class="isActive?'yellow':'red'">111</div>
:class="{'active':index==current}" - 数组绑定
:class="['red','em','small']" - 对象绑定
:class="classobj"
data:{
classobj:{
a:true,
b:true
}
}
b.案例 1:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>class绑定</title>
<style>
.red{color:red;}
.em{font-style: italic;}
.small{font-size:12px;}
</style>
</head>
<body>
<div id="app">
<!-- 在指令的值是js表达式不是字符串 -->
<h1 :class="'red'">class是一个属性 可通过属性绑定</h1>
<h1 :class="{'red':flag}">class 对象方式绑定</h1>
<h1 :class="['red','em','small']">数组的方法绑定多个</h1>
<button @click="flag=!flag">{{flag}}</button>
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
flag:true,
red:'red'
}
})
</script>
</body>
</html>
c. 案例2-选项卡切换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>选项卡案例</title>
<style>
.content{
width: 300px;
height: 300px;
clear:both;
border: 1px solid #ccc;
}
.title{
display: inline-block;
padding: 5px 15px;
background-color: #ccc;
}
.active{color:#fff;background-color: dodgerblue;}
</style>
</head>
<body>
<div id="app">
<div class="title"
v-for="(item,index) in list"
:key="index"
@click="current=index"
:class="{'active':index==current}"
>{{item.title}}</div>
<!-- 当单击标题 设置current为当前的index(单击改变current) -->
<!-- 类名active 的绑定 如果当前current与index相等 就绑定activeclass -->
<div class="content">{{list[current].content}}</div>
<!-- 内容根据 current值不同来显示不同内容 -->
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
list:[
{title:"jquery",content:"jquery内容"},
{title:"vue",content:"vue内容"},
{title:"react",content:"react内容"},
],
current:0,//默认显示第几个div
}
})
</script>
</body>
</html>
3. style绑定
动态绑定
- 三目写法
- 对象写法
- 数组写法
a.结构
style 绑定
对象
<h1 :style="{fontSize:'14px',color:'red'}">style的绑定</h1>
<h1 :style="obj">对象变量方式</h1>
data:{
obj:{'font-size':"48px",fontStyle:'italic',color:red}
}
b. 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>style绑定</title>
<style> </style>
</head>
<body>
<div id="app">
<h1 :style="{fontSize:'14px',color:'red'}">style的绑定</h1>
<div :style="'background:'+(isActive?'red':'yello')">动态三目写法</div>
<h1 :style="obj">对象变量方式</h1>
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
obj:{
"font-size":"100px",
fontStyle:'italic',
color:'blue'
}
}
})
</script>
</body>
</html>
4. 综合案例--购物车
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>购物车案例</title>
</head>
<body>
<div id="app">
<table>
<tr>
<td >全选 <input type="checkbox" v-model="all" @change="checkAll"></td>
<td>id</td> <td>书名</td> <td>日期</td> <td>价格</td><td>数量</td> <td>操作</td>
</tr>
<tr v-for="(item,index) in books" :key="index">
<td><input type="checkbox" v-model="item.sel"></td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td>{{item.price}}</td>
<td>
<button @click="item.num--">-</button>
<input type="text" v-model.number="item.num">
<button @click="item.num++">+</button>
</td>
<td> <button @click="delItem(item)">删除</button></td>
</tr>
</table>
总价格:{{total}}
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
books:[
{sel:true,id:1,name:"小红书",date:"2020/12/24",price:100,num:1},
{sel:true,id:2,name:"小蓝书",date:"2020/12/25",price:20,num:1},
{sel:true,id:3,name:"小绿书",date:"2020/12/26",price:80,num:1},
{sel:true,id:4,name:"小白书",date:"2020/11/24",price:300,num:1},
{sel:true,id:5,name:"vue精通",date:"2020/10/05",price:175,num:2}
],
all:true,
},
computed:{
"total":function(){
var n=0;
this.books.forEach(item=>{
if(item.sel){
n+=item.price*item.num;
// 加上每项 单价*数量
}
})
return n;
// 返回n;
}
},
watch:{
"books":{
handler:function(nval){
this.all = this.books.every(item=>item.sel);
// every 每一个都返回为true,则最终返回为true,有一个返回为false最终都返回为false
// 当books有任何变化的时候都检测全选是否为true or false
},
deep:true
}
},
methods:{
delItem(item){
var re = window.confirm("你确定要删除么");
if(re){
let ind = this.books.indexOf(item);
this.books.splice(ind,1);
}
},
checkAll(){
this.books.forEach(item=>item.sel=this.all);
// 当全选按钮发生改变是 ,所有的books项目的sel值都等于 all的值
}
}
})
</script>
</body>
</html>
5. Vue 动画
1. vue它不能直接实现动画,它提供动画各阶段需要的class
2. <transition> 组件提供class
3. 在vue中,动画是在元素显示与隐藏的过程中,添加 class实现的
v-if v-else v-show
4. transition组件提供
v-enter-active 元素整个进入的过程
v-enter 元素进入的初始状态
v-enter-to 元素进入的结束状态
v-leave-active 元素整个离开的过程
v-leave 元素的离开初始状态
v-leave-to 元素的离开结束状态
自定义动画名
enter-active-class=“xxx”
leave-active-class=“xxx”
要引入第三方css animate.css
动画模式 mode
in-out 先执行进入动画,再执行离开动画
out-in 先执行离开动画,再执行进入动画
5. transition-group组件
tag 指定标签
move-class 给正在移动中的元素添加class
name 动画名称
指定进入离开class
enter-active-class
leave-active-class
案例 1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动画</title>
<script src="./js/vue.js"></script>
<style>
.fade-enter-active{ transition: all 2s ease;}
/* 元素进入的整个过程 */
.fade-leave-active{ transition: all .5s ease;}
/* 元素离开的整个过程 */
.fade-enter{opacity: 0;}
/* 进入的初始状态 */
.fade-enter-to{opacity: 1;}
/* 进入的结束状态 */
.fade-leave{opacity: 1;}
/* 离开的初始状态 */
.fade-leave-to{opacity: 0;}
/* 离开的结束状态 */
</style>
</head>
<body>
<div id="app">
<button @click="flag=!flag">切换</button> <br>
<transition name="fade">
<img src="./img/sun.jpg" v-if="flag" alt="" width="120">
</transition>
</div>
<script>
new Vue({
el:"#app",
data:{flag:true}
})
</script>
</body>
</html>
案例 2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动画</title>
<script src="./js/vue.js"></script>
<style>
/* keyframes定义关键帧 fadeIn 动画名称 */
@keyframes fadeIn {
from{opacity: 0; transform:translate(-100px,0) rotate(-180deg)}
/* 从{透明度:0,变换:位置变换(x位置-100,y位置0) 旋转变换(-180度)} */
to{opacity: 1; transform:translate(0,0) rotate(0deg)}
}
@keyframes fadeOut {
0%{opacity: 1;transform:translate(0,0) rotate(0deg)}
100%{opacity: 0;transform:translate(100px,0) rotate(180deg)}
}
.fade-enter-active{ animation: fadeIn ease 1s; }
/* 元素进入的整个过程 */
.fade-leave-active{ animation: fadeOut ease 1s;}
/* 元素离开的整个过程 */
</style>
</head>
<body>
<div id="app">
<button @click="flag=!flag">切换</button> <br>
<transition name="fade">
<img src="./img/sun.jpg" v-if="flag" alt="" width="120">
</transition>
<!-- transition是vue内置的一个组件,只要是动画都要包裹再里面 深,动态给img 再离开和进入是添加6个不同的class -->
</div>
<script>
new Vue({
el:"#app",
data:{flag:true}
})
</script>
</body>
</html>
6. animate引入动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动画</title>
<link rel="stylesheet" href="./css/animate.min.css">
<!-- 著名的css动画库引入 -->
<script src="./js/vue.js"></script>
<style>
</style>
</head>
<body>
<div id="app">
<button @click="flag=!flag">切换</button> <br>
<transition enter-active-class="slideInDown animated" leave-active-class=" hinge animated">
<img src="./img/sun.jpg" v-if="flag" alt="" width="120">
</transition>
<!-- 定义进入的动画名称 定义离开的动画名称 -->
<!-- transition是vue内置的一个组件,只要是动画都要包裹再里面 深,动态给img 再离开和进入是添加6个不同的class -->
</div>
<script>
new Vue({
el:"#app",
data:{flag:true}
})
</script>
</body>
</html>
7. 动画模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动画组</title>
<link rel="stylesheet" href="./css/animate.min.css">
<script src="./js/vue.js"></script>
<style>
.fadeOutUp{ position: absolute;}
.move{ transition: all ease .6s;}
</style>
</head>
<body>
<div id="app">
<input type="text" v-model="temp" placeholder="添加内容"
@keyup.enter="list.unshift(temp);temp=''">
<transition-group tag="div"
enter-active-class="fadeInDown animated"
leave-active-class="fadeOutUp animated"
move-class="move"
>
<div v-for="(item,index) in list" :key="item">
{{item}} <button @click="delItem(item)">x</button>
</div>
</transition-group>
</div>
<script>
new Vue({
el:"#app",
data:{
temp:"",
list:['vue','react','angular']
},
methods:{
delItem(item){
var ind = this.list.indexOf(item);
this.list.splice(ind,1)
}
}
})
</script>
</body>
</html>