1. 条件渲染
-
v-if
- v-if=“表达式”
- v-else-if = “表达式”
- v-else = “表达式”
适用于:切换频率较低的场景
特点:不显示dom元素,直接被删除
注意:v-if和v-else-if、v-else一起使用,但要求结构不能被打断
v-if和template一起使用, v-show不可以 -
v-show v-show = “表达式” 适用于: 切换频率较高的场景 特点: 不展示dom元素,未被移除,仅仅是样式隐藏
-
备注:使用v-if时,元素可能无法取到,v-show一定可以获取到
示例:
<!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>
</head>
<body>
<div id="app">
<!-- v-show: 控制元素style样式中display属性实现显示与隐藏 -->
<p v-show="1 !== 3">这是v-show文本</p>
<p v-show="false">这是v-show文本</p>
<hr>
<!-- v-if: 对元素的删除与渲染 -->
<p v-show="1 !== 3">这是v-if文本</p>
<p v-if="true">这是v-if文本</p>
<hr>
<!-- v-if, v-else 的使用 -->
<button @click="n++">点击if事件</button>
<!-- <p v-if="n === 1"> 8:00</p>
<p v-if="n === 1"> 9:00</p>
<p v-if="n === 3"> 10:00</p> -->
<p v-if="n === 1"> 8:00</p>
<p v-else-if="n === 2"> 9:00</p>
<p v-else-if="n === 3"> 10:00</p>
<p v-else>其他时间</p>
<hr>
<!--v-if可以和 template使用,v-show不可以 -->
<!-- <p v-if="n === 1"> 小红</p>
<p v-if="n === 1"> 小李</p>
<p v-if="n === 1"> 小王</p> -->
<!-- template模板,不改变页面结构 -->
<!-- <template v-show="n === 1"> -->
<template v-if="n === 1">
<p> 小红</p>
<p> 小李</p>
<p> 小王</p>
</template>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
n: 0,
},
})
</script>
</body>
</html>
2. 列表渲染
- v-for
- 用于展示列表数据
- 语法:v-for=“(val, index) in arr” :key = yyy
- 可遍历:数组,对象,字符串(用的很少),指定次数(用的很少)
示例:
<!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>
</head>
<body>
<div id="app">
<!-- 遍历数组 -->
<h2>人员列表</h2>
<ul>
<li v-for="(p, index) in persons" :key="index">
{{ p.name }} - {{ p.age }}
</li>
</ul>
<hr>
<!-- 遍历对象 -->
<ul>
<li v-for="(v, index) in obj" :key="index">
{{ index }} - {{ v }}
</li>
</ul>
<hr>
<!-- 遍历字符串(比较少用) -->
<ul>
<li v-for="(v, index) in 'ahggg'" :key="index">
{{ index }} - {{ v }}
</li>
</ul>
<hr>
<!-- 遍历数字(比较少用) -->
<ul>
<li v-for="(v, index) in 5" :key="index">
{{ index }} - {{ v }}
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
persons: [
{ id: '001', name: '小红', age: 19 },
{ id: '002', name: '小明', age: 20},
{ id: '003', name: '小亮', age: 21}
],
obj: {
name: '小丽',
age: 19,
sex: '女'
}
}
})
</script>
</body>
</html>
-
key作用与原理
- 虚拟DOM中key的作用:
- key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
- 随后Vue进行【新虚拟DOM】和【旧虚拟DOM】的差异比较,比较规则如下:
- 对比规则:
- 旧虚拟DOM中找到与新虚拟DOM相同的key:
- 若虚拟DOM中的内容没有变,直接使用之前的真实DOM
- 若虚拟DOM中的内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
- 旧虚拟DOM中未找到与新虚拟DOM相同的key:
- 创建新的真实DOM,随后渲染到页面
- 创建新的真实DOM,随后渲染到页面
- 旧虚拟DOM中找到与新虚拟DOM相同的key:
- 虚拟DOM中key的作用:
-
用index作为key可能会引发的问题:
- 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
- 会产生没有必要的真实DOM更新 ==>界面效果没问题,但效率低
- 如果结构中还包含输入类的DOM:
- 会产生错误的DOM更新,页面有问题
- 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
-
开发中如何选择key:
- 最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号等唯一值
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表用于展示,使用index作为key是没有问题的
示例:
<!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>
</head>
<body>
<div id="app">
<!-- 唯一值作为key值: 逆序添加 -->
<button @click.once="handleClickUnshiftPerson">unshift添加person</button>
<ul>
<!-- <li v-for="(p, index) in persons" :key="p.id"> -->
<li v-for="(p, index) in persons" :key="index">
{{ p.name }} - {{p.age }}
<input type="text">
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
persons: [
{ id: 1, name: '小红', age: 19 },
{ id: 2, name: '小梁', age: 20 },
{ id: 3, name: '小名', age: 21 },
]
},
methods: {
handleClickUnshiftPerson(){
this.persons.unshift({id: 4, name: '小丽', age:22})
}
},
})
</script>
</body>
</html>
3. 收集表单数据
- 若:
<input type = "text"/>
, 则v-model收集的是value值,用户输入的就是value值。 - 若:
<input type = "radio"/>
, 则v-model收集的是value值,且要给标签配置value值。 - 若:
<input type = "checkbox"/>
- 没有配置input的value属性,v-model收集的就是checked(勾选 or 未勾选, 是布尔值)
- 配置input的value属性:
- v-model 的初始值是非数组,那么收集的就是checked(勾选 or 未勾选, 是布尔值)
- v-model 的初始值是数组,那么收集的就是value组成的数组
- 备注:v-model的三个修饰符:
- lazy: 失去焦点再收集数据
- number: 输入字符串转为有效的数字
- trim: 输入首尾空格过滤
示例:
<!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>
</head>
<body>
<div id="app">
<form @submit.prevent="demo">
<!-- 完整写法 -->
<!-- <label for="demo">账号:</label> -->
<!-- <input type="text" id="demo"> -->
账号:<input type="text" v-model.trim="obj.account">1{{ obj.account }}2<br><br>
密码:<input type="password" v-model="obj.password"> {{ obj.password }}<br><br>
年龄:<input type="number" v-model.number="obj.age"> {{ typeof(obj.age) }}<br><br>
性别:
男<input type="radio" name="sex" v-model="obj.sex" value="male">
女<input type="radio" name="sex" v-model="obj.sex" value="female">
{{ obj.sex }}<br><br>
爱好:
<!-- 多选框的初始值影响v-model收集回来的值 -->
学习<input type="checkbox" v-model="obj.hobby" value="study" id="demo">
打游戏<input type="checkbox" v-model="obj.hobby" value="game">
读书<input type="checkbox" v-model="obj.hobby" value="read">
{{ obj.hobby }}<br><br>
家乡:
<select v-model="obj.city">
<option value="">请选择家乡</option>
<option value="sjz">石家庄</option>
<option value="xt">邢台</option>
<option value="hd">邯郸</option>
<option value="cd">承德</option>
</select>
{{ obj.city }}
<br><br>
其他信息:
<textarea v-model.lazy="obj.other"></textarea> {{ obj.other }}
<br><br>
<input v-model="obj.argee" type="checkbox"> 阅读并接受<a href="http://www.baidu.com">《用户协议》</a> {{ obj.argee }}
<br><br>
<button>提交</button>
</form>
</div>
<script>
const vm = new Vue({
el: "#app",
data:{
obj:{
account: '',
password: '',
age: 18,
sex: 'female',
hobby: [],
city:'',
other: '',
argee: false
}
},
methods: {
demo(){
console.log(this.obj);
}
},
})
</script>
</body>
</html>