@[TOC](vue2 插值语法中使用可选链运算符(.?)compile异常排查思路)
前言
最近接到组内前端求助,在使用v-for进行动态渲染的时候项目突然不能正常编译了,报错提示SyntaxError: Unexpected token ...
十分奇怪
代码可参考如下:
<h3>动态渲染内容</h3><el-row v-for="(item, index) in form.subObjList" :key="index" :gutter="12" :style="{ background: '#edfced' }"><el-col> {{item?.projectNameLabel}}:{{item?.projectName}}</el-col><el-col> {{item?.technicalPointLabel}}:{{item?.technicalPoint}}</el-col><el-col> {{item?.mainFunctionLabel}}:主要功能:{{item?.mainFunction}}</el-col><el-col> {{item?.difficultyLabel}}:{{item?.difficulty}}</el-col><el-col><hr></el-col></el-row>
待渲染的数据
this.form.subObjList = [{ projectNameLabel: '项目名称',projectName: 'xx项目前端',technicalPointLabel: '技术点',technicalPoint: 'vue vuex vue-router js',mainFunctionLabel: '主要功能',mainFunction: '前端交互ux整改,完善用户体验',difficultyLabel: '难点',difficulty: '大批量数据渲染'},{ projectNameLabel: '项目名称',projectName: 'xx项目后端',technicalPointLabel: '技术点',technicalPoint: 'springboot mybatis redis pgsql',mainFunctionLabel: '主要功能',mainFunction: '支持用户的特定业务流程',difficultyLabel: '难点',difficulty: '大批量数据校验'}]
排查思路
把新增的代码区域el-row
以及内部el-col
注释掉,重新加载检查编译情况,这时能成功编译
接着在放开el-row
新增自定义el-col
,重新加载检查编译情况,能够成功编译和渲染
<h3>动态渲染内容</h3><el-row v-for="(item, index) in form.subObjList" :key="index" :gutter="12" :style="{ background: '#edfced' }"><el-col>heheda</el-col>
<!-- <el-col> {{item?.projectNameLabel}}:{{item?.projectName}}</el-col>-->
<!-- <el-col> {{item?.technicalPointLabel}}:{{item?.technicalPoint}}</el-col>-->
<!-- <el-col> {{item?.mainFunctionLabel}}:主要功能:{{item?.mainFunction}}</el-col>-->
<!-- <el-col> {{item?.difficultyLabel}}:{{item?.difficulty}}</el-col>-->
<!-- <el-col><hr></el-col>--></el-row>
观察到插值语法中的可选链运算符(.?
)比较怪,于是选取一个el-col
去掉.?
并放开注释,可以正常渲染
再次加上.?
,重现了编译失败
由此可以确认是在插值语法中使用可选链运算符(.?
)引起的
临时解决措施
去掉可选链运算符(.?
),与前端确认,此处动态渲染的数据需请求接口得到,item的属性没有在data()
中申明,所以使用(.?
)来避免一些潜在的问题
后续
处理完这个问题后,计划在个人PC上复现,但是并没有复现成功(环境为vue 3.4.28
& node 18.20.4
),经过搜查发现该问题会在vue2低版本上出现,此时相应的node.js版本不支持在插值语法中使用可选链运算符,于是搭建了(vue 2.6.10
& node 14.16
),确实成功复现了这个问题。求助的项目vue版本为2.5.x
,考虑到不久后该项目就会升级vue 3
,所以没有深究如何在vue 2
中实现插值语法可以使用可选链运算符号。
此处分享在vue3中该案例的完整代码:
<template><div><h3>Welcome</h3><el-form :model="form" label-width="100px"><el-row :gutter="20"><el-col :span="12"><el-form-item label="姓名"><el-input v-model="form.name"></el-input></el-form-item></el-col><el-col :span="12"><el-form-item label="年龄"><el-input v-model="form.age"></el-input></el-form-item></el-col></el-row><el-row :gutter="20"><el-col :span="8"><el-form-item label="地址"><el-input v-model="form.address"></el-input></el-form-item></el-col></el-row><h3>动态渲染内容</h3><el-row v-for="(item, index) in form.subObjList" :key="index" :gutter="12" :style="{ background: '#edfced' }"><el-col> {{item?.projectNameLabel}}:{{item?.projectName}}</el-col><el-col> {{item?.technicalPointLabel}}:{{item?.technicalPoint}}</el-col><el-col> {{item?.mainFunctionLabel}}:主要功能:{{item?.mainFunction}}</el-col><el-col> {{item?.difficultyLabel}}:{{item?.difficulty}}</el-col><el-col><hr></el-col></el-row></el-form><button @click="setRenderInfo">动态渲染赋值</button><button @click="clearRenderInfo">动态渲染清空</button></div>
</template><!--vue3写法-->
<!--<script setup lang="ts" name="About">
import { reactive, ref } from 'vue'
import type { ComponentSize, FormProps } from 'element-plus'let form = {name: '松树戈',age: '66',address: '这里',secondLabel: '我就是第二个标题',subObjList: []}
// 模拟远程请求后对subObjList进行赋值
form.subObjList = [{ projectNameLabel: '项目名称',projectName: 'xx项目前端',technicalPointLabel: '技术点',technicalPoint: 'vue vuex vue-router js',mainFunctionLabel: '主要功能',mainFunction: '前端交互ux整改,完善用户体验',difficultyLabel: '难点',difficulty: '大批量数据渲染'},{ projectNameLabel: '项目名称',projectName: 'xx项目后端',technicalPointLabel: '技术点',technicalPoint: 'springboot mybatis redis pgsql',mainFunctionLabel: '主要功能',mainFunction: '支持用户的特定业务流程',difficultyLabel: '难点',difficulty: '大批量数据校验'}
]
</script>-->
<!--vue2写法-->
<script>export default {data() {return {form: {name: '松树戈',age: '66',address: '这里',secondLabel: '我就是第二个标题',subObjList: []}}},mounted() {console.log('在-mounted内部')},methods: {setRenderInfo() {this.form.subObjList = [{ projectNameLabel: '项目名称',projectName: 'xx项目前端',technicalPointLabel: '技术点',technicalPoint: 'vue vuex vue-router js',mainFunctionLabel: '主要功能',mainFunction: '前端交互ux整改,完善用户体验',difficultyLabel: '难点',difficulty: '大批量数据渲染'},{ projectNameLabel: '项目名称',projectName: 'xx项目后端',technicalPointLabel: '技术点',technicalPoint: 'springboot mybatis redis pgsql',mainFunctionLabel: '主要功能',mainFunction: '支持用户的特定业务流程',difficultyLabel: '难点',difficulty: '大批量数据校验'}]},clearRenderInfo() {this.form.subObjList = []}}}
</script>
<style scoped>
.about {display: flex;justify-content: center;align-items: center;height: 100%;color: rgb(85, 84, 84);font-size: 18px;
}
</style>
demo项目完整代码:
码云
gitehub