记录我的Vue.js从会用到精通之路 8

593 阅读3分钟

列表渲染

v-for可以用来遍历一个元素,然后渲染出一个列表!

1.用v-for遍历一个数组

  • 基本语法:v-for="item in items",其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
  • v-for="(item,index) in items",v-for还支持可选的第二个参数,是遍历出元素对应的索引。

2.用v-for遍历一个对象

  • 基本语法:v-for="value in object",其中object是目标对象,而value则是被迭代出的属性址。
  • v-for="(value,key,index) in object",在遍历对象的情况下,第二个属性是property,第一个属性是object[property],第三个参数是索引,从0开始。
  • 值得一提的是,在遍历对象时,会按照Object.keys()的结果遍历,而不是for..in..,我想这样设计的原因是不会遍历到原型链上的属性吧。

3.维护状态与key值

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。 啥意思?????

www.zhihu.com/question/61…

这篇文章直接讲的明明白白!但是有个问题,我在此时此刻读文档,可以很确定的告诉你,官网上写的是“就地更新”,但是我在查阅的时候,很多资料包括这一篇中,都是“就地复用”,我严重怀疑他俩是一回事,然后改名字了。然后我在写一点自己的想法:

我们在v-if条件渲染中提到过,Vue为了提升性能,会对DOM进行高度的复用。那在v-for进行列表渲染的时候,如果元素的位置的发生了变化,比如第一个和第二个交换了位置,Vue并不会去相应的改变DOM的顺序,而是就地更新,但是在更新中也不会傻傻的把元素全部删除,再重新创建,而是会高度复用,如果不能复用,那只能删了重新来。这也就是为什么,在这篇知乎解答中,第一个input框中的值,没有发生改变。因为input被复用了,而给定属性key,vue会认为即使DOM元素可以复用,但他俩仍然是完全不同的俩玩意儿,就不会复用了。

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/10/28/16e1134c97770960~tplv-t2oaga2asx-image.image

4.数组更新检测

4.1变异方法

我们都知道,Vue使用了双向绑定,也就是vm层数据的变化一定会相应的在v层上得到体现。比如我们去列表渲染一个数组中的元素,当向数组中push一个元素的时候,视图层一定会改变。但是,我们回过头在思考,如果是简简单单的push操作,数组的引用不会改变,那凭什么能被响应呢?

Vue重写了push方法(变异),这些变异的方法会改变原数组

除了push,还有很多变异方法。

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

4.2非变异方法

它们不会改变原数组 而是返回一个新的数组

  • filter()
  • concat()
  • slice() 可以用新数组代替旧数组来达到响应式的目的

4.3注意事项(很可能成为开发的bug)

Vue并不能检测以下数组的变动:

  • 当我们利用索引值设置一个数组项的时候,例如:vm.items[indexOfItem] = newValue
  • 当我们修改数组的长度时,例如:vm.items.length = newLength

第一种情况的解决方法:

//  Vue.set解决
Vue.set(vm.items,indexOfItem,newValue)
vm.$set(vm.items,indexOfItem,newValue) //通过实例方法,该方法是Vue.set的一个别名
//  使用变异的splice方法
vm.items.splice(indexOfItem,1,newValue)

第二种情况的解决方法:

vm.items.splice(newLength)

4.4对象变更检测注册事项

  • Vue不能检测对象属性的添加或删除
// Vue.set解决
Vue.set(object,propertyName,value)
vm.$set(object,propertyName,value) // Vue.set的别名
  • 如果需要为已又对象赋值多个属性,可以使用Object.assign()
vm.userProfile = Object.assign({},vm.userProfile,{
    age: 27,
    favoriteColor: 'Vue'
})

4.5 v-for里使用指范围

<li v-for="n in 10">{{n}}</li>  //  1 2 3 4 5 6 7 8 9 10

4.6 v-for和v-if不要一起使用,因为v-for的优先级更高。