关于在vue2 template 中如何使用 ?.可选链操作符

7,537 阅读2分钟

小记一下,vue2 template 中如何使用 ?.可选链操作符问题

最近碰到返回的数据结构嵌套的无比深。

const data = {
  a: {
    b: {
      c: 'c',
      d: [1, 2, 3],
      e: {
        f: {
          g: 1433223
        }
      }
    }
  }
}

// 如果你需要取c, 如果直接 obj.a.b.c 这样是会报错的,在template中直接导致页面的运行错误
// 如果你需要取c, 在以前正确的做法是: obj && obj.a && obj.a.b && obj.a.b.c || ''
// 如果你需要取c, 现在的做法是 采用可选链操作符: obj?.a?.b?.c 就可以取到值了

这样的嵌套深的结构同时也知道了vue2的template不支持可选链的情况,主要是可选链语法挺新的,以前我就碰到到这个问题并没有在意,但是这次它真的太深了,写的代码奇丑无比

<div>{{ detail && detail.skuInfo && detail.skuInfo.skus && detail.skuInfo.skus[0] && detail.skuInfo.skus[0].sku }}</div>

// 看着是不是头皮发麻

目前探索出三种解决方案

  1. 升级到vue3,目前vue3框架生态趋近于成熟且template支持可选链操作符
  2. 进行template源码拦截更改,成功解决但是,侵入性过高
  3. 抒写一个hooks解决
/**
* 可选链操作方法,可直接用于 template
* @param {*} target 对象源
* @returns Proxy
*/
export const useChain = (target) => {
  return new Proxy(target, {
    get: (target, key) => {
      const keys = key.split('?.')
      return keys.reduce((a, b) => a?.[b], target)
    }
  })
}

使用方式如下

const data = {
  a: {
    b: {
      c: 'c',
      d: [
        { dd: 1 },
        { dd: 2 }
      ],
      e: {
        f: {
          g: 1433223
        }
      }
    }
  }
}
// 如果我要取 c:useChain(data)['a?.b?.c']
// 如果我要取 d下标为1的dd :useChain(data)['a?.b?.d?.1?.dd']

当然如果觉得每次都要引入hooks麻烦的话,各位童鞋们可以将该hooks挂载到 vue原型上或者放在全局mixins中

Vue.prototype.$c = useChain

方法有了来看看在template中如何使用吧

<div>{{ $c(detail)['skuInfo?.skus?.0?.sku'] }}</div>
// 现在看着是不是更加的省心悦目了

如果发现兼容性问题的话请安装可选链的babel插件: @babel/plugin-proposal-optional-chaining ,并在项目根目录的babel.config.js中添加该babel插件

// yarn add @babel/plugin-proposal-optional-chaining -D
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    '@babel/plugin-proposal-optional-chaining'
  ]
}