Vue中this.$set與this.$nextTick()的使用

  • 最近寫代碼碰到了數(shù)據(jù)響應(yīng)式丟失的問題愧旦,剛開始還以為是值綁定錯(cuò)了/代碼邏輯寫錯(cuò)了世剖,結(jié)果是由于數(shù)據(jù)是額外添加導(dǎo)致的,這次就記錄下錯(cuò)誤出現(xiàn)原因笤虫,加深下印象旁瘫。

1. this.$set

1.1 Vue響應(yīng)式的局限性
  • 對(duì)于對(duì)象:Vue 無法檢測(cè)對(duì)象元素的添加或移除。由于 Vue 會(huì)在初始化實(shí)例時(shí)對(duì)對(duì)象元素執(zhí)行 getter/setter 轉(zhuǎn)化琼蚯,所以對(duì)象元素必須在 data 對(duì)象上存在才能讓 Vue 將它轉(zhuǎn)換為響應(yīng)式的

  • 對(duì)于數(shù)組:當(dāng)你利用索引直接設(shè)置一個(gè)數(shù)組值時(shí)this.items[indexOfItem] = newValue酬凳,當(dāng)你修改數(shù)組的長(zhǎng)度時(shí)this.items.length = newLength

  • 注:this.$set()Vue.set()別名

1.2 對(duì)象形式的實(shí)際例子演示
  data() {
    return {
        obj:{name:'zs'}
    }
  }
  // 錯(cuò)誤演示
  methods: {
   drag(){
    this.obj.age = 18
  }
}
// 正確演示
// this.$set(要添加數(shù)據(jù)的對(duì)象, key值, 數(shù)據(jù))
  methods: {
   drag(){
    this.$set(this.obj, 'b', 18)
    // 或者這樣
    this.obj= Object.assign({}, this.obj, {  b: 18 })
  }
}

Vue 無法檢測(cè)對(duì)象元素的添加或移除,所以這樣也會(huì)丟失響應(yīng)式

  data() {
    return {
        this.stockList:[{name:'zs' ,id:'1'},{{name:'ls' ,id:'2'}],
        this.stockArray:[{name:'zs' ,id:'1',maxLimit:'新字段'},{{name:'ls' ,id:'2',maxLimit:'新字段'}]
    }
  }
  // 錯(cuò)誤演示
  methods: {
   drag(){
     this.stockList.map((item) => {
     const newData = this.stockArray.find(x=>x.id===item.id)
      if (newData) {
       item.maxLimit = newData.maxLimit
      }
    })
  }
}

  // 正確演示
  methods: {
   drag(){
     this.stockList.map((item) => {
     const newData = this.stockArray.find(x=>x.id===item.id)
      if (newData) {
       this.$set(item,"maxLimit", newData.maxLimit)
      }
    })
  }
}

以上可以看到遭庶,首先數(shù)組this.stockList與數(shù)組this.stockArray進(jìn)行了遍歷宁仔,如果符合條件,數(shù)組this.stockArray就會(huì)把maxLimit字段傳遞給數(shù)組this.stockList,看起來是不是很正常峦睡,但this.stockList里面是沒有這個(gè)maxLimit的台诗,這條數(shù)據(jù)屬于額外新增字段,Vue并不會(huì)對(duì)其進(jìn)行響應(yīng)式變化赐俗。

1.3 數(shù)組形式的實(shí)際例子演示
  data() {
    return {
        itemList: ['a', 'b', 'c']
    }
  }

// 錯(cuò)誤示范
this.itemList[3] = 'd' // 不是響應(yīng)性的
this.itemList.length = 2 // 不是響應(yīng)性的

//正確示范
this.$set(this.itemList, 3, 'd' )
this.itemList.splice(刪除位置, 刪除幾個(gè),要添加的元素)) // 如果只傳索引則從索引位置后刪除之后的元素
  • 當(dāng)然拉队,可能有時(shí)候往 數(shù)組對(duì)象 里動(dòng)態(tài)添加子數(shù)組,此時(shí)需要面對(duì)的不單單是添加數(shù)據(jù)的問題阻逮,還要指定key值粱快,此時(shí)演示另一個(gè)辦法,不指定位置叔扼,但指定key值事哭。
demo() {
      // 演示數(shù)據(jù)
      const children = [{ name: "子級(jí)" }, { name: "子級(jí)" }, { name: "子級(jí)" }];
      const list = [{ name: "演示" }, { name: "演示" }, { name: "演示" }];
      // 循環(huán)添加  // 可根據(jù)條件判斷是否添加
      list.forEach((x) => {
        this.$set(x, "children", children);
      });
      console.log(list);
    },
  • 如果不使用$set()則子級(jí)屬于動(dòng)態(tài)添加的,不會(huì)觸發(fā)界面的渲染瓜富。
    效果圖

2 . this.$nextTick()

  • Vue 在更新 DOM 時(shí)是異步執(zhí)行的鳍咱。只要偵聽到數(shù)據(jù)變化,Vue 將開啟一個(gè)隊(duì)列与柑,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)變更谤辜。如果同一個(gè) watcher 被多次觸發(fā),只會(huì)被推入到隊(duì)列中一次价捧。為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM再更新數(shù)據(jù)丑念,那么就建議使用this.$nextTick()
