文章目录
条件渲染
v-show
显示与隐藏。
v-show=true
表示显示
v-show=false
表示隐藏
实现原理:调用display
来控制显示与隐藏
<div id ="root">
<h2 v-show="false">欢迎,{{name}}</h2>
</div>
控制台显示:
v-show的值当然也可以是返回值为true或false的表达式。
v-if
v-if也可以控制显示与隐藏
v-if=true
表示显示
v-if=false
表示隐藏
实现原理:将整个结构删除
<div id ="root">
<h2 v-if="false">欢迎,{{name}}</h2>
</div>
控制台显示:
所以 v-if比v-show的消耗更大
v-else-if
和 v-if
一起使用,和 else if
的用法一样:
先判断v-if是否满足条件,如果不满足再判断 v-else-if是否满足条件
<div v-if="n===1">n=1</div>
<div v-else-if="n===2">n=2</div>
<div v-else-if="n===3">n=3</div>
v-else
和else用法一样,和 v-if,v-else-if 一起用:
当v-if,v-else-if 都不满足条件时就执行v-else
,v-else后面无需跟条件
<div v-if="n===1">n=1</div>
<div v-else-if="n===2">n=2</div>
<div v-else-if="n===3">n=3</div>
<div v-else>哈哈</div>
v-if,v-else-if 和 v-else
连用时要连着使用中间不能插入其他语句,如在v-if和v-else-if两条语句之间插入一个<div></div>
,v-if和v-else-if就来不连来了,就不能正常判断了。
eg:
<!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 type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id ="root">
<h2 v-show="true">欢迎,{{name}}</h2>
<h2>当前的n值是:{{n}}</h2>
<button @click="n++">点击n+1</button>
<div v-if="n===1">n=1</div>
<div v-else-if="n===2">n=2</div>
<div v-else-if="n===3">n=3</div>
<div v-else>哈哈</div>
</div>
<script type='text/javascript'>
Vue.config.productionTip = false;
new Vue({
el:'#root',
data: {
name:"yang",
n:0
}
})
</script>
</body>
</html>
v-show 和v-if
v-if
适用于切换频率较低的场景。
v-show
适用于切换频率较高的场景。
使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
template
<template> </template>
<template>
标签是模板的意思,它的一个优点是不会被解析到页面上,即不影响页面结构
template和v-if结合使用
<template v-if="n===1">
<h2>Hello</h2>
<h2>你好</h2>
</template>
解析结果:
外层没有template
标签
而且template
只能和v-if
联用,不能和v-show
联用。
列表渲染
v-for
循环生成:想要生成谁,就在谁身上使用v-for
遍历数组
格式:
<ul>
<li v-for="item in(或of) 要遍历的数组">
{{item}}
</li>
</ul>
一般情况下每条数据有一个对应的key值,每条数据的key值是唯一的,遍历数组时实际上还有一个参数,代表的是数组的下标,我们通常将该参数设置为key值。
<ul>
<li v-for="(item,index)in 要遍历的数组" :key="index">
{{item}}
</li>
</ul>
当然,如果有自己定义的id属性,也可以将key定义成自己设置的id属性:
<body>
<div id ="root">
<ul>
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}}-{{p.age}}
</li>
</ul>
</div>
<script type='text/javascript'>
Vue.config.productionTip = false;
new Vue({
el:'#root',
data: {
name:"yang",
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:21},
{id:'003',name:'王五',age:19}
]
}
})
</script>
</body>
遍历对象
格式:
<ul>
<li v-for="(value,key) in 对象名" :key="key">
{{key}}-{{value}}
</li>
</ul>
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<ul>
<li v-for="(value,key) in person" :key="key">{{key}}-{{value}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "yang",
person:{
name: "yang",
age: 18,
gender: "male",
}
},
});
</script>
</body>
</html>
遍历字符串
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<ul>
<li v-for="(char,index) in str" :key="index">{{index}}-{{char}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
str:"hello"
},
});
</script>
</body>
</html>
遍历指定次数
<ul>
<li v-for="(number,index) in 5" :key="index">{{index}}-{{number}}</li>
</ul>
v-for中key的作用与原理
key是由vue内部使用的,是供拟vue中虚拟DOM
作用的。
vue数据的转化——虚拟DOM
首先我们要知道vue不是直接生成真实DOM的,而是先生成虚拟DOM
,之后再转化为真实DOM
.
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<ul>
<li v-for="(p,index) in persons" :key="index">{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "yang",
persons: [
{ id: "001", name: "张三", age: 18 },
{ id: "002", name: "李四", age: 21 },
{ id: "003", name: "王五", age: 19 },
]
},
});
</script>
</body>
</html>
数据转换:
vue中key的作用
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据新数据
生成新的虚拟DOM
,随后Vue会通过key
进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
对比规则:(Diff算法)
- 旧虚拟DOM中找到了与新虚拟DOM相同的key;
- 若虚拟DOM中内容没变,直接使用之前的真实DOM
- 若虚拟DOM中内容变了,则生成新的真实DOM随后替换掉页面中之前的真实DOM.
- 旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
演示:
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<button @click.once="addPerson">点击添加赵六</button>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
<input type="text" />
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "yang",
persons: [
{ id: "001", name: "张三", age: 18 },
{ id: "002", name: "李四", age: 21 },
{ id: "003", name: "王五", age: 19 },
],
},
methods: {
addPerson() {
const p = { id: "004", name: "赵六", age: 23 };
this.persons.push(p);
},
},
});
</script>
</body>
</html>
点击添加按钮之后vue的处理过程(以处理一个节点为例子)
vue中key去index还是自定义的id
使用index出现的问题:
上述例子如果把新的数据插入到数组开头就会出现问题:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<button @click.once="addPerson">点击添加赵六</button>
<ul>
<li v-for="(p,index) in persons" :key="index">{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "yang",
persons: [
{ id: "001", name: "张三", age: 18 },
{ id: "002", name: "李四", age: 21 },
{ id: "003", name: "王五", age: 19 },
]
},
methods: {
addPerson(){
const p ={id:"004",name:"赵六",age:23}
this.persons.unshift(p)
}
},
});
</script>
</body>
</html>
添加前:
添加后:
位置不太对。
分析出现问题原因
这样不仅出现了错误,效率也非常底。因为由于key相同的名字不同,就将自己的名字又创建一边放在真实DOM中,就等于说所有的名字都是又创建一边的,没有实现复用,效率底。
小结
用index作为key可能会引发的问题:
- 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新==>界面效果没问题,但效率低。 - 如果结构中还包含输入类的DOM:
会产生错误DOM更新==>界面有问题。
使用自己定义的id就不会出现了:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<button @click.once="addPerson">点击添加赵六</button>
<ul>
<li v-for="(p,index) in persons" :key="p.id">{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "yang",
persons: [
{ id: "001", name: "张三", age: 18 },
{ id: "002", name: "李四", age: 21 },
{ id: "003", name: "王五", age: 19 },
]
},
methods: {
addPerson(){
const p ={id:"004",name:"赵六",age:23}
this.persons.unshift(p)
}
},
});
</script>
</body>
</html>
添加前:
添加后:
这是因为没个对象都有自己的id作为key值,那就不会使用vue生成的index,就不会出现”错位“现象。
选择index还是id总结
- 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
列表过滤——模糊搜索
通过条件对列表进行过滤查询:
需求:输入框输入名字,可以进行搜索显示
效果:
watch实现
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<input type="text" v-model="keyWord" placeholder="请输入名字">
<ul>
<li v-for="(p,index) in filPerson" :key="p.id">{{p.name}}-{{p.age}}-{{p.age}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
keyWord: "",
persons: [
{ id: "001", name: "张三", age: 18,sex:"男" },
{ id: "002", name: "李四", age: 21,sex:"男" },
{ id: "003", name: "王五", age: 19,sex:"男" },
{ id: "004", name: "张浩", age: 19,sex:"男" },
{ id: "005", name: "小四", age: 19,sex:"男" },
],
filPerson:[]
},
watch:{
keyWord:{
immediate:true,
handler(newValue){
this.filPerson = this.persons.filter((p)=>{
// 过滤名字中包含搜索值得数据
// 空串中都包含空串""
return p.name.indexOf(newValue)!=-1
})
}
}
}
});
</script>
</body>
</html>
计算属性实现
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<input type="text" v-model="keyWord" placeholder="请输入名字">
<ul>
<li v-for="(p,index) in filPerson" :key="p.id">{{p.name}}-{{p.age}}-{{p.age}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 计算属性实现
new Vue({
el:'#root',
data: {
keyWord: "",
persons: [
{ id: "001", name: "张三", age: 18,sex:"男" },
{ id: "002", name: "李四", age: 21,sex:"男" },
{ id: "003", name: "王五", age: 19,sex:"男" },
{ id: "004", name: "张浩", age: 19,sex:"男" },
{ id: "005", name: "小四", age: 19,sex:"男" },
]
},
computed:{
filPerson(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord)!=-1
})
}
}
})
</script>
</body>
</html>
列表排序
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<input type="text" v-model="keyWord" placeholder="请输入名字" />
<button @click="sortType=2">年龄升序</button>
<button @click="sortType=1">年龄降序</button>
<button @click="sortType=0">原顺序</button>
<ul>
<li v-for="(p,index) in filPerson" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
keyWord: "",
sortType: 0, //0原顺序,1降序,2升序
persons: [
{ id: "001", name: "张三", age: 18, sex: "男" },
{ id: "002", name: "李四", age: 21, sex: "男" },
{ id: "003", name: "王五", age: 19, sex: "男" },
{ id: "004", name: "张浩", age: 30, sex: "男" },
{ id: "005", name: "小四", age: 19, sex: "男" },
],
},
computed: {
filPerson() {
const arr = this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) != -1;
});
if (this.sortType) {
arr.sort((a, b) => {
return this.sortType === 1 ? b.age - a.age : a.age - b.age;
});
}
return arr;
},
},
});
</script>
</body>
</html>