Appearance
Vue 能自动检测数据变化并更新页面——但有些操作它能侦测到,有些不行。这一篇讲清楚规则。
数组的"变更方法"
Vue 特别对待了 JavaScript 中 7 个会修改原数组的方法。只要用它们操作数组,Vue 就能自动更新视图: | 方法 | 做什么 | 示例 | | push() | 末尾添加 | list.push('D') | | pop() | 末尾删除 | list.pop() | | shift() | 开头删除 | list.shift() | | unshift() | 开头添加 | list.unshift('A') | | splice() | 删除/插入/替换 | list.splice(1, 1, 'X') | | sort() | 排序 | list.sort() | | reverse() | 反转 | list.reverse() |
vue
<template>
<ul>
<li v-for="item in list" :key="item">{{ item }}</li>
</ul>
<button @click="addItem">添加 D</button>
</template>
<script>
export default {
data() {
return { list: ['A', 'B', 'C'] }
},
methods: {
addItem() {
this.list.push('D') // ✅ Vue 能侦测到,页面自动更新
}
}
}
</script>
数组的"非变更方法"
有些方法不会修改原数组,而是返回一个新数组: | 方法 | 说明 | | filter() | 过滤 | | concat() | 拼接 | | slice() | 截取 | | map() | 映射 | 这些方法不会触发视图更新,因为原数组没变。解决方法是用新数组替换旧数组:
javascript
// ❌ 这样不会更新视图
this.numbers.filter(n => n > 0)
// ✅ 要整体替换
this.numbers = this.numbers.filter(n => n > 0)
this.numbers = this.numbers.concat([4, 5, 6])
📝 Note:为什么整体替换可以? Vue 的内部机制会优化这个操作——它不会真的销毁重建整个列表,而是尽可能复用已有的 DOM 元素。所以用 filter 整体替换和用 splice 删除,性能差不多。
Vue 2 的限制(已废弃的 Vue.set)
⚠️ Warning:Vue 2 中已废弃,Vue 3 已修复 以下问题只存在于 Vue 2。在 Vue 3 中,这些问题已经被 Proxy 机制解决了,你不需要担心这些限制。 Vue 2 无法侦测到以下两种操作:
javascript
// ❌ Vue 2 无法侦测:直接通过索引设置数组元素
this.items[0] = '新值'
// ❌ Vue 2 无法侦测:直接给对象添加新属性
this.user.age = 18 // 如果 age 不在初始 data 中
Vue 2 需要用 Vue.set() 或 this.$set() 来处理:
javascript
// Vue 2 的解决方案
this.$set(this.items, 0, '新值')
this.$set(this.user, 'age', 18)
但在 Vue 3 中直接用 this.items[0] = '新值' 就行,不需要 $set。
响应式原理(通俗版)
你不需要理解底层实现,但有个概念对以后有帮助:
- Vue 在创建实例时,把你
data里的数据都"劫持"了 - 每次你读写这些数据,Vue 都能感知到
- 数据一变,Vue 就知道"哪些页面元素依赖这个数据",然后自动更新它们 就像一个管家,你只管说"茶杯放桌子上",管家会自动把旧杯子拿走、新杯子放上。你不用管"怎么更新页面",Vue 包了。
新手常见问题
Q:为什么我的列表改动后页面没反应? A:检查你是否做了以下操作:
- 直接改数组索引:
this.list[0] = 'X'(Vue 2 不行,Vue 3 可以) - 用了
filter但没赋值:this.list.filter(...)→ 应该是this.list = this.list.filter(...) - 也别忘了在 JavaScript 里组合式 API 用
ref时需要用.valueQ:对象属性变化能侦测到吗? A:Vue 3 可以,Vue 2 只能在初始data中存在的属性才能被侦测。新增属性在 Vue 2 中需要用$set。 下一步: 💡 Tip:Composition API 写法(Vue 3)
vue
<script setup>
import { ref } from 'vue'
const list = ref(['A', 'B', 'C'])
function addItem() { list.value.push('D') }
</script>
在 Vue 3 的组合式 API 中,数组操作更直观,没有 Vue 2 的那些限制。 详见: