WXML 属性里的中文引号把编译器搞崩了
给一个搜索框写 placeholder,需求很简单:用中文弯引号把默认搜索词括起来,像这样——搜索"xxx"。动态部分是一个 {{initSearchTxt}} 绑定。看起来无害,保存之后微信开发者工具直接编译报错,什么代码都没写错,就是这一行 <input> 炸了。
现象
微信开发者工具 WXML 编译器抛出:
unexpected character `{`
错误光标落在 {{initSearchTxt}} 的第一个 { 上,但这个 mustache 语法明明写对了。代码长这样:
<input placeholder="搜索"{{initSearchTxt}}"" />更诡异的是:这段代码在某些机器上能编译通过,换一台或者重新粘贴一次就挂了。
根因
中文全角弯引号 " (U+201C) 和 " (U+201D) 与 ASCII 双引号 " (U+0022) 长得极像,但字节完全不同。WXML 属性的定界符是 ASCII " (U+0022)。
问题来了:部分版本的 WXML 编译器在词法分析阶段,遇到 U+201C/U+201D 时会将其误判为属性结束符,导致后面的 {{initSearchTxt}} 被扔到属性上下文外面,解析器当然不认识裸露的 {,于是报错。
placeholder="搜索"{{xxx}}""——编译器看到第一个 " 时可能认为属性已经关闭,把 {{xxx}} 推到属性外层,触发 unexpected character {。
这个行为不稳定,取决于编译器版本和文件的字节编码。某些场景下能跑,但换环境或重新粘贴后就复现——这正是最难察觉的地方。
正解
把属性的定界符从 ASCII 双引号换成 ASCII 单引号 ',中文弯引号作为字面字符留在值里,mustache 绑定照常工作:
<!-- 错:用双引号定界,值里还有中文双引号 -->
<input placeholder="搜索"{{initSearchTxt}}"" />
<!-- 对:改用单引号定界 -->
<input placeholder='搜索"{{initSearchTxt}}"' />WXML 和 HTML 一样,属性值可以用单引号或双引号,两者完全等价。单引号定界时,值内部的 ASCII 双引号和中文弯引号都是普通字符,编译器不会歧义。
把外层 "..." 改成 '...',内部的 " " 变成无歧义的字面文本,mustache 绑定不受影响,编译立刻通过。
备选方案
如果不方便换定界符,还有两条路:
- 去掉中文引号,直接
placeholder="搜索{{initSearchTxt}}"——牺牲视觉效果,最简单。 - JS 侧拼接,在
onLoad里setData({ placeholderText: '搜索"' + initSearchTxt + '"' }),模板绑定placeholder="{{placeholderText}}"——干净但多一次数据流。
一句话外卖
属性值里有中文弯引号 + mustache 时,把属性定界符从
"换成',就能避开 WXML 编译器对 U+201C/U+201D 的错误识别。