在真实开发中,我们往往会从服务器拿到一组数据,并且需要对其进行渲染
可以通过html标签内添加v-for 属性(Vue里面叫指令),实现html标签的循环控制
v-for类似于JavaScript的for循环,可以用于遍历一组数据;
数组用法
1、数组基本用法
通过
<template>
<div>
<div>健康食物有:</div>
<div v-for="item in food">{{item}}</div>
</div>
</template>
<script>
export default {
data(){
return {
food:[
"青菜",
"牛奶",
"鸡蛋",
"豆制品"
]
}
}
};
</script>
<style>
</style>
数组写成这样也可以,调用的时候就要调用{{item.name}}
items: [
{ name:20},
{ name:23 },
{ name:18 }
]
2、数组带下标index的用法
注意:( )内第一个一定是数组元素,第二个一定是下标号,不管是什么名字
<template>
<div>
<div>健康食物有:</div>
<div v-for="(item,index) in food">{{index+1}}.{{item}}</div>
</div>
</template>
<script>
export default {
data(){
return {
food:[
"青菜",
"牛奶",
"鸡蛋",
"豆制品"
]
}
}
};
</script>
<style>
</style>
对象用法
1、对象value值的用法
<template>
<div>
<div>健康食物有:</div>
<div v-for="item in food">{{item}}</div>
</div>
</template>
<script>
export default {
data(){
return {
food:{
a:"青菜",
b:"牛奶",
c:"鸡蛋",
d:"豆制品"
}
}
}
};
</script>
<style>
</style>
2、对象key值和value值
注意:第一个一定是值,第二个一定是键
<template>
<div>
<div>健康食物有:</div>
<div v-for="(value,key) in food">{{key}} {{value}}</div>
</div>
</template>
<script>
export default {
data(){
return {
food:{
a:"青菜",
b:"牛奶",
c:"鸡蛋",
d:"豆制品"
}
}
}
};
</script>
<style>
</style>
3、对象key、value、下标
注意:第一个一定是值,第二个一定是键,第三个一定是下标
<template>
<div>
<div>健康食物有:</div>
<div v-for="(value,key,index) in food">{{index}} {{key}} {{value}}</div>
</div>
</template>
<script>
export default {
data(){
return {
food:{
a:"青菜",
b:"牛奶",
c:"鸡蛋",
d:"豆制品"
}
}
}
};
</script>
<style>
</style>
数值用法
第一个参数是数值,第二个参数是下标
<ul>
<li v-for="(num, index) in 10">{{num}}-{{index}}</li>
</ul>
=======================
template元素
类似于v-if,你可以使用 template 元素来循环渲染一段包含多个元素的内容:
我们使用template来对多个元素进行包裹,而不是使用div来完成,重复的div无用且消耗性能;
<template id="my-app">
<ul>
<template v-for="(value, key) in info">
<li>{{key}}</li>
<li>{{value}}</li>
<li class="divider">我是分隔符</li>
</template>
</ul>
</template>
数组排序
伪排序
<template>
<div>
<div>伪排序:</div>
<div v-for="(value,index) in arrSort" >{{index}}.{{value}}</div>
</div>
</template>
<script>
export default {
data(){
return {
food:[
3,
54,
78,
11,
22,
33,
13,
11,
23,
22,
54,
59,
]
}
},
computed:{
arrSort(){
return this.food.sort();
}
},
};
</script>
<style>
</style>
真排序
<template>
<div>
<div>伪排序:</div>
<div v-for="(value,index) in arrSort" >{{index}}.{{value}}</div>
</div>
</template>
<script>
export default {
data(){
return {
food:[
3,
54,
78,
11,
22,
33,
13,
11,
23,
22,
54,
59,
]
}
},
computed:{
arrSort(){
return this.food.sort((a,b)=>{return a-b});
}
},
};
</script>
<style>
</style>
=======================
key标识
给 v-for 循环增加一个key,这个key可以更好地提高组件复用的效率,提高页面视图的更新效率。
这个是怎么实现的呢?
1、数组更新检测
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图页面响应式更新。
包括数组的这些方法:
push( )
pop( )
shift( )
unshift( )
splice( )
sort( )
reverse( )
上面的方法会直接修改原来的数组,
但是某些方法不会替换原来的数组,而是会生成新的数组,比如 filter()、
concat() 和 slice()。
这些方式都可以触发页面响应式更新。
注意!通过下标索引修改,不是响应式,无法触发页面更新。
2、VNode
VNode的全称是Virtual Node,也就是虚拟节点;
事实上,无论是组件还是元素,它们最终在Vue中表示出来的都是一个个VNode(如下图); 这样可以更好地适配任何的环境,比如浏览器访问,就通过对应的算法转换为浏览器DOM,小程序就通过对应的转为小程序的DOM显示。 如果我们不只是一个简单的div,而是有一大堆的元素,那么它们应该会形成一个VNode虚拟节点组成的树形结构,这个就是虚拟DOM 也就是N * VNode = VDOM,和真实的DOM一样,也是一些节点Node组成的。 但虚拟DOM转换成真实的DOM,不一定是一 一对应的,通过一定的算法来实现转换。 后续响应式改变,就要通过一些算法来实现。 我们可以确定的是,这次更新对于ul和button是不需要进行更新,需
要更新的是我们li的列表:
那么Vue中对于列表的更新究竟是如何操作的呢? Vue3 源码事实上会对于有key和没有key会调用两个不同的方法;
(2)从0开始for循环,一个一个比较,节点不管是否一样,都更新 (3)最后对比新旧VNode的长度,新的多了就增加节点,新的少了就删除旧的节点 我们会发现上面的diff算法效率并不高: (2)是从尾部开始进行遍历、比较 (3)如果旧节点遍历完毕,但是依然有新的节点,那么就新增节点 (4)是如果新的节点遍历完毕,但是依然有旧的节点,那么就移除旧节点 (5)最特色的情况,中间还有很多未知的或者乱序的节点,通过使用key建立索引图,最大限度使用旧节点 所以我们可以发现,Vue在进行diff算法的时候,会尽量利用我们的key来进行优化操作: 通过节点的type和节点的key,来判断是不是同一节点。 比较两个节点并且操作的一个方法 diff是different的意思,意思是处理两个不同节点树的方法,就是叫diff算法
VNode的本质是一个JavaScript的对象,Vue是通过把 标签里面的这些HTML元素,转换为JS对象,如下图:
然后一次性转换成真实的DOM,再触发页面更新。
3、虚拟DOM
首次转换,一般都是生成好虚拟DOM再转换,否则一个一个转会严重影响DOM性能,每增加一个节点,浏览器都会重新渲染一遍,因此只要一次性更新就好。4、插入F的案例
这个案例,是通过 v-for 根据提供的数组生成列表,然后通过点击按钮触发事件,事件直接通过Vue包装的数组方法插入一个数组元素,让页面响应式实时更新。
1、在Vue中,对于相同父元素的子元素节点并不会重新渲染整个列
表;
2、因为对于列表中 a、b、c、d它们都是没有变化的;
3、在操作真实DOM的时候,我们只需要在中间插入一个f的li即可;5、Vue3 更新操作
1、有key,那么就使用 patchKeyedChildren方法;
2、没有key,那么久使用 patchUnkeyedChildren方法;没有key的过程
(1)获取旧VNode、新VNode长度,对比哪个小
1、c和d来说它们事实上并不需要有任何的改动;
2、但是因为我们的c被f所使用了,所有后续所有的内容都要一次进行改动,并且最后进行新增有key的过程
(1)通过while循环对VNode进行遍历,节点相同就继续,节点不同就通过 break 跳出while循环。
a和b是一致的会继续进行比较;
c和f因为key不一致,所以就会break跳出循环;
1、在没有key的时候我们的效率是非常低效的;
2、在进行插入或者重置顺序的时候,保持相同的key可以让diff算法更加的高效;怎么比较两个节点?
patch是什么?
diff算法?
1、有key,那么就使用 patchKeyedChildren方法;
2、没有key,那么久使用 patchUnkeyedChildren方法;<template>
<div>
<div>健康食物有:</div>
<div v-for="(value,key,index) in food" v-bind:key="index">{{index}} {{key}} {{value}}</div>
</div>
</template>
<script>
export default {
data(){
return {
food:{
c:"青菜",
b:"牛奶",
d:"鸡蛋",
a:"豆制品"
}
}
}
};
</script>
<style>
</style>