vue2.x如何像element一样获取组件代码提示。

1,042 阅读2分钟

背景

在 vue2.x 中使用 element 组件会有代码提示如下 image.png 哇哦!用起来真的好爽!

那么我自己的全局组件怎么做到呢?

vetur

image.png

  • 它提供了实现这一因为的方案。
  • 在 package.json 中定义 vetur 并引入 tags/attributes 两个 json 文件

奈斯!接下来就是如何批量的完成这一步骤了

现在就有有 jym 说你可以用 vue-docgen-api 写呀,啊对对对,但是我不听。 没有错以前我通过vue-docgen-api写过这么一篇文章,但是现在我不。我要自己用手写。(手动滑稽)

依赖安装

npm install fs-extra vue-template-compiler @babel/parser @babel/traverse
  • fs-extra:文件操作
  • vue-template-compiler:针对 sfc 文件进行分解
  • @babel/parser:对代码解析得到 ast 树
  • @babel/traverse:遍历 ast 树进行一些操作

我的构思

针对全局组件进行遍历获取组件名称和需要外部传入的 props,进行 ast 树的遍历最总组合成我需要的 tags/attributes 两个 json 文件

初始化代码

const path = require("path");
const fs = require("fs-extra");
const compiler = require("vue-template-compiler");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;

const tags = {};
const attributesJson = {};
// 初始化
const init = async function (src) {
  // 获取根目录
  const rootDir = path.resolve(src);
  // 获取文件列表
  const fileList = await fs.readdir(rootDir);
  if (fileList.length) {
    fileList.forEach(async (dirSrc) => {
      const filePath = `${rootDir}\\${dirSrc}`;
      const isDir = await fs.stat(filePath);
      if (isDir.isDirectory()) {
        // 递归遍历
        recursiveGetSfc(filePath);
      } else {
        // 读取sfc文件
        await readSfc(filePath);
      }
    });
  }
};
const recursiveGetSfc = async function (src) {
  await init(src);
};
  • init:此方法主要是获取文件并对其进行判断是否是文件夹,是文件夹继续遍历获取文件直到拿到所有的组件文件为止
const readSfc = async function (src) {
  const baseName = path.basename(src);
  const tagsAttributes = [];
  let attrName = null;
  // 当为index.vue时做一些处理
  if (baseName === "index.vue") {
    // 读取sfc 获取code
    const code = await fs.readFile(src, "utf-8");
    // 通过vue-template-compiler对code进一步处理获取js部分代码
    const vueScript = compiler.parseComponent(code);
    // 获取ast树
    const ast = parser.parse(vueScript.script.content, {
      plugins: ["jsx"],
      sourceType: "module",
    });
    // 通过traverse对ast树进行遍历
    traverse(ast, {
      ObjectProperty(key) {
        const label = key.node.key.name;
        // leadingComments为//这种注释
        const value =
          key.node.leadingComments && key.node.leadingComments[0].value;
        // 获取组件的名称
        if (key.node.key.name === "name") {
          key = key.node.value.value;
          tags[key] = {
            description: "a global component",
            attributes: tagsAttributes,
          };
          attrName = key;
        }
        if (value) {
          attributesJson[`${attrName}/${label}`] = {
            description: value,
          };
          tagsAttributes.push(label);
        }
      },
    });
    // 创建vetur文件并写入json
    fs.ensureDir("./vetur");
    fs.writeJSON("./vetur/tags.json", tags);
    fs.writeJSON("./vetur/attributes.json", attributesJson);
  }
};
  • 当文件名为 index.vue 时对文件进行 sfc 的解析
  • 通过 parser 函数将 code 转为 ast
  • 用 traverse 对 ast 树进行遍历获取我需要的值
  • 最总输出 json 文件

最后实现

在 pageage.json 中引入如下图: image.png

还有最重要的一点在 pageage.json 引入后需要重启 vscode 去加载它。

效果图

vetur.gif

ending

点个赞呗.