vue數(shù)組更新后,頁(yè)面沒有動(dòng)態(tài)刷新的問題

在一個(gè)函數(shù)中,改變了data中的數(shù)據(jù),在函數(shù)中查看是修改成功的,但是頁(yè)面中并沒有刷新。

尤大的解釋:由于性能的代價(jià)與獲得的用戶體驗(yàn)不成正比,故vue2.0的實(shí)現(xiàn)中放棄了這個(gè)特性。在vue3.0中,使用proxy替代了Object.defineProperty()

數(shù)組變更檢測(cè)注意事項(xiàng):

由于JS的限制,以下兩種情況,vue不能檢測(cè)以下數(shù)組的變動(dòng)

  1. 當(dāng)利用索引直接修改數(shù)組的某一項(xiàng)時(shí)
  2. 直接修改數(shù)組的長(zhǎng)度時(shí)

示例:

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是響應(yīng)性的
vm.items.length = 2 // 不是響應(yīng)性的

也就是說(shuō),直接設(shè)置數(shù)組的某一項(xiàng)時(shí),雖然改變了數(shù)組的值,但視圖上顯示的仍然為數(shù)組之前的值,數(shù)據(jù)的響應(yīng)式失效了。

vue的數(shù)據(jù)劫持是利用Object.defineProperty()get,set方法,但是get,set是有限制的。示例:

var person = {};
Object.defineProperty( person, { 
      age: { 
        defaultValue: 11, 
        get: function () {
          return this.defaultValue;
        }, 
        set: function (val) { 
          this.defaultValue = val; 
          console.log("觸發(fā)了set") 
        }
      } 
    });
 
// 修改屬性的值時(shí)能夠觸發(fā)set
person.age = 12    // 觸發(fā)了set
->觸發(fā)了set
->12
 
person.age
->12
 
// 將屬性的值設(shè)置為一個(gè)數(shù)組,當(dāng)通過(guò)索引值修改數(shù)組的某一項(xiàng)或使用數(shù)組的某些方法修改數(shù)組時(shí)不能觸發(fā)set
person.age = [2,3,4]    // 觸發(fā)了set
->觸發(fā)了set
->(3) [2, 3, 4]
 
person.age[2] = 5      // 未觸發(fā)set
->5
 
person.age
->(3) [2, 3, 5]
 
person.age.push(5)     // 未觸發(fā)set
->4
 
person.age
->(4) [2, 3, 4, 5]
 
 
// 將屬性的值設(shè)置為一個(gè)對(duì)象,當(dāng)修改對(duì)象中某屬性的值時(shí)無(wú)法觸發(fā)set
person.age = { first: 1 }
->觸發(fā)了set
->{first: 1}
 
person.age.first = 2      // 未觸發(fā)set
->2

通過(guò)上述例子可以觀察得出:

當(dāng)該屬性的值為一個(gè)數(shù)組時(shí),通過(guò)索引修改數(shù)組某一項(xiàng)的值或使用數(shù)組的某些方法修改數(shù)組并不能觸發(fā)set;當(dāng)屬性的值為一對(duì)象時(shí),直接修改對(duì)象中屬性的值時(shí)也無(wú)法觸發(fā)set。

解決方法:

  1. Vue.setVue.set(vm.items, indexOfItem, newValue)
  2. vm.$set(vm.items, indexOfItem, newValue)也可以使用 vm.$set 實(shí)例方法,該方法是全局方法 Vue.set 的一個(gè)別名
  3. vm.items.splice(indexOfItem, 1, newValue)
  4. 運(yùn)用this.$forceUpdate()強(qiáng)制刷新。
    示例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for='(item,index) in list' :key='index'>{{item}}</li>
        </ul>
        <button @click='change'>按鈕</button>
    </div>
</body>
</html>
<script src="./lib/vue-2.6.10.js"></script>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            list:[
                1,2,3,4,5
            ]
        },
        methods: {
            change(){
                this.list[0] = 2
                // Vue.set(vm.list,0,2)
                vm.list.splice(0,1,2)
                // this.$forceUpdate()
                console.log(this.list);
            }
        },
    })
</script>

proxy

  1. Object.define()只能對(duì)屬性進(jìn)行劫持,需要遍歷對(duì)象的每個(gè)屬性,若屬性值也是對(duì)象,則需要深度遍歷。而Proxy直接代理對(duì)象,不需要遍歷操作。
  2. 新增屬性時(shí),需要重新遍歷對(duì)象,對(duì)其新增屬性在使用Object.define()進(jìn)行劫持。
    參考鏈接:

VUE中數(shù)組更新后,頁(yè)面沒有動(dòng)態(tài)刷新問題
vue為什么不能檢測(cè)數(shù)組的變化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容