03:模板语法(下)
本文介绍了在Vue中使用条件判断和循环遍历的方法,包括v-if、v-else-if、v-else、v-show、v-for遍历数组和对象,以及组件的key属性的应用。通过实例和案例展示了各种情况下的效果和注意事项。

Vue自学笔记3:模板语法(下)
本文章为观看B站codewhy老师教学视频自学vuejs过程中记录的笔记,对视频进行了清晰的整理。
ps:最全最新Vue、Vuejs教程,从入门到精通_哔哩哔哩_bilibili(附上视频链接!)
5. 条件判断
5.1 v-if、v-else-if、v-else
总结: 该案例使用v-if这些标签并不合适, 使用计算属性( computed )更好
5.2 条件渲染案例
代码:
<body>
<div id="app">
<span>{{type}}:</span>
<input type="text" :value="type">
<button @click="change">切换类型</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
type: '用户账号'
},
methods: {
change() {
if (this.type === '用户账号') {
this.type = '邮箱地址'
}
else {
this.type = '用户账号'
}
}
}
})
</script>
</body>
5.3 v-show
6. 循环遍历
6.1 v-for遍历数组
6.2 v-for遍历对象
效果:
6.3 组件的key属性
在用v-for更新已渲染的元素列表的时候,会使用就地复用的策略;这就是说列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改了就重新渲染,不然就复用之前的元素。总结一下,就是通过key值来提升渲染的效率。
例子:
const list = [
{
id:1,
name:'test'
},
{
id:2,
name:'test2',
},
{
id:3,
name:'test3'
},
]
<div v-for="(item,index) in list :key="index">{{item.name}}</div>
这个场景在我们开发的时候经常会碰到,因为不加key,vue现在会直接报错,所以我使用index作为key; 下面再举两个例子来看数据更新后的情况。
1.在最后一条数据后再加一条数据
const list = [
{
id: 1,
name: 'test1',
},
{
id: 2,
name: 'test2',
},
{
id: 3,
name: 'test3',
},
{
id: 4,
name: '我是在最后添加的一条数据',
},
]
此时前三条数据直接复用之前的,新渲染最后一条数据,此时用index
作为key
,没有任何问题;
2.在中间插入一条数据
const list = [
{
id: 1,
name: 'test1',
},
{
id: 4,
name: '我是插队的一条数据',
}
{
id: 2,
name: 'test2',
},
{
id: 3,
name: 'test3',
},
]
此时更新渲染数据,通过index
定义的key
去进行前后数据的对比,发现
之前的数据 之后的数据
key: 0 index: 0 name: test1 key: 0 index: 0 name: test1
key: 1 index: 1 name: test2 key: 1 index: 1 name: 我是插队的一条数据
key: 2 index: 2 name: test3 key: 2 index: 2 name: test2
key: 3 index: 3 name: test3
可以发现除了第一条数据可以复用以外,另外三条数据都需要重新渲染,因为key值发生了变化; 这时候就可以体现出了一个效率问题,只插入了一条数据,却要重新渲染三条数据;
所以我们需要可以想办法让数组中不会变化的数据的key值也不变,所以不能通过index来设置key值,应该设置一个唯一的id来标识数据的唯一性;我们修改之后再来对比一下渲染的效率:
之前的数据 之后的数据
key: 1 id: 1 index: 0 name: test1 key: 1 id: 1 index: 0 name: test1
key: 2 id: 2 index: 1 name: test2 key: 4 id: 4 index: 1 name: 我是插队的那条数据
key: 3 id: 3 index: 2 name: test3 key: 2 id: 2 index: 2 name: test
key: 3 id: 3 index: 3 name: test3
总结: 对比可以发现,只有一条数据发生了变化,因为其他数据的id都没变,所以key值也没变,所以只需要渲染这一条新的数据即可 所以一般推荐使用id作为key值来配合v-for使用
下面大致从虚拟DOM的Diff算法实现的角度去解释一下:
vue和react的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设:
- 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
- 同一层级的一组节点,他们可以通过唯一的id进行区分。基于这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)
引用React’s diff algorithm中的例子:
当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。 比如一下这个情况:
我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:
即把C更新成F,D更新成C,E更新成D,最后再插入E,很没有效率
所以我们需要使用key来给每个节点做一个唯一标识符,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
所以用一句话来概括,key的作用主要是为了高效的更新虚拟DOM。
6.4 检测数组更新
通过索引值修改数组中的元素
是无法做到响应式的,既视图不会实时更新
<body>
<div id="app">
<ul>
<li v-for="v in letters">{{v}}</li>
</ul>
<button @click="btnlick">按钮</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
letters: ['a', 'b', 'c', 'd']
},
methods: {
btnclick() {
//push()尾部插入
this.letters.push('abc')
//pop()尾部删除
this.letters.pop()
//unshift()头部插入
this.letters.unshift('abc')
//shift()头部删除
this.letters.shift()
//splice():删除元素/插入元素/替换元素
// 删除元素:splice(start,num) start是开始删除的第一个位置,num是删除的元素数量(num不写则默 认删除start后所有元素)
// 替换元素:splice(start,num,'a','b') start是开始替换的第一个位置,num是插入的元素数量,后面 跟num个替换的元素
// 插入元素:splice(start,0,'a','b') start是开始插入的第一个位置,第二个参数置0,后面跟待插入 的元素
this.letters.splice(2)
//sort()数组排序
this.letters.sort()
//reverse()数组反转
this.letters.reverse()
}
}
})
</script>
</body>
7.(补充) 高阶函数
forEach 是 ES5 中操作数组的一种方法,主要功能是遍历数组,该语句需要一个回调函数,作为参数。回调函数的形参,依次为,value:遍历的数组内容;index:对应的数组索引,array:数组本身。
<script type="text/javascript">
// 分别对应:数组元素,元素的索引,数组本身
var arr = ['a','b','c'];
arr.forEach(function(value,index,array){
console.log(value);
console.log(index);
console.log(array);
})
</script>
8. v-model
8.1 v-model原理
8.2 v-model:radio(单选)
单选框:
<body>
<div id="app">
<input type="radio" value="男" v-model="sex"> 男
<input type="radio" value="女" v-model="sex"> 女
//使用v-model就不需要都取一个name了
<br>
{{sex}}
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: '你好啊',
sex:'男' //sex赋初值为男,可以实现单选框默认选择男
}
})
</script>
</body>
8.3 v-model:checkbox(复选)
单个勾选框: v-model即为布尔值。 此时input的value并不影响v-model的值。 多个复选框: 当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。 当选中某一个时,就会将input的value添加到数组中。
<body>
<div id="app">
<!-- 单个复选框 -->
<label for="">
<input type="checkbox" v-model="isagree">同意协议
</label>
<h2>
isagree是:{{isagree}}
</h2>
<!-- 多个复选框 -->
<input type="checkbox" v-model="hobbies" value="篮球" id="aa"> <label for="aa">篮球</label>
<input type="checkbox" v-model="hobbies" value="足球" id="bb"> <label for="bb">足球</label>
<input type="checkbox" v-model="hobbies" value="橄榄球" id="cc"> <label for="cc">橄榄球</label>
<input type="checkbox" v-model="hobbies" value="棒球" id="dd"> <label for="dd">棒球</label>
<h2>
你选择了:{{hobbies}}
</h2>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
isagree: false, //默认为不同意
hobbies: ["足球"] //默认选了足球
}
})
</script>
</body>
8.4 v-model:select
和checkbox一样,select也分单选和多选两种情况。 单选:只能选中一个值。 v-model绑定的是一个值。 当我们选中option中的一个时,会将它对应的value赋值到mySelect中 多选:可以选中多个值。 v-model绑定的是一个数组。 当选中多个值时,就会将选中的option对应的value添加到数组mySelects中
<body>
<div id="app">
<!-- 选择一个 -->
<select name="selectFruit" id="" v-model="fruit">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="榴莲">榴莲</option>
<option value="葡萄">葡萄</option>
</select>
<h2>你选择的水果是:{{fruit}}</h2>
<!-- 选择多个 -->
<select name="selectFruits" id="" v-model="fruits" multiple>
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="榴莲">榴莲</option>
<option value="葡萄">葡萄</option>
</select>
<h2>你选择的水果有:{{fruits}}</h2>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
fruit: '香蕉',//默认选择香蕉
fruits: []
}
})
</script>
</body>
效果:
8.5 值绑定
<body>
<div id="app">
<!-- 多个复选框 -->
<input type="checkbox" v-model="hobbies" value="篮球" id="aa"><label for="aa">篮球</label>
<input type="checkbox" v-model="hobbies" value="足球" id="bb"><label for="bb">足球</label>
<input type="checkbox" v-model="hobbies" value="橄榄球" id="cc"><label for="cc">橄榄球</label>
<input type="checkbox" v-model="hobbies" value="棒球" id="dd"><label for="dd">棒球</label>
<h2>
你选择了:{{hobbies}}
</h2>
<!-- 值绑定 -->
<label v-for="item in hobbies111" :for="item">
<input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
</label>
<!--:id="item" :value:"item"就是值绑定-->
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
hobbies: ["足球"], //默认选了足球
hobbies111: ['篮球', '足球', '橄榄球', '棒球']
}
})
</script>
</body
效果:
8.6 修饰符
<body>
<div id="app">
<!-- 未使用lazy修饰符:实时绑定 -->
<input type="text" v-model="message">
<!-- 使用lazy修饰符:失去焦点,按下回车时绑定 -->
<input type="text" v-model.lazy="message">
<h2>{{message}}</h2>
<!-- input标签里输入的是number类型,但是其实age是一个string类型 -->
<input type="number" v-model="age">
<!-- 当希望age在后面使用时是nuber类型时 -->
<input type="number" v-model.number="age">
<h2>{{typeof(age)}}</h2>
<!-- 去除两端的空格 -->
<input type="text" v-model.trim="name">
<h2>{{name}}</h2>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: 'hello,world',
age: '',
naem:''
}
})
</script>
</body>