小记一下,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>
// 看着是不是头皮发麻
目前探索出三种解决方案
- 升级到vue3,目前vue3框架生态趋近于成熟且template支持可选链操作符
- 进行template源码拦截更改,成功解决但是,侵入性过高
- 抒写一个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'
]
}