简体   繁体   English

将单文件 .vue 组件转换为 JavaScript?

[英]Convert single-file .vue components to JavaScript?

Is there a tool out there that can take a .vue template like this:是否有一种工具可以采用这样的.vue模板:

<template>
  <div>Hello, {{ thing }}</div>
</template>

<script>
  export default {
    data() { return { thing: 'World' }; }
  }
</script>

<style>
  div { background: red; }
</style>

And convert it into a .js file, like this:并将其转换为.js文件,如下所示:

export default {
  template: `
    <div>Hello {{ thing }}</div>
  `,
  data() {
    return {
      thing: 'World'
    }
  }
}

(Not sure what magic it'd do with the CSS, but it'd do something.) (不确定它对 CSS 有什么魔力,但它会做一些事情。)

I'm trying to use native browser modules, which work great, but I'd like to use the .vue file syntax since it offers some nice things.我正在尝试使用本机浏览器模块,它工作得很好,但我想使用.vue文件语法,因为它提供了一些不错的东西。 I'd like to avoid using a bundler like Webpack or Browserify.我想避免使用像 Webpack 或 Browserify 这样的打包器。

I am using Babel.我正在使用巴贝尔。 I have the transform-vue-jsx plugin, but that can't handle the .vue format, only converting the JSX.我有transform-vue-jsx插件,但不能处理.vue格式,只能转换 JSX。

You can utilize vue-template-compiler to parse the *.vue files and extract the relevant sections.您可以使用vue-template-compiler来解析 *.vue 文件并提取相关部分。

I've written a node script which should do the job:我已经编写了一个节点脚本,它应该可以完成这项工作:

convert.js转换.js

const compiler = require('vue-template-compiler');

let content = '';

process.stdin.resume();

process.stdin.on('data', buf => {
    content += buf.toString();
});

process.stdin.on('end', () => {
    const parsed = compiler.parseComponent(content);
    const template = parsed.template ? parsed.template.content : '';
    const script = parsed.script ? parsed.script.content : '';

    const templateEscaped = template.trim().replace(/`/g, '\\`');
    const scriptWithTemplate = script.match(/export default ?\{/)
        ? script.replace(/export default ?\{/, `$&\n\ttemplate: \`\n${templateEscaped}\`,`)
        : `${script}\n export default {\n\ttemplate: \`\n${templateEscaped}\`};`;

    process.stdout.write(scriptWithTemplate);
});

To convert all *.vue files to *.vue.js, run the following bash command inside the directory containing the *.vue files (assuming you're using linux or macOS):要将所有 *.vue 文件转换为 *.vue.js,请在包含 *.vue 文件的目录中运行以下 bash 命令(假设您使用的是 linux 或 macOS):

find . -name '*.vue' -exec bash -c 'node convert.js < "{}" > "{}.js"' \;

This will result in the following conversion:这将导致以下转换:

foo.vue foo.vue

<template>
    <div>a</div>
</template>

<script>
    export default {
        name: 'foo',
    };
</script>

<style>
    /* Won't be extracted */
</style>

foo.vue.js (generated) foo.vue.js(生成)

export default {
    template: `
        <div>a</div>
    `,
    name: 'foo',
};

You might want to tweak the script so that it deals with extracting the styles (however you want that to be handled) and fixing up whitespace and stuff like that.您可能想要调整脚本,以便它处理提取样式(无论您希望如何处理)并修复空白和类似的东西。

I've put together an online vue converter which allows you to copy/paste your vue-file and convert it to said javascript.我已经建立了一个在线 vue 转换器,它允许您复制/粘贴您的 vue 文件并将其转换为上述 javascript。

https://fluxfx.nl/htools/vue-conv https://fluxfx.nl/htools/vue-conv

在线 Vue 转换器

This is my edit for Typescript这是我对 Typescript 的编辑

const parser = require("vue-template-compiler");
const fs = require("fs");
const path = require("path");
const glob = require("glob");

function getFiles(src, callback) {
  glob(src + "/**/*.vue", callback);
}

getFiles(path.join(__dirname, "../src"), function(err, filePaths) {
  if (err) {
    console.log("Error", err);
  } else {
    filePaths.forEach(filePath => {
      fs.readFile(filePath, "utf8", (err, data) => {
        if (err) throw err;
        const parsed = parser.parseComponent(data);
        if (!parsed.script) {
          return;
        }
        fs.writeFile(
          filePath.replace("vue", "ts"),
          parsed.script.content,
          err => {
            if (err) throw err;
            console.log(`The file ${filePath} has been created!`);
          }
        );
      });
    });
  }
});

I am using it for sonarcube static analyses of my typscript codes, since sonarcube does not support vue SFC for now.我使用它对我的打字稿代码进行声纳立方体静态分析,因为声纳立方体目前不支持 vue SFC。

There is no cleanup, because I am running it in gitlab pipeline so after pipeline is done, it is all cleaned automatically.没有清理,因为我在 gitlab 管道中运行它,所以在管道完成后,它会自动清理。

Thanks :)谢谢 :)

Here's an updated version that works with Vue 3 single file components:这是一个适用于 Vue 3 单文件组件的更新版本:

package.json:包.json:

{
      "name": "vue3-sfc-convert",
      "version": "3.0.0",
      "description": "",
      "main": "convert.js",
      "scripts": {
        "convert": "node convert.js"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "glob": "^7.2.0",
        "vue": "^3.2.20"
      },
      "devDependencies": {
        "@vue/compiler-sfc": "^3.2.20"
      }
}

convert.js转换.js

/**
 * convert.js
 * 
 * Convert Vue3 Single File Component to stand-alone script with template property
 * Run node convert.js in directory containing *.vue files
 * Output will be .vue files converted to .ts files with template property set to contents of SFC template block
 */
const sfcCompiler = require("@vue/compiler-sfc");
const fs = require("fs");
const glob = require("glob");

const COMPONENT_START = "export default defineComponent({";

function convertSFC(filePath) {
  try {
    fs.readFile(filePath, "utf8", (err, data) => {
      if (err) {
        console.log(err);
      } else {
        try {
          const parsed = sfcCompiler.parse(data);
          if (!parsed.descriptor) {
            return;
          }
          let templateEncoded = parsed.descriptor.template
              ? parsed.descriptor.template.content
                  .replace(/[\n\r]/gi, " ")
                  .replace(/\"/gi, '\\"')
                  .replace(/\s\s+/gi, " ")
              : null,
            templateLine = templateEncoded ? `\ntemplate: "${templateEncoded}",\n` : "",
            justScript = parsed.descriptor.script.content,
            startPos = justScript.indexOf(COMPONENT_START),
            scriptAndTemplate =
              justScript.substring(0, startPos + COMPONENT_START.length) +
              templateLine +
              justScript.substring(startPos + COMPONENT_START.length);
          fs.writeFile(
            filePath.replace("vue", "ts"),
            scriptAndTemplate,
            (err) => {
              if (err) throw err;
              console.log(`The file ${filePath} has been created!`);
            }
          );
        } catch (parseError) {
          console.log(parseError);
        }
      }
    });
  } catch (readError) {
    console.log(readError);
  }
}

glob("**/*.vue", {}, (err, files) => {
  console.log(`Convert ${files.length} SFCs...`);
  files.forEach((filePath) => {
    convertSFC(filePath);
  });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM