Vue 3 如何实现一个 `v-const` 指令?

情景

Vue 模板中我们经常会用到一些中间量,比如

<div v-for="item of items">
    {{ item.a.b.c.d1 }}
    <MyComponent :data="item.a.b.c.d2"></MyComponent>
</div>

中的 item.a.b.c

<MyComponent>
    <template #default="{ message }">
        <span class="header">{{ message.split(' ')[0] }}: </span>
        <span v-for="item of message.split(' ').slice(1)">...</span>
    </template>
</MyComponent>

中的 message.split(' ')

问题

由于 v-for<slot> 等的包裹,我们难以利用 computed 简单地提出这些中间量(当然我知道都有普通的解决方案)

我想到 Vue 既然有 v-if / v-for 等和 JavsScript 关键字风格类似的内建指令,能不能实现一个 v-const 来简化代码?

设想中这个指令是这样用的:

<div v-for="item of items">
    <template v-const="data = item.a.b.c">
        {{ data.d1 }}
        <MyComponent :data="data.d2"></MyComponent>
    </template>
</div>
<MyComponent>
    <template #default="{ message }" v-const="[ header, ...tail ] = message.split(' ')">
        <span class="header">{{ header }}: </span>
        <span v-for="item of tail">...</span>
    </template>
</MyComponent>

我想得到的帮助

  • 较简单的实现方案 / 思路
  • Vue 和其它框架如 Svelte 不提供类似指令出于什么原因?性能 / 歧义 / 历史原因?
  • 指令实现后,与 Volar 兼容的可能性 / 相关资料(指的是可以获得补全,而不仅仅是不报错)
阅读 577
1 个回答
Vue.directive('let', {
  bind(el, binding, vnode) {

    const ComponentConstructor = Vue.extend({
      render(createElement) {
        // render函数可以访问this.$slots.default
        return createElement('div', this.$slots.default);
      },
    });

    const componentInstance = new ComponentConstructor({
      // 使用data函数来定义响应式数据
      data() {
        return typeof binding.value === 'function'
          ? binding.value()
          : { value: binding.value };
      },
    });

    // 挂载到一个临时元素上
    const mountNode = document.createElement('div');
    componentInstance.$mount(mountNode);

    // 替换绑定元素的内容
    el.innerHTML = '';
    el.appendChild(componentInstance.$el);
  },
});

自定义指令的类型声明:


declare module 'vue' {
  interface ComponentCustomProperties {
    'v-let': any;
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题