vue学习第二天
经过前一天的知识点学习,那么今天我们主要以案例练习为主,多敲代码,提高代码量才是学习编程的王道。
1、key的作用
假设现在有一个需求,在页面循环data中的数组。很简单,有手就行,分分钟写出来。
<div id="app">
<ul>
<li v-for="(item, i) in list">
<input type="checkbox"> {{item.name}}
</li>
</ul>
<script>
var vm = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: '诡秘之主' },
{ id: 2, name: '诛仙' },
{ id: 3, name: '惊悚乐园' }
]
}
});
</script>
</div>
写完之后,需求进行升级。要求可以手动在列表的头部添加一本书。好,没问题,有手就行,分分钟写出来。
HTML中添加如下代码:
<form>
<input type="text" v-model="name">
<input type="submit" value="添加" @click.prevent="add">
</form>
因为我们需要获取输入框中输入的书籍名称,所以这里使用了v-model数据双向绑定。
那么就需要在vue实例中的data属性中添加一个name属性
data: {
list: [
{ id: 1, name: '诡秘之主' },
{ id: 2, name: '诛仙' },
{ id: 3, name: '惊悚乐园' }
],
name:""
}
接下来在vue实例的methods属性中实现添加方法。
methods: {
add(){
let newPerson = {name: this.name, id: this.list.length + 1};
this.list.unshift(newPerson);
this.name = "";
}
}
好,需求已经实现完了。不过现在,有一个非常严重的问题出现了。什么问题呢?我们来看一下
首先,因为我们使用的是多选框,是可以有选中状态的,所以我们在添加新书之前,先选中诛仙
,
然后再添加新书
这个时候我们发现,诛仙的状态状态被改变了,变成了未选中,诡秘之主
从未选中变成了选中,这是为什么呢?
原因
vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。
vue为了提高效率,在更新已渲染过的元素列表时,会采用“就地复用”策略。
比如一下这个情况:
我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:
即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?
所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
所以一句话,key的作用主要是为了高效的更新虚拟DOM。
修改HTML中的代码如下,在被v-for循环的标签中添加:key="item.id"
【注意】key一定要是唯一的。
<ul>
<li v-for="(item, i) in list" :key="item.id">
<input type="checkbox"> {{item.name}}
</li>
</ul>
再次尝试选中诛仙
,再添加新书,效果如下:
2、案例:Tab切换
css样式
* {
margin: 0;
padding: 0;
}
ul,
li {
list-style: none;
}
.tab {
width: 800px;
border: 1px solid #000;
}
.tab ul {
display: flex;
}
.tab li {
width: 200px;
height: 50px;
background: #f00;
border: 1px solid #000;
line-height: 50px;
text-align: center;
}
.tab .tabcont div {
width: 100%;
border: 1px solid #00f;
}
.tab .tabcont div img{
width: 100%;
vertical-align: top;
}
.tab .active {
background-color: yellow;
}
<div id="app">
<div class="tab">
<ul>
<li v-for="(item,index) of list" :class="isActive(index)" @click="toggle(index)">{{item.title}}</li>
</ul>
<div class="tabcont">
<div v-for="(item,index) of list" v-show="isShow(index)">
<img :src="item.path" alt="">
</div>
</div>
</div>
</div>
const vm = new Vue({
el: '#app',
data: {
list: [{
id: 1,
title: '武则天',
path: "img/0.jpg",
},
{
id: 2,
title: '李白',
path: "img/1.jpg",
},
{
id: 3,
title: '伽罗',
path: "img/2.jpg",
},
{
id: 4,
title: '大乔',
path: "img/3.jpg",
}
],
cur: 0
},
methods: {
isActive(index) {
return index == this.cur ? 'active' : ''
},
isShow(index) {
return index == this.cur ? true : false
},
toggle(index) {
this.cur = index;
}
}
});
3、案例: TodoList
3.1 线上案例演示
http://www.todolist.cn/
3.2 案例需求分析
-
用户输入待办事项,回车后添加进”正在进行“,并清空文本框
-
在”正在进行"列表项单击,添加进“已经完成”列表
-
在”已经完成"列表项单击,添加进“正在进行”列表
-
在相应列表项中单击“删除”,删除该项目
3.3代码
<div id="app">
<!-- 输入框 -->
<h1>ToDoList <input type="text" v-model="thing" @keyup.enter="addNew"></h1>
<!-- 待办列表 -->
<h2>正在完成 ---{{pending.length}}</h2>
<ul>
<li v-for="(item,index) in pending">
<button @click="addResolve(index)">添加到已完成</button>
<span>{{item}}</span>
<button @click="delPending(index)">删除</button>
</li>
</ul>
<!-- 已完成列表 -->
<h2>已经完成---{{resolve.length}}</h2>
<ul>
<li v-for="(item,index) in resolve">
<button @click="addPending(index)">添加到未完成</button>
<span>{{item}}</span>
<button @click="delResolve(index)">删除</button>
</li>
</ul>
</div>
const vm = new Vue({
el: '#app', //挂载点
data: {
thing: '',
pending: [],
resolve: []
},
methods: {
// 添加待办事项
addNew() {
this.pending.push(this.thing);
this.thing = ''
},
// 单击正在完成项目,切换到已经完成
addResolve(index) {
this.resolve.push(this.pending[index]);
this.pending.splice(index, 1);
},
// 单击已经完成项目,切换到正在完成
addPending(index) {
this.pending.push(this.resolve[index]);
this.resolve.splice(index, 1);
},
//删除正在完成项目
delPending(index) {
this.pending.splice(index, 1);
},
// 删除已经完成项目
delResolve(index) {
this.resolve.splice(index, 1);
}
}
});