DEBUG.WIKI
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
雨云;给项目一台云服务器
晚安云;香港 CN2 ¥15/月

Vue 动态参数报 Unexpected token '||',v-model 更新也失效

Vue 3.5.44 把动态参数与回退、事件前缀直接拼接,可能生成错误语法或属性名。将名称计算移到脚本区,同时核对模型属性、更新监听和修饰符三个键。

Vue 3.5.44 编译动态参数时,v-bind 可能报 SyntaxError: Unexpected token '||';换成三元表达式后虽然能编译,组件的 v-model 更新事件却收不到,甚至原来的模型值被 modifiers 对象覆盖。这时要检查生成的属性名和事件名,不能只检查模板括号是否成对。

问题集中在动态参数直接写了 ??、?:、|| 等表达式的组合。普通标识符参数不需要与这些运算符争夺优先级,可以作为局部规避入口。

报错发生在拼接后的表达式

3.5.44 的一条 v-bind 转换会给动态参数附加 || ""。参数原本是 foo ?? "id" 时,生成的计算属性可能变成:

{ [foo ?? "id" || ""]: value }

JavaScript 不允许在没有括号分组的情况下这样混用 ?? 和 ||。语法错误来自生成代码,不能通过给 value 换个值解决。

v-model 的影响更隐蔽。编译器还要根据参数生成更新监听名和 modifiers 属性名。例如,参数是 condition ? "foo" : "bar",事件名应为 onUpdate:foo 或 onUpdate:bar。若生成了 "onUpdate:" + condition ? "foo" : "bar",它会先做字符串拼接,再判断三元条件,结果变成普通的 foo,没有所需的 onUpdate: 前缀。

同样,condition ? "foo" : "bar" + "Modifiers" 只给后一个分支加后缀。条件为真时,modifiers 属性可能与模型属性同名,后写入的对象便覆盖前面的值。这不是子组件没有发事件,也不是 .trim 自己把文本变成了对象。

把参数的计算移到脚本区

保留原有参数选择规则,让模板只读取一个标识符。下面是组件结构示例;ModelInput 代表项目中已有、能处理 foo/bar 模型及对应 modifiers 的组件:

<script setup>
import { computed, ref } from 'vue'

const maybeName = ref(undefined)
const condition = ref(true)
const value = ref('')

const attrName = computed(() => maybeName.value ?? 'id')
const modelName = computed(() => condition.value ? 'foo' : 'bar')
</script>

<template>
  <div :[attrName]="value" />
  <ModelInput v-model:[modelName].trim="value" />
</template>

这里计算的是参数名称,v-model 的值仍然绑定到原来可写的 value。不要把 value 随手换成没有 setter 的计算属性,那会引入另一种写入错误。

参数来自已有 props 时,把计算接到那些真实状态上;示例的两个 ref 只是展示两条分支。名称变化后还要确认子组件支持新的模型名称,.trim 等修饰符也需要组件原来的处理逻辑,不能因为生成了 modifiers 属性就认定组件一定执行了它。

同时核对三类生成键

在原来的开发编译与生产构建入口检查实际使用的 Vue、compiler-sfc 和 compiler-core 版本,并重新生成产物。3.5.44 的正式源码仍包含上述拼接方式;不能仅凭一个修复分支或开放修改就认定部署中的编译器已修。

验收分别覆盖条件真假、空值回退及参数后续变化,检查模型属性、onUpdate: 监听属性和 Modifiers 属性是否对应同一个名称。再从子组件发出实际更新事件,确认父级得到正确值,模型值没有被修饰符对象替换。

只看到构建通过不够:三元表达式可以生成合法 JavaScript,却使用了错误的键。采用后续正式版本时,仍用这组条件确认输出;临时移出的参数计算也应与原业务规则一起保留,避免回退时恢复到错误的编译形态。