vue 數(shù)組中嵌套的對(duì)象添加新屬性--頁(yè)面更新

我們知道vue屬于MVVM框架,數(shù)據(jù)操作視圖。對(duì)data對(duì)象中的數(shù)據(jù)進(jìn)行監(jiān)聽(tīng),當(dāng)偵測(cè)到數(shù)據(jù)改變時(shí)相應(yīng)數(shù)據(jù)所影響的頁(yè)面也會(huì)觸發(fā)更新。所以我們所需要的這些響應(yīng)式數(shù)據(jù),受到j(luò)avascript的限制,vue不能檢測(cè)到對(duì)象屬性的添加或刪除,因?yàn)閂ue利用的是Object的defineProperty()方法,在初始化實(shí)列時(shí)將屬性轉(zhuǎn)為getter/setter,所以屬性必須在data對(duì)象上才能讓vue轉(zhuǎn)換它。
當(dāng)然這只是一般的屬性,以一般字符串,數(shù)字,布爾值這樣的基本數(shù)據(jù)類型作為屬性值的響應(yīng),當(dāng)然我們有時(shí)候的訴求的初始化屬性的屬性值不只有這樣的基本數(shù)據(jù)變量,我們還會(huì)用到數(shù)組,對(duì)象這樣的引用數(shù)據(jù)變量。引用數(shù)據(jù)變量就是對(duì)地址的引用,只是對(duì)象的指針發(fā)生變化,并沒(méi)有重新生成一個(gè)對(duì)象,此處省略過(guò)多其他介紹,應(yīng)該這些都比較懂。。。

vue在這種情況下給我們提供了$set這種響應(yīng)式方法去操作頁(yè)面更新。其實(shí)這只是set簡(jiǎn)單的對(duì)象不是嵌套很深的那種,那如果是那樣嵌套比較深的那種我們?cè)撛鯓尤プ瞿兀空f(shuō)多了不如來(lái)個(gè)業(yè)務(wù)情景然后擼幾行代碼看一下:

這樣的一個(gè)場(chǎng)景我們從后臺(tái)請(qǐng)求下一個(gè)list相當(dāng)于渲染成一個(gè)Table,我們需要賦予每行都有自己獨(dú)立的編輯功能和顯示功能。類似于這樣的效果:


每行都有單獨(dú)的編輯功能

