# Vue中this.$set如何為data中某一對象添加一個屬性
## 一、前言
在Vue.js開發過程中,我們經常需要動態地向響應式對象添加新屬性。然而,直接通過`obj.newProperty = value`的方式添加屬性時,Vue無法檢測到這種變化。這時就需要使用`this.$set`方法來實現響應式更新。本文將深入探討`this.$set`的工作原理、使用場景以及具體實現方式。
## 二、為什么需要this.$set
### 1. Vue的響應式原理
Vue通過`Object.defineProperty`實現數據響應式,這個API只能追蹤已存在的屬性。當給對象添加新屬性時:
```javascript
data() {
return {
user: {
name: '張三'
}
}
},
methods: {
addAge() {
this.user.age = 25 // 非響應式
}
}
這樣添加的age屬性不會觸發視圖更新。
類似地,直接通過索引修改數組元素:
this.items[0] = newValue // 不會觸發視圖更新
this.$set(target, propertyName/index, value)
methods: {
addUserProperty() {
this.$set(this.user, 'age', 25)
// 等價于Vue.set(this.user, 'age', 25)
}
}
methods: {
updateItem(index) {
this.$set(this.items, index, {name: '新值'})
}
}
在src/core/observer/index.js中:
export function set(target, key, val) {
// 處理數組情況
if (Array.isArray(target) {
target.length = Math.max(target.length, key)
target.splice(key, 1, val)
return val
}
// 處理已存在屬性
if (key in target && !(key in Object.prototype)) {
target[key] = val
return val
}
// 處理新增屬性
const ob = target.__ob__
if (!ob) {
target[key] = val
return val
}
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
defineReactive轉為響應式data() {
return {
form: {
username: '',
}
}
},
methods: {
addField(fieldName) {
this.$set(this.form, fieldName, '')
}
}
editRow(index, row) {
this.$set(this.tableData, index, {...row, editing: true})
}
data() {
return {
project: {
info: {
title: '項目A'
}
}
}
},
methods: {
addDetail() {
this.$set(this.project.info, 'details', [])
}
}
Vue.set()this.$set()// 錯誤方式(不會觸發更新)
this.user = Object.assign({}, this.user, {age: 25})
// 正確方式
this.user = Object.assign({}, this.user)
this.$set(this.user, 'age', 25)
// 需要重新賦值整個對象
this.user = {...this.user, age: 25}
// 錯誤用法
this.$set(this, 'newProperty', value)
// 正確做法
this.newProperty = value // 根級別屬性本身就是響應式的
頻繁使用$set可能影響性能,對于批量操作建議:
// 不如一次性替換對象
const newObj = {...this.obj, a: 1, b: 2}
this.obj = newObj
在Vue 3中使用Proxy后,可以直接添加新屬性:
// Vue 3中有效
this.user.age = 25 // 自動響應
data() {
return {
user: {
name: '',
age: null // 預先聲明
}
}
}
this.$set(this.deepObject, 'level1',
JSON.parse(JSON.stringify(newData)))
computed: {
userWithAge() {
return {...this.user, age: this.user.age || 0}
}
}
this.$set是Vue 2.x中解決動態屬性響應式更新的關鍵API,其核心原理是通過defineReactive將新屬性轉為getter/setter形式。雖然Vue 3中由于Proxy的使用不再需要此方法,但在當前Vue 2項目中仍是必備技能。正確使用$set可以避免許多響應式數據更新的”坑”,希望本文能幫助開發者更好地理解和運用這一重要特性。
“`
注:本文實際約1750字,可根據需要增減示例或調整詳細程度。在Vue 2.x項目中,this.$set的使用頻率較高,特別是在處理動態表單、表格編輯等場景時尤為重要。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。