别让我抓到你不学Vue,不然你可遭老罪咯!
目录
一、计算属性
1.计算属性原理:底层借助了Object.definePropert中的getter和setter方法
2.如何使用计算属性:
(1)在vue实例对象中添加新的配置对象:computed:{
计算属性名:{
get(){},
set(value){}
}
}
3.当我们读取计算属性的名时,自动调用get方法,完成相应的操作
4.get什么时候被调用:(1)初次读取计算属性名时,
(2)计算属性所依赖的属性有一个发生变化,get就会被重新调用
5.get存在缓存机制,并且经常去使用,而set由于很少在console中去对计算属性进行修改,所以set按需求来使用。
6.计算属性简写:若计算属性中只包含get不包含set,可以进行简写。function就相当于get,直接在里面写计算属性的相关操作就可以,并且在调用计算属性时,不用加小括号,因为他是属性不是方法。
例如:computed:{
fullName:function(){
console.log("get被读取了")
return this.firstName+'-'+this.lastName
}
}
注:split可以分割数组。例如:split(‘-’)
案例:
<body>
<!--创建容器 -->
<div id="box">
姓:<input type="text" v-model:value="firstName"><br>
名:<input type="text" v-model:value="lastName"><br>
<!-- 全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br> -->
全名:<span>{{fullName}}</span>
</div>
<script>
const vm=new Vue({
el:"#box",
data:{
firstName:"王",
lastName:"耀萱"
},
computed:{
// 若确定我们需求只读不改,可以简写,function就当get用,fullName不需要加小括号,因为读的是计算属性
fullName:function(){
console.log("get被读取了")
return this.firstName+'-'+this.lastName
}
// set(value){
// console.log("fullName被修改为"+value)
// const arr= value.split('-')
// this.firstName=arr[0]
// this.lastName=arr[1]
// }
}
})
7.计算属性的优势:与methods实现相比,内部有缓存机制(复),效率更高,调试方便。
8.案例:根据姓和名的变化,动态显示全名的变化
<body>
<!--创建容器 -->
<div id="box">
姓:<input type="text" v-model:value="firstName"><br>
名:<input type="text" v-model:value="lastName"><br>
<!-- 全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br> -->
全名:<span>{{fullName}}</span>
</div>
<!-- 计算属性原理:底层借助了Objcet.defineproperty方法提供的getter和setter。 -->
<!-- 优势:与methods实现相比,内部有缓存机制(复),效率更高,调试方便。-->
<!-- 创建vue实例对象 -->
<script>
const vm=new Vue({
el:"#box",
data:{
// data配置中的就是属性
firstName:"王",
lastName:"耀萱"
},
// 全新的配置项computed计算属性
computed:{
fullName:{
// 当有人读取fullName时,get就会被自动调用,且返回值是fullName的值
// get什么时候调用?(1)初次读取fullname,(2)所依赖的数据发生变化时,只要姓或者名改变,get就会被重新被调用
// get存在缓存机制,并且常用
get(){
console.log("get被读取了")
return this.firstName+'-'+this.lastName
},
// set什么时候调用?
// 看需求分析,如果计算属性需要被修改,可以设置set函数
set(value){
console.log("fullName被修改为"+value)
// 利用split拆分数组
const arr= value.split('-')
this.firstName=arr[0]
this.lastName=arr[1]
// 业务流程:在console中利用vm.fullname="xx-xx"修改名字,修改后调用set方法将值传给数组进行拆分
// 拆分后分别将姓和名赋值给firstName和lastName,之后get读取
}
}
}
})
</script>
二、监视属性
1.监视属性主要是在console中监视data中的属性或者是计算属性的变化。
2.使用方法:在data中添加一个配置对象(用于以及知道需要对哪个属性进行监视)
watch:{
immdiate:true //初始化时让handler调用一下
属性名:{
handler(newValue,oldValue){
console.log("info被修改了",newValue,oldValue)
}
}
}
3.handler什么时候调用?
当属性发生改变时被调用,并且把修改前的值和修改后的值返回给你。
4.监视的另一种写法(一般用于写代码时不知道需要监视哪个属性):写在vue实例外面
vm.$watch('需要监视的属性名',{
immdiate:xxx
handler(newValue,oldValue)
})
注:immidiate是在监测到属性变化之前,自动调用一次。
5.案例:
<body>
<div id="box">
<h2>今天天气很{{change}}</h2>
<!-- 绑定事件的时候@xxx="yyy" yyy可以写一些简单得语句 -->
<button @click="cut">切换天气</button>
</div>
<script>
// 监视属性既可以监视data中的属性也可以监视计算属性,在console中可以
const vm=new Vue({
el:"#box",
data:{
isHot:true
},
methods:{
cut(){
this.isHot=!this.isHot
}
},
computed:{
change:function(){
return this.isHot?'炎热':'凉爽'
}
} ,
// 声明一个监视配置对象
// watch:{
// // 初始化时让handler调用一下
// immediate:true,
// isHot:{
// // handler什么时候调用?当isHot发生改变时,并且把修改前后的值给你。
// handler(newValue,oldValue){
// console.log("info被修改了",newValue,oldValue)
// }
// },
// }
})
// 监视的另一种方式
vm.$watch('isHot',{
immediate:true,
handler(newValue,oldValue){
console.log("info被修改了",newValue,oldValue)
}
})
</script>
6.深度监视:为了监视多级结构中的所有属性值,需要引入新的配置对象,格式:‘属性名’,在其中引入了deep,默认为false,true表示开启深度监视,开启后深度监视对象内部值得改变。例如:若监测多级结构肿某个属性的变化,只监测a不监测b。
'numbers.a':{
handler(newValue,oldValue){
console.log("a被修改了")
}
}
案例:
<body>
<div id="box">
<h2>今天天气很{{change}}</h2>
<!-- 绑定事件的时候@xxx="yyy" yyy可以写一些简单得语句 -->
<button @click="cut">切换天气</button>
<br>
<h3>a的值是{{numbers.a}}</h3>
<button @click="numbers.a++">点我让a+1</button>
<h3>b的值是{{numbers.b}}</h3>
<button @click="numbers.b++">点我让b+1</button>
{{numbers.c.d.e}}
</div>
<script>
// 监视属性既可以监视data中的属性也可以监视计算属性,在console中可以
const vm=new Vue({
el:"#box",
data:{
isHot:true,
numbers:{
a:1,
b:1,
c:{
d:{
e:100
}
}
}
},
methods:{
cut(){
this.isHot=!this.isHot
}
},
computed:{
change:function(){
return this.isHot?'炎热':'凉爽'
}
} ,
watch:{
'isHot':{
immediate:true,
handler(newValue,oldValue){
console.log("isHot被修改了",newValue,oldValue)
}
},
// // 监测多级结构中某个属性的变化:只监测a不监测b
// 'numbers.a':{
// handler(newValue,oldValue){
// console.log("a被修改了")
// }
// },
'numbers':{
deep:true,//开启深度监视可以监视对象内部值得改变,vue中的watch不能监测到对象内部值得改变
handler(newValue,oldValue){
console.log("a被修改了")
}
}
}
})
</script>
</body>
三、监视属性简写
1.在不需要immdiate和deep属性情况下,监视属性可以简写,包含如下两种简写形式。
(newValue,oldValue)相当于handler
(1)方法一:
watch{
’监视属性名’(newValue,oldValue) {
console.log(’xxx’)
}
}
如果被监测的属性发生了变化,自动调用handler方法,进行触发事件。
(2)方法二:
声明在Vue实例外。vm.$watch(’监视属性名’,function(newValue,oldValue){
console.log(’xxx’)
})
如果明确需要指定哪些是监视属性,采用方法一,如果一时不知道监视哪些属性,采用方法二。
2.handler中的属性是可变的。
3.案例:
<div id="box">
<h2>今天天气很{{change}}</h2>
<button @click="cut">切换天气</button>
</div>
<script>
const vm=new Vue({
el:"#box",
data:{
isHot:true,
},
methods:{
cut(){
this.isHot=!this.isHot
}
},
computed:{
change:function(){
return this.isHot?'炎热':'凉爽'
}
} ,
watch:{
//若配置项中只有handler,才能简写
// 'isHot':{
// // immediate:true,
// // deep:true,
// handler(newValue,oldValue){
// console.log("isHot被修改了",newValue,oldValue)
// }
// },
//isHot为需要监视的属性,函数当handler使用
// 'isHot'(newValue,oldValue){
// console.log("isHot被修改了",newValue,oldValue)
// }
}
})
//监视属性的另一种方法的简写
vm.$watch('isHot',function(newValue,oldValue){
console.log("isHot被修改",newValue,oldValue)
})
</script>
四、computed和watch的区别
1.watch中可以做一些异步的操作,例如:定时器。
2.computed中需要retrun一个值,在其中不能设置箭头函数。
3.计算属性不能开启异步维护数据,他需要依赖返回值,而watch可以进行一步操作不需要返回值
4.两个重要的小原则:
(1).所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
(2)所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或组件实例对象。
5.案例
<div id="box">
姓:<input type="text" v-model:value="firstName"><br>
名:<input type="text" v-model:value="lastName"><br>
全名:<span>{{fullName}}</span>
</div>
<script>
const vm=new Vue({
el:'#box',
data:{
firstName:'张',
lastName:'三',
fullName:'张-三'
},
watch:{
'firstName':{
handler(newValue){
setTimeout(() =>{ //设置定时器,可以延时1秒
this.fullName=newValue+'-'+this.lastName
},1000);
}
},
'lastName':{
handler(newValue){
this.fullName=this.firstName+'-'+newValue
}
},
}
})
</script>
五、绑定class(常用)
1.将固定不变的样式添加到class中,将动态绑定的样式声明在:class中,把不变化的样式,正常写,变化的动态绑定
2当不清楚样式的类名,可以用一个字符串声明在:class=“字符串名”,在data中声明一个该字符串名并赋予style。适用于点击切换样式
3.当不清楚样式的个数,名字叶不确定时,可以声明一个数组,:class=“arr”,在data中声明一个数组,里面包含样式的名字。适用于一个div利用多个样式进行渲染。
4.既清楚样式的名字,又清楚样式的个数,可以声明一个对象,例如 :class=“obj”,在data中声明一个obj对象,利用true /false来控制样式的开启,适合将多个样式渲染在一个标签上。
5.绑定style样式:利用对象的写法,在data中配置该对象,其中style对象中的属性不能瞎写,必须是css中存在的属性。
6.案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="vue.js"></script>
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy{
width: 400px;
height: 100px;
background-color: coral;
}
.sad{
width: 400px;
height: 100px;
background-color: rgb(27, 196, 27);
}
.romantic{
width: 400px;
height: 100px;
background-color: rgb(255, 37, 139);
}
</style>
</head>
<body>
<div id="box">
<!-- class常用 -->
<!-- 绑定class样式,字符串写法,适用于:样式的类名不确定,需要动态指定 -->
<div class="basic" :class="a" @click="changeMood">{{name}}</div><br>
<!-- 一个div利用多个样式进行渲染 ,利用数组的方式-,适用于,绑定样式的个数不确定,名字也不确定-->
<div class="basic" :class="arr" >{{name}}</div><br>
<!-- 样式的名字和个数都确定,利用对象的方式,但要动态决定用不用 ,在data中配置该对象-->
<div class="basic" :class="obj" >{{name}}</div><br>
<!-- 绑定style样式,利用对象的写法,在data中配置该对象,其中style对象中的属性不能瞎写,必须是css中存在的属性 -->
<div class="basic" :style="styleObj" >{{name}}</div><br>
<!-- 把不变化的样式,正常写,变化的动态绑定 -->
</div>
<script>
const vm=new Vue({
el:'#box',
data:{
name:'djtu',
a:'happy',
arr:['basic','sad','happy'],
obj:{
basic:false,
sad:true
},
styleObj:{
fontSize:'40px',
color:'red'
}
},
methods:{
// 实现随机切换背景色
changeMood(){
const arr=['happy','sad','romantic']
const index= Math.floor(Math.random()*3)
this.a=arr[index]
}
}
})
</script>
</body>
</html>
六、条件渲染
1.v-show:动态显示/隐藏,不会被移除,仅仅是使样式进行了隐藏
(1)适用于:切换频率较高的场景
2.v-if:动态显示/隐藏,并且不展示的元素会被移除
(1)适用于:切换频率较低的场景
(2)写法:
v-if="表达式"
.v-else-if="表达式"
v-else="表达式"
挨个表达式判断,满足条件就执行标签。
3.template标签:使用template标签不会破坏结构,并且只能配合v-if使用。
4.案例:
<div id="box">
<h2>当前的n值是{{n}}</h2>
<button @click="n++">点我n+1</button>
<!-- v-show 动态显示或隐藏 -->
<!-- v-if 动态显示或隐藏,若为false则整个语句结构都不存在-->
<!-- <h2 v-show="a">欢迎来到{{name}}</h2>
<h2 v-if="true">拜拜{{name}}</h2> -->
<!-- <div v-show="n===1">angular</div>
<div v-show="n===2">react</div>
<div v-show="n===3">vue</div> -->
<!-- v-if成立,页面展示数据,若v-else-if成立 展示数据-->
<div v-if="n===1">angular</div>
<div v-else-if="n===2">react</div>
<div v-else-if="n===3">vue</div>
<div v-else=>哈哈哈</div>
<!-- 使用template的优势:结构不会被破坏,并且只能配合v-if使用 -->
<template v-if="n===1">
<h2>你好</h2>
<h2>尚硅谷</h2>
<h2>北京</h2>
</template>
</div>
<script>
const vm=new Vue({
el:'#box',
data:{
name:'djtu',
n:0
}
})
</script>
七、列表渲染
1.数组(包含对象)进行渲染:利用v-for=“形参 in data中的数组名” :key=“数组中的唯一标识(例如id,身份号等)也可以是索引值”,若不加key,默认key为索引值,推荐一般加上key
2.遍历对象:遍历在data中声明对象中的每一个属性
3.案例:
<div id="box">
<ul>
<!-- 遍历数组;如果想生成多个相同结构的数据,利用v-for,p相当于形参,persons为数组里面存放的对象 -->
<!-- :key设置唯一标识 -->
<!-- <li v-for="p in persons" :key="p.id">{{p.id}}-{{p.name}}</li> -->
<!-- <li v-for="p in persons" :key="p.id">{{p.id}}-{{p.name}}</li> -->
<li v-for="p in persons" :key="p.index">{{p.name}}-{{p.age}}</li>
</ul>
<h2>汽车信息</h2>
<!-- 遍历对象 -->
<ul>
<li v-for="(value,k) in car" ::key="k">
{{k}}-{{value}}
</li>
</ul>
</div>
<script>
const vm=new Vue({
el:"#box",
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李丽',age:28},
{id:'004',name:'王强',age:38}
],
car:{
name:'奥迪A8',
price:80
}
}
})
</script>
4.key的机理:(
(1)尽量不要把key设置成index,效率低并且当逆向添加或删除数据时,会出现索引值的错乱。
(2)旧虚拟DOM中找到了与新虚拟DOM相同的KEY,若虚拟DOM中的内容没变,直接使用之前的真实DOM,若虚拟DOM中的内容改变,则生成新的真实DOM随后替换掉页面中之前的真实DOM
八、列表过滤
1.利用watch监视属性实现模糊查询:
(1)filter实现过滤操作,把不符合条件的过滤掉
(2)indexOf判断是否包含该元素,包含返回元素的索引值,不包含返回-1
2.案例:
<div id="box">
<!-- placeholder和value的区别? -->
<input type="text" placeholder="输入姓名" v-model:value="keyWord">
<ul>
<li v-for="e in filEmployee" :key="e.id">
{{e.id}}-{{e.name}}-{{e.address}}
</li>
</ul>
</div>
<script>
const vm=new Vue({
el:'#box',
data:{
keyWord:'',
employee:[
{id:'001',name:'高启强',address:'京海市'},
{id:'002',name:'高启盛',address:'公安局'},
{id:'003',name:'高启强',address:'京海市'},
{id:'004',name:'李有田',address:'莽村'}
],
filEmployee:[]
},
watch:{
'keyWord':{
immediate:true,
handler(newValue){
// filter实现过滤,空字符串也包含在数组中
this.filEmployee=this.employee.filter((e)=>{
// indexOf判断是否包含该元素,包含返回元素的索引位置,不包含返回-1
return e.name.indexOf(newValue) !== -1
})
}
}
}
})
</script>
3.利用计算属性实现列表过滤并且设置排序功能
<div id="box">
<!-- placeholder和value的区别? -->
<h2>人员列表</h2>
<input type="text" placeholder="输入姓名" v-model:value="keyWord">
<button @click="sortType=2">年龄升序</button>
<button @click="sortType=1">年龄降序</button>
<button @click="sortType=0">原顺序</button>
<ul>
<li v-for="(e,index) of filEmployee" :key="e.id">
{{e.id}}-{{e.name}}-{{e.address}}-{{e.age}}
</li>
</ul>
</div>
<script>
const vm=new Vue({
el:'#box',
data:{
keyWord:'',
sortType:0,//0原顺序
employee:[
{id:'001',name:'高启强',address:'京海市',age:21},
{id:'002',name:'高启盛',address:'公安局',age:24},
{id:'003',name:'高启强',address:'京海市',age:36},
{id:'004',name:'李有田',address:'莽村',age:27}
]
},
computed:{
filEmployee(){
const arr= this.employee.filter((e)=>{
return e.name.indexOf(this.keyWord)!==-1
})
if(this.sortType){
arr.sort((p1,p2)=>{
return this.sortType===1?p2.age-p1.age:p1.age-p2.age
})
}
return arr
}
}
})
</script>