結合實際場景聊聊大部分前端都不會使用的數據結構Map

前言

你們好呀,我是wangly,一名前端菜貓子。
最近項目中不少地方都用到了Map來作數據結構。因此總結一篇文章來複習本身。順便給各位看官總結下這個ES6新的數據結構。它不像Object同樣在開發中大量的被用到。但在某些特定的場景下使用它簡直就是神來一筆。因此今天就給各位嘮嗑下Map了。若是你還不知道Map是什麼,不妨在掘金看其餘的筆者寫的文章。固然,直接看下去也是能夠的。javascript

若是以爲不錯,看完後能夠點個贊哦,支持下筆者哦。前端

什麼是Map

MapES6新增長的數據結構。它屬於鍵控「集團」(keyed collections)的股東之一,它會用戶提供了更增強大的key鍵擴展集。更加自由的容器隱私,如set,get,size一系列的原生api,來方便用戶管理容器。必定狀況下,它們能夠提供至關大的性能優點。vue

什麼時候使用Map代替Object

  • Object的key沒法支持該數據時
  • 須要瞭解對象大小時
  • 不想存在衝突的key值時
  • 自定義key值時

推薦閱讀這篇文章,瞭解一些基本的知識:
前端小智:什麼時候使用 Map 來代替普通的 JS 對象java

一些經常使用的業務場景

都是一些真實的業務場景,很是簡單。若是你的項目中碰到不妨能夠試試這種解決方案。我就以vue做爲演示環境來給各位作Demo詳解啦。其它環境下的朋友借鑑思路哦。如下三個案例均可以用Object實現。只是寫起來會有點異樣性。web

場景一:我的信息表

在一些Admin項目中咱們一般都對我的信息進行展現,好比將以下信息展現到頁面上,你會怎麼作呢?立馬一個糟糕的寫法就出來了。api

<div class="info-item">
 <span>姓名</span>  <span>{{info.name}}</span> </div> <div class="info-item">  <span>年齡</span>  <span>{{info.age}}</span> </div> <div class="info-item">  <span>性別</span>  <span>{{info.sex}}</span> </div> <div class="info-item">  <span>手機號</span>  <span>{{info.phone}}</span> </div> <div class="info-item">  <span>家庭住址</span>  <span>{{info.address}}</span> </div> <div class="info-item">  <span>家庭住址</span>  <span>{{info.duty}}</span> </div>  </div> 複製代碼
mounted() {
 this.info = {  name: 'wangly',  sex: '男',  age: '18',  phone: '13000000000',  address: '中國......',  duty: '總經理'  } } 複製代碼

咱們經過Map來改造,將咱們須要顯示的labelvalue存到咱們的Map後渲染到頁面。雖然在javascript中代碼顯得沉澱。只是作一個演示。具體操做你們能夠一塊兒思考。如何去解決更好一點。這只是個人一些見解。雖然邏輯層代碼多了。可是view視圖卻節省了不少耦合的代碼。以啊就是我對cell的一個簡單理解。你還有更妙的解決方案嗎?數組

<template>
 <div id="app">  <!-- <router-view></router-view> -->  <div class="info-item" v-for="[label, value] in infoMap" :key="value">  <span>{{label}}</span>  <span>{{value}}</span>  </div>  </div> </template> 複製代碼
data: () => ({
 info: {},  infoMap: {} }), mounted () {  this.info = {  name: 'wangly',  sex: '男',  age: '18',  phone: '13000000000',  address: '中國......',  duty: '總經理'  }  const mapKeys = ['姓名', '性別', '年齡', '電話', '家庭地址', '身份']  const result = new Map()  let i = 0  for (const key in this.info) {  result.set(mapKeys[i], this.info[key])  i++  }  this.infoMap = result } 複製代碼

那麼該如何渲染到頁面呢?

map在v-for下也變得很是現實。能夠看下面代碼。一步搞定瀏覽器

<!-- show map  -->
<div class="info-item" v-for="[label, value] in infoMap" :key="value">  <span>{{label}}</span>  <span>{{value}}</span> </div> 複製代碼

嘮嗑

經過map遍歷,在解構出想要的key, value,就能夠將一些完整的鍵對展現內容展現到頁面上了。這是我經常使用的一個地方。固然它使用計算屬性的方式也能夠作到很好的完成。數據結構

