难点

4 阅读1分钟
  1. 像react一样传递 属性和方案 自定义属性不行 因为自定义指令主要还是针对dom来的
    不推荐在组件上使用自定义指令 v-xxx="obj" 编译为 把v-xxx="select"翻译成v-bind="select.bindProps" v-on="select.bindEvents",只要我们开发的时候规定绑定组件的hook返回格式必须有bindPropsbindEvents就好了
function Demo(){
    const select = useSelect({
        apiFun:getDict
    })
    // 这里可以直接用...将useSelect返回的属性与方法全部绑定给Select组件
    return <Select {...select}>;
}

// component-enhance-hook
import type { PluginOption } from "vite";

// 可以自定义hook绑定的前缀、绑定的属性值合集对应的键和事件合集对应的键
type HookBindPluginOptions = {
  prefix?: string;
  bindKey?: string;
  eventKey?: string;
};
export const viteHookBind = (options?: HookBindPluginOptions): PluginOption => {
  const { prefix, bindKey, eventKey } = Object.assign(
    {
      prefix: "v-ehb",
      bindKey: "bindProps",
      eventKey: "bindEvents",
    },
    options
  );

  return {
    name: "vite-plugin-vue-component-enhance-hook-bind",
    enforce: "pre",
    transform: (code, id) => {
      const last = id.substring(id.length - 4);

      if (last === ".vue") {
        // 处理之前先判断一下
        if (code.indexOf(prefix) === -1) {
          return code;
        }
        // 获取 template 开头
        const templateStrStart = code.indexOf("<template>");
        // 获取 template 结尾
        const templateStrEnd = code.lastIndexOf("</template>");

        let templateStr = code.substring(templateStrStart, templateStrEnd + 11);

        let startIndex;
        // 循环转换 template 中的hook绑定指令
        while ((startIndex = templateStr.indexOf(prefix)) > -1) {
          const endIndex = templateStr.indexOf(`"`, startIndex + 7);
          const str = templateStr.substring(startIndex, endIndex + 1);
          const obj = str.split(`"`)[1];

          const newStr = templateStr.replace(
            str,
            `v-bind="${obj}.${bindKey}" v-on="${obj}.${eventKey}"`
          );

          templateStr = newStr;
        }

        // 拼接并返回
        return (
          code.substring(0, templateStrStart) +
          templateStr +
          code.substring(templateStrEnd + 11)
        );
      }

      return code;
    },
  };
};