marko编译器在编译阶段将模板指令(如if、for、on-click)转换为虚拟dom操作逻辑,而非运行时解析;例如on-click="dosomething()"被转为事件监听器注册代码,而onclick="dosomething()"则作为原生属性保留,不触发响应式绑定。

Marko编译器如何处理模板指令
Marko的模板指令(如if、for、class、on-click)不是运行时解析的,而是在编译阶段被识别并转换为虚拟DOM操作逻辑。这意味着你写的if="showHeader"不会生成字符串拼接或eval调用,而是直接映射为条件分支的JS函数调用。
常见错误现象:在.marko文件里写onclick="doSomething()"——这会被当作原生HTML属性保留,不触发响应式绑定;正确写法是on-click="doSomething()",它会在Transform阶段被转成事件监听器注册代码。
-
for指令支持解构和索引:for|item, i| of=items→ 编译后生成带i参数的循环函数,而非简单Array.prototype.map -
class绑定支持对象/数组语法:class=["active", { disabled: isDisabled }]→ 静态类名提取为常量,动态部分生成运行时计算逻辑 - 自定义指令(如
my-attr)必须提前在compiler.config.js中注册,否则会被忽略或报错Unknown directive "my-attr"
Vue 2 模板编译中指令的 AST 转换逻辑
Vue 2 的parseHTML函数配合4个钩子(start、end、chars、comment)将模板字符串逐步构建为AST节点,其中指令被挂载到node.directives数组里。比如v-if="loading"会被解析为:{ name: 'if', value: 'loading', arg: null, modifiers: {} }。
这个AST结构直接影响后续generate阶段产出的渲染函数。例如v-for会强制生成_l(即renderList)调用,而v-once则会让对应节点标记once: true,跳过后续diff。
- 指令优先级由
directives.js中定义的priority值决定,v-if(700)比v-for(1000)低,所以v-if包裹v-for时,整个列表会被条件控制,而不是每个项单独判断 -
v-model不是单一指令,而是语法糖:对<input>展开为:value+@input,对<select multiple></select>则展开为:value+@change,且自动处理Array.prototype.push等行为 - 自定义指令需在
Vue.directive('focus', {...})中注册,其bind和update钩子只在运行时生效,编译阶段不参与AST转换
HTML转Vue模板时指令迁移的典型陷阱
把静态HTML改写成Vue模板时,最常踩的坑不是结构复制,而是指令语义错位。浏览器忽略v-if这类属性,但Vue编译器会严格校验语法合法性——写错一个引号或漏掉括号,vue-template-compiler就直接抛Parse error: Unexpected token。
使用场景:老项目重构、设计稿切片、第三方HTML片段嵌入。这时候不能只做“属性替换”,得理解每个指令背后的响应式契约。
- 原HTML中的
id="user-name"若被JS用于document.getElementById,迁入Vue后必须改为ref="userName",否则this.$refs.userName拿不到元素 -
style="color: {{ color }}"在原生HTML里是无效语法,Vue中要写成:style="{ color }"或:style="'color: ' + color",前者更安全(自动CSS注入防护) - 含
data-属性的HTML(如data-tooltip="tip")可直接保留,Vue不干涉,但若想响应式更新,就得用:data-tooltip="tooltip"
html-docx-js这类工具为何不处理模板指令
html-docx-js只做纯HTML内容转DOCX,它读取的是最终渲染后的DOM或字符串,不关心源模板是否含v-if或if指令。换句话说,它消费的是编译+挂载后的结果,而非编译前的模板。
如果你传给htmlDocx.asBlob()的是未执行的Vue模板字符串(含{{ msg }}),生成的Word里就会显示字面量{{ msg }};必须确保传入的是已求值的HTML,比如从document.getElementById('export-area').innerHTML获取。
- 服务端渲染(SSR)场景下,务必等
mounted或nextTick后再调用asBlob,否则拿到的是占位符内容 - 使用
shadowRoot或scoped CSS的组件,其样式不会自动包含在innerHTML中,需手动提取getComputedStyle或注入style标签 - 图片路径问题:相对路径(如
./img/logo.png)在Word里无法加载,必须转为base64或绝对URL
html-docx-js运行在用户点击导出的那一刻。两者不在同一生命周期阶段,强行混用会导致内容错位或空白。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