場景二:自定義提交表單

不知道你們有沒有碰過前端動態表單。意思是經過組合而成的表單。好比:app

  • A表單字段: ['A', 'B', 'C', D, 'E']
  • B表單字段: ['A', 'C', D, 'E']
  • C表單字段: ['A', 'B', D, 'E', 'F']

根據不一樣形勢下上傳的表單,它不同。若是要渲染到頁面上,容易出現空白列。由於它沒有數據,你不清楚你當前的表單是什麼樣子的。基本場景: 學生,老師,工做人員的疫情調查表,它們是不同的。它們都須要交到某個管理這個事的工做人員手上。那麼這個工做人員查看錶單信息是多元化的。就擁有多個模板。甚至還須要作導出xls文件。因此傳統表單的prop就很難去適應這個多元的東西了。

模板結構

list對象是不同的。這先當與它們傳上來的字段表。咱們須要經過labelvalue渲染到頁面上。

模板一:
模板二:

動態表格

結果一:
結果二:

實現過程

其實核心就是map.set(child.label, child.value),將後臺發下來自定義模板數組,轉換爲Map。這樣,咱們就不要過多的去關注一些模板的字段。能夠專一數據的渲染。

<table class="table" border="1" id="table">
  <tr>
    // 獲取頭部,也就是map的key
    <th v-for="([label], key) in tableMap.length > 0 ? tableMap[0] : []">
      {{label}}
    </th>
  </tr>
  // 渲染map數組
  <tr v-for="(map, index) in tableMap">
    <td v-for="[,value] in map">{{value}}</td>
  </tr>
</table>
複製代碼
createModule () {
 this.tableMap = []  this.tableList.forEach(el => {  const map = new Map()  map.set('時間', el.name)  el.custom.forEach(child => {  // 將label 做爲 key , value做爲值  map.set(child.label, child.value)  })  // map結束  this.tableMap.push(map)  }) } 複製代碼

場景三:避免重複的數據

動態更新最多見的地方就是移動端的下拉加載更多。正常下是不會出錯的。可是有一種極爲特殊的狀況。socket實時推送的累加的內容。咱們都知道socket在發送消息的時候,存在通訊延遲。影響這方面的地方不少。每每沒法保證在socket接收到這個對象添加到DOM時,用戶有沒有手動更新這個消息內容。若是列表中存在。你在socket.onmessage動態添加到列表就會有值衝突的問題。雖然能夠經過filter過濾出去。可是經過mapkey無重複性。能夠很好的完成這個問題。

當button添加先後

能夠看到,頁面上出現了一條新的標籤9。可是瀏覽器報錯key重複了。由於v-for我是使用id做爲key的,有兩條相同的數據在視圖上,這是不合理的現象。若是咱們使用map,就徹底不用去擔憂這個事情。咱們不管set多少次都不會有相同的數據影響到重複的key,新的key會替換舊的數據。 舊的 新的

<div class="info-item" v-for="[key, {id, label}] in tableMap" :key="key">
 <span>{{id}}</span>  <span>{{label}}</span> </div> <button @click="pushTable">添加標籤9</button>  複製代碼
// @ pushTbale function 
pushTable () {  this.tableMap.set(9, {  id: 9,  label: '標籤10'  })  this.tableMap = new Map(this.tableMap) },  // createData @moount function const map = new Map() for (let index = 0; index < 10; index++) {  map.set(index, {  id: index,  label: `標籤${index}`,  }) } this.tableMap = map  複製代碼

心得

  • Vue對於Map的響應監聽比較差,當你直接 set,數據更新了。可是沒法通知觀察者更新視圖。當你須要響應更新,只能被動從新設置當前整個 Map,這實際上是不合理的。
  • Map和Object是兩個東西,Map能作到Object有時候作不到的東西,
  • 合理使用Map,思考是否須要用到它。
  • 不要被單一原則固定思惟,思考是否有更好的方式解決問題。(div走遍天,object一招鮮)
  • Map的使用場景很小,可是不要忽視它。

後言

若是以爲對你有幫助,能夠給我點贊哦。各位的支持是對我最好的確定。我的其餘文章推薦。文章內容不必定是最好的解決方法。

v-model源碼分析: 點擊跳轉
前端五月面經: 點擊跳轉

相關文章
相關標籤/搜索