2.1 數(shù)據(jù)演示
  • 以下為模擬代碼
<template>
  <div class="">
    <div>{{value}}</div>
    <button @click='btn'>點(diǎn)擊</button>
  </div>
</template>

<script>
export default {

  data () {
   return {
     value:'原始數(shù)據(jù)',
   }
  },
 
  methods: {
    btn(){
      this.value='我更新了?'
      console.log(this.$refs.val.innerText);
      this.$nextTick(()=>{
      this.value='我更新了'
      console.log(this.$refs.val.innerText);
      })
    }
  },
}
</script> 

以上可以看到,當(dāng)點(diǎn)擊后直接進(jìn)行賦值操縱结蟋,由于Dom還沒進(jìn)行更新脯倚,所以打印出的還是原始數(shù)據(jù),當(dāng)把賦值放在this.$nextTick()里就不一樣了嵌屎,這樣回調(diào)函數(shù)將在 DOM 更新完成后被調(diào)用推正。

2.2 官方詳細(xì)說明傳送門 -- 深入響應(yīng)式原理 — Vue.js -- 個(gè)人比較推薦直接看官方文檔恍涂。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市植榕,隨后出現(xiàn)的幾起案子乳丰,更是在濱河造成了極大的恐慌,老刑警劉巖内贮,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異哄陶,居然都是意外死亡答姥,警方通過查閱死者的電腦和手機(jī)沉噩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來竞端,“玉大人,你說我怎么就攤上這事庙睡∈赂唬” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵乘陪,是天一觀的道長(zhǎng)统台。 經(jīng)常有香客問我,道長(zhǎng)啡邑,這世上最難降的妖魔是什么贱勃? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮谤逼,結(jié)果婚禮上贵扰,老公的妹妹穿的比我還像新娘。我一直安慰自己流部,他們只是感情好戚绕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著枝冀,像睡著了一般舞丛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上果漾,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天瓷马,我揣著相機(jī)與錄音,去河邊找鬼跨晴。 笑死欧聘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的端盆。 我是一名探鬼主播怀骤,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼费封,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了蒋伦?” 一聲冷哼從身側(cè)響起弓摘,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎痕届,沒想到半個(gè)月后韧献,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡研叫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年锤窑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嚷炉。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡渊啰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出申屹,到底是詐尸還是另有隱情绘证,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布哗讥,位于F島的核電站嚷那,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏杆煞。R本人自食惡果不足惜车酣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望索绪。 院中可真熱鬧湖员,春花似錦、人聲如沸瑞驱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽唤反。三九已至凳寺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間彤侍,已是汗流浹背肠缨。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盏阶,地道東北人晒奕。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親脑慧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子魄眉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容