一文帶你詳解Vue2 中的可選鏈式呼叫操作符「?.」

2022-02-14 22:00:09
本篇文章帶大家瞭解一下Vue2 中的可選鏈式呼叫操作符「?.」,聊聊 ?. 在 template中使用報錯的解決方法,希望對大家有所幫助!

一、先說一下什麼是?.(可選鏈式呼叫操作符

可選鏈操作符( ?. )允許讀取位於連線物件鏈深處的屬性的值,而不必明確驗證鏈中的每個參照是否有效。?. 操作符的功能類似於 . 鏈式操作符,不同之處在於,在參照為空(nullish ) (null 或者 undefined) 的情況下不會引起錯誤,該表示式短路返回值是 undefined。與函數呼叫一起使用時,如果給定的函數不存在,則返回 undefined。【相關推薦:】

連結: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Optional_chaining

簡單來說就是我們平時使用「 . 」操作符來獲取物件某個值的一個升級版本。當上一個值不存在時防止undefined.東西報錯。
廢話不多說,直接上程式碼。

let obj = { a: { b: { c: ['冰墩墩', '冬奧會'] } } }

// 當我們想獲取「冰墩墩」的時候
// 如果直接obj.a.b.c[0]的話a、b、c任意一項不存在的話都會報錯

// 正確的做法是
obj && obj.a && obj.a.b && obj.a.b.c && obj.a.b.c[0] // 冰墩墩

// 而採用?.操作符的話 
obj?.a?.b?.c?.[0] // 冰墩墩

當我們工作中遇到巢狀無比深的資料結構時,用&&來校驗屬性是否存在。程式碼就變的十分臃腫。可讀性和維護起來讓人頭皮發麻。但是使用 ?. 就簡潔了不少,可閱讀性也大大提高

二、?. 在 Vue2 template中使用問題

當我們學會一個新的技能興致勃勃想在程式碼的世界中大露一手的時候,發現在Vue2環境下js中能正常使用 ?. ,但是在template中卻報錯。

1.png

Vue2 template中無法正常識別 ?. 操作符 可能是因為 ?. 可選鏈語法比較新,沒有在template中做關於這方面的處理

想必各位都不是等閒之輩,既然能在js中使用那我們就順著思路解決這個問題

三、解決方案

  • 第三方庫 lodash中的 _get 方法
  • 升級到vue3,目前vue3成為預設版本生態趨近於成熟且template支援可選鏈操作符
  • computed計算屬性中使用 ?.
  • 對template原始碼進行攔截更改,程式碼侵入性過高
  • 寫一個hook掛到global/mixins上隨時呼叫

想了一圈只有最後一種方案最靠譜 說幹就幹,讓我們先來書寫一個自己的 ?. 函數

let obj = { a: { b: { c: ['冰墩墩', '冬奧會'] } } }

function variableJudge(obj, keyName, tag = '?.') {
  if (!obj) return undefined
  let keys = keyName.split(tag)
  return keys.reduce((objNew, keyItem) => {
    if (keyItem === '') return objNew
    if (keyItem.indexOf('.') !== -1) return variableJudge1(objNew, keyItem, '.')
    return objNew?.[keyItem]
  }, obj)
}
//------------------------------ Proxy 版本 --------------------------------------
function variableJudgeProxy(obj, tag = '?.') {
  if (!obj) return undefined
  return new Proxy(obj, {
    get: (obj, key) => {
      const keys = key.split(tag)
      return keys.reduce((objNew, keyItem) => {
        if (keyItem === '') return objNew
        if (keyItem.indexOf('.') !== -1) return variableJudgeProxy(objNew, '.')[keyItem]
        return objNew?.[keyItem]
      }, obj)
    }
  })
}
  console.log(variableJudge(obj, '?.a?.b?.c?.0')) //冰墩墩
  console.log(variableJudgeProxy(obj)['?.a?.b?.c?.0']) //冰墩墩

wait wait wait 既然我們要寫自己的 ?. 函數為什麼要定義傳進來的keyName含有 ?. 呢。
為什麼不讓keyName直接是 . 語法而且還擁有 ?. 的功能這樣既符合我們的開發習慣,又能達到我們的預期,豈不美哉
而且按理說如果上一個值是undefined的話我們應該直接reutrn,但是用reduce方法也無法提前中斷。
於是又優化了一版程式碼

let obj = { a: { b: { c: ['冰墩墩', '冬奧會'] } } }

const variableJudge = (obj, keyName) => {
  if (!obj) return null
  let keys = (keyName + '').split('.')
  let tempObj = obj
  for (let i = 0; i < keys.length; i++) {
    if (!tempObj) return
    if (keys[i] !== '') tempObj = tempObj?.[keys[i]]
  }
  return tempObj
}
console.log(variableJudge(obj, '.a.b.c.0')) //冰墩墩

然後我們掛到Vue原型上就可以隨時使用了

Vue.prototype.$vj = variableJudge

讓我們來看一下在template中如何使用

// 省去了臃腫的程式碼為空判斷 是不是賞心悅目了
<div>{{ $vj(ugc, '.itemList.item.pic.picList.1.picUrl') }}</div>

四、總結

?.(可選鏈式呼叫操作符)其實還有很多的妙用等待大家的發掘,本文只為 ?. 在 Vue2 中template中使用報錯的問題來圍繞展開

如果文章 / 程式碼哪裡有可以優化的點歡迎大家提出
本文如果對你產生了幫助可以分享給其他人
既然都看到這裡了,創作不易,留下一個小小的贊吧。

更多程式設計相關知識,請存取:!!

以上就是一文帶你詳解Vue2 中的可選鏈式呼叫操作符「?.」的詳細內容,更多請關注TW511.COM其它相關文章!