當(dāng)然實(shí)現(xiàn)效果多種多樣,但我們就當(dāng)后臺(tái)給我們的list數(shù)據(jù)是:

   [
        {
          name: '第1行',
          textShow: true,
          text: ''
        },
         {
          name: '第2行',
          textShow: true,
          text: ''
        },
         {
          name: '第3行',
          textShow: true,
          text: ''
        },
         {
          name: '第4行',
          textShow: true,
          text: ''
       

我們的頁(yè)面為這樣

<template>
  <div>
    <ul v-if="list">
      <li v-for="(item, index) in list" :key="index">
        <span>{{item.name}}</span>
        <span ref="text" v-show="item.textShow">
          {{item.txt}}
        </span>
        <input type="text" v-model="item.txt" v-show="!item.textShow">
        <button @click="edit(item)" v-show="item.showEditBtn">編輯</button>
        <button @click="confirm(item)" v-show="!item.showEditBtn">確定</button>
      </li>
    </ul>
  </div>
</template>

當(dāng)然看上面的數(shù)據(jù)機(jī)構(gòu)我們可以看出其實(shí)顯示隱藏編輯和確定的數(shù)據(jù)參數(shù)并沒(méi)有給咱們,其實(shí)就是我們需要在數(shù)組中對(duì)象增加一個(gè)新屬性“showEditBtn”去判定:那有時(shí)候我們可能會(huì)這樣寫:

mounted () {
    this.arr.forEach(item => {
      item.showEditBtn = true
    })
  },

當(dāng)我們看頁(yè)面效果居然無(wú)動(dòng)于衷,


只顯示確定,應(yīng)該顯示編輯呀!

哈哈!看到上面這種效果,我們應(yīng)該明白了,showEditBtn屬性并不是初始化在data對(duì)象里面的,雖然arr屬于data對(duì)象,但你應(yīng)該再好好想想js不能監(jiān)測(cè)但對(duì)象的變化,當(dāng)然這時(shí)候我們可以考慮如何去偵測(cè),必須讓對(duì)象變化。
此時(shí)我們可以這樣改寫

 mounted () {
    this.arr.forEach(item => {
      this.$set(item, 'showEditBtn', true)
    })
  },
這個(gè)姿勢(shì)可以呀

這樣他就可以偵測(cè)到你對(duì)象中的屬性的變化,當(dāng)然這是一種比較官方的姿勢(shì)也是一種比較推薦的姿勢(shì)。
我們考慮一下,對(duì)象沒(méi)有變化我們沒(méi)有更新頁(yè)面,單純的等號(hào)賦值只是引用地址的變化,本身不等于數(shù)組的變化,那我們讓他的數(shù)組真正變化(重新創(chuàng)建不就可以了),我們利用Object. assign()去進(jìn)行淺拷貝對(duì)象。

mounted () {
    this.arr.forEach(item => {
      item.showEditBtn = true;
    })
    this.arr = Object.assign({},this.arr)
  },
這個(gè)姿勢(shì)也可以呀

當(dāng)然這種方式我們可以現(xiàn)效果,但我們不如用第一種,第一種只是單純?nèi)ジ淖円粋€(gè)數(shù)組中嵌套的對(duì)象的屬性而已,而第二種方法直接淺拷貝的一個(gè)數(shù)組對(duì)象。
當(dāng)然,第二種有沒(méi)有變通之法,當(dāng)然有!我們考慮一下,如果之前的功能只是單純的去渲染一個(gè)list,

arr: [
        {
          name: '第1行'
        },
         {
          name: '第2行'
        },
         {
          name: '第3行'
        },
         {
          name: '第4行'
        }

沒(méi)有編輯功能,編輯功能是后來(lái)加的,并且遇見(jiàn)的后臺(tái)比較懶,它就維持這個(gè)數(shù)據(jù)結(jié)構(gòu)不變,那我們是不是有想法了,這樣就啟迪了第二種方式的變通,
我們不忙著將獲取到的list賦值給arr,我們對(duì)他進(jìn)行改寫:

mounted () {
    list.forEach(item => {
      item.textShow = true;
      item.text = ' ';
      item.showEditBtn = true;
    })
    this.arr = list
  },

// 同時(shí)我們將改寫好的arr放在
 <ul v-if="arr">
 <li v-for="(item, index) in arr" :key="index">

通過(guò)上面的方法我們可以提前預(yù)判我們需要怎樣的數(shù)據(jù)去驅(qū)動(dòng)視圖,然后我們最先將它初始化在data對(duì)象中,這就需要寫代碼錢我們有個(gè)思考全面的過(guò)程。
當(dāng)然如果想第一種設(shè)想我們只是單純的去隱藏編輯和確定功能,我們可不可以將在data里去聲明一個(gè)單純的全局變量,不去嵌在數(shù)組和對(duì)象那種很隱秘的角落,我想正大光明的成為一個(gè)data對(duì)象中單獨(dú)的控制變量currentShow。我們可以分析一下:
因?yàn)樵趯懕闅v列表的時(shí)候我們通過(guò)v-for循環(huán)去寫,所以我們?nèi)绻タ刂葡嗤δ茉氐娘@示隱藏,我們引用全局變量currentShow,當(dāng)我們觸發(fā)某個(gè)行為去改變currentShow的值時(shí),我們會(huì)發(fā)現(xiàn)所有的item都會(huì)相應(yīng)的變化,雖然你操作的是其中一個(gè):


會(huì)是這樣的效果

當(dāng)然我們想想因?yàn)槲覀內(nèi)值腸urrentShow變量是完全變化一致的,我們要想單獨(dú)去操作每行元素,我們?cè)撛鯓尤プ觯科鋵?shí)也很簡(jiǎn)單,我們?cè)偌觽€(gè)判斷,同時(shí)滿足這兩個(gè)結(jié)果才會(huì)觸發(fā)行為,這個(gè)判斷必須是每行獨(dú)一無(wú)二的,哈哈!肯定是index索引了,我們可以再聲明一個(gè)data對(duì)象屬性currentIndex,當(dāng)我們對(duì)每行進(jìn)行操作時(shí),我們將this.currentIndex等于這行的索引,我們?cè)黾拥呐袛嗑涂梢宰兂?/p>

v-show="currentIndex === index && currentShow"

每行變化時(shí)currentIndex都在變化,他只能等于操作行的索引,感覺(jué)有一種借力打力的效果。不過(guò)實(shí)現(xiàn)了


定義變量接力打力

以上雖不是難的東西,但貴在舉一反三,簡(jiǎn)書記之!!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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