vue使用中的注意事项(一)


在vue的开发过程中,有不少需要注意的问题。今天就来说一下在开发中需要注意的一些问题。

v-if和v-for在一起使用的问题

如下所示:

1
2
3
<ul>
<li v-for="page in articles" v-if="page.isActive" :key="page.id">{{ page.title }}</li>
</ul>

这样写是可以正常运行的,看着没什么毛病。但是会有一个问题,假如有1000篇文章,但只需要展示10篇,如上的代码就会遍历整个数组,循环1000次。在同一节点中,v-for的优先级比v-if 更高,这意味着v-if 将分别重复运行于每个v-for循环中。这样造成了性能的浪费。那怎么样避免出现这种问题呢? 我们可以利用计算属性,如下:

1
2
3
4
5
6
7
computed:{
activeArticles: function (){
this.articles.filter(item=>{
return item.isActive
})
}
}
1
2
3
<ul>
<li v-for="page in activeArticles" :key="page.id">{{ page.title }}</li>
</ul>

watch使用时的注意事项

watch可以用来监听基本类型的属性和引用类型的属性。但这两个会有不同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var vm = new Vue({
el: '#blogs',
data: {
author: 'amos',
level: 'gold',
authorMessage: 'amos, gold',
age: 30,
articles: []
},
watch: {
author: function (val) {
this.authorMessage = val + ', ' + this.level
},
level: function (val) {
this.authorMessage = this.author + ', ' + val
},
articles: function (val){
...
}
}
})

以上的写法,对于articles的监听其实是一种浅监听。因为articles所存储的只是一个指向数组的指针。假如对这个数组进行一些简单的修改时,比如修改某一个元素里的某个属性的值,这时articles所存储指针地址并没有改变。所以并不会触发监听函数的运行。数组中filter()、concat() 和 slice()方法,会产生一个新的数组来替换原来的数组。新生成的数组的指针地址是不一样的,所以这些元素方法会触发监听函数。但是push、pop、shift、unshift、splice、sort、reverse等原生方法并没有新生成一个数组所以不会触发,但是vue对这些变更方法进行了包裹,所以也会触发监听函数。引用类型数据监听可以通过设置深度监听来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
watch: {
author: function (val) {
this.authorMessage = val + ', ' + this.level
},
level: function (val) {
this.authorMessage = this.author + ', ' + val
},
articles: {
handler (val){
console.log('changed',val)
},
deep: true,
immediate: true //如果还需要数据立即进行监听,则需要在加上 immediate: true
}
}

v-for的key绑定不建议用index

在v-for循环中绑定key属性的作用是在数据有更新时,可以重用没有变化的DOM节点,不必销毁再重新建,这样可以最小化的对DOM进行修改。但在实际开发中,并不建议直接将key绑定为元素的索引index。为什么呢?

1
2
3
<ul>
<li v-for="(page,index) in articles" :key="index">{{ page.title }}</li>
</ul>

假如第二条数据被删除了。那原来的第三条中key将变成1,之后的元素的key都一样会减1。那第三条及其之后的元素都会被销毁并在js中重新生成并渲染。

如果是换成id呢?

1
2
3
<ul>
<li v-for="(page,index) in articles" :key="page.id">{{ page.title }}</li>
</ul>

由于每个page的id是唯一,所以即使删除了第二个元素,但其他剩余的元素的key并没有变化。所以只需要删除第二条数据就行。相比之前的开销要减少很多。

$refs中ref重复的问题

当多个元素的ref属性相同时,这时this.$refs访问时将不是指向某个具体的元素,而是一个包含多个元素的数组。这里要注意,有时并不是因为正常的需要,而是页面元素多了后,人为造成的重复。

1
2
3
4
5
6
<div ref="page"></div>
<!-- this.$refs['page'] -->

<div ref="page"></div>
<div ref="page"></div>
<!-- 此时this.$refs['page'] // Array-->

在官方文档里,特别提出了关于ref注册时间的重要说明,这里再重复一下。在开发中也需要注意一下。

因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。