v-bind 的 .sync 修饰符在 vue3 已移除

但为了更深刻的理解 vue3 模板编译 和 AST,所以我尝试用 AST 实现 .sync 修饰符


vite.config.ts

import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import { transformSync } from './transformSync'export default defineConfig({  plugins: [    vue({      template: { compilerOptions: { nodeTransforms: [transformSync] } }    })  ]})

transformSync.ts

import { createSimpleExpression, DirectiveNode, SimpleExpressionNode, TemplateChildNode } from '@vue/compiler-core'import { remove } from '@vue/shared'const ELEMENT = 1const DIRECTIVE = 7// 创立事件表达式// e.g. @arg="exp"const createEventExpression = (arg?: SimpleExpressionNode, exp?: SimpleExpressionNode) => ({ type: DIRECTIVE, name: 'on', arg, exp, loc: undefined, modifiers: [] } as unknown as DirectiveNode)/** * 将 `.sync` 修饰符转换为 `@update:xxx` * * e.g. * * `<AAA :xxx.sync="value" />` * * ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ * * `<AAA :xxx="value" @update:xxx="value = $event" />` */export function transformSync(node: TemplateChildNode) {  if (node.type === ELEMENT) {    const { props } = node    for (let i = 0; i < props.length; i++) {      const dir = props[i]      // 判断属性是否有 sync 修饰符      if (dir.type == DIRECTIVE && dir.modifiers.includes('sync')) {        remove(dir.modifiers, 'sync')        const { arg, exp } = dir        // @update:xxxx        const name = createSimpleExpression('update:' + arg?.loc.source, true)        // value = $event        const val = createSimpleExpression(exp?.loc.source + ' = $event')        // 为元素增加 @update:xxx="value = $event"        props.push(createEventExpression(name, val))      }    }  }}

以上就是残缺代码了

transformSync.ts 文件去除正文后大略是 30 行代码


让咱们来试试成果

<!-- MyButton.vue --><template>  <button @click="$emit('update:count', count + 1)">count: {{ count }}</button></template><script setup lang="ts">defineProps<{  count: number}>()</script>
<!-- App.vue --><template>  <my-button :count.sync="value" /></template><script setup lang="ts">import { ref } from 'vue'import MyButton from './MyButton.vue'const value = ref(0)</script>

运行胜利

源码地址 | 在线 StackBlitz 编辑


点个赞吧 ✨