【问题标题】:Convert single-file .vue components to JavaScript?将单文件 .vue 组件转换为 JavaScript?
【发布时间】:2017-12-13 04:15:53
【问题描述】:

有没有可以像这样采用.vue 模板的工具:

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

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

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

并将其转换为.js 文件,如下所示:

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

(不确定它对 CSS 有什么魔力,但它会做一些事情。)

我正在尝试使用本地浏览器模块,效果很好,但我想使用.vue 文件语法,因为它提供了一些不错的东西。我想避免使用像 Webpack 或 Browserify 这样的打包工具。

我正在使用 Babel。我有transform-vue-jsx 插件,但是不能处理.vue 格式,只能转换JSX。

【问题讨论】:

  • 正如所写的,您的问题听起来很像您自己还没有搜索过这个问题?另外,根据您问题的最后一部分,听起来很像您提出了XY problem,您真正的问题应该是“我如何在.vue 文件中制作babel/webpack/etc 捆绑包”,因为这就是您'最终试图解决。例如,github.com/vuejs/vue-loader 如果是 babel + webpack,那么 google 很容易找到。
  • @Mike OP 说他们宁愿避免使用 Webpack 或 Browserify,否则 Webpack 肯定是要走的路。
  • 要反驳“先去哪里解决方案,然后看看你是否仍然不开心”,因为人们已经将使用捆绑器的过程几乎变成了一个预制解决方案现在所有流行的框架。当你已经在使用 babel 时不想使用 webpack/browserify 有点像在马已经狂奔时关上谷仓的门。
  • @Mike'Pomax'Kamermans 我确实做了很多搜索,并且遇到了 webpack 和 browserify 解决方案。它们是不容错过的,它们从单个文件组件的文档开始,并且几乎出现在每个 google 搜索中。但是,正如我所说,我特别不想捆绑,这就是这两个工具所做的。出于某些特定原因,我正在尝试使用新的本机模块功能。不想捆绑与使用 Babel 获得最新最好的 JS 语法支持无关。
  • @Mike 我还想指出,我偶然发现这个问题的原因与 OP 提出的不同,但我专门寻找 OP 所问的问题。有时一个问题可能看起来像“您要求 foo,但您真正想要的是 bar”,但对于发布者和整个社区来说,回答最初提出的问题仍然有价值 - 你永远不知道何时有人确切需要那个。

标签: javascript vue.js babeljs


【解决方案1】:

您可以利用vue-template-compiler 来解析 *.vue 文件并提取相关部分。

我已经编写了一个节点脚本来完成这项工作:

convert.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);
});

要将所有 *.vue 文件转换为 *.vue.js,请在包含 *.vue 文件的目录中运行以下 bash 命令(假设您使用的是 linux 或 macOS):

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

这将导致以下转换:

foo.vue

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

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

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

foo.vue.js(生成)

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

您可能想要调整脚本,以便它处理提取样式(无论您希望如何处理)并修复空白和类似的东西。

【讨论】:

  • 谢谢。这看起来可能正是我所追求的。有点惊讶我找不到那个包,因为它看起来用了不少。必须被vue-loader 的结果掩埋。今晚我会试一试。
【解决方案2】:

我已经组装了一个在线 vue 转换器,它允许您复制/粘贴您的 vue 文件并将其转换为上述 javascript。

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

【讨论】:

    【解决方案3】:

    这是我对 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!`);
              }
            );
          });
        });
      }
    });
    

    我将它用于我的打字稿代码的 sonarcube 静态分析,因为 sonarcube 目前不支持 vue SFC。

    没有清理,因为我是在gitlab管道中运行的,所以管道完成后会自动清理。

    谢谢:)

    【讨论】:

      【解决方案4】:

      这是一个适用于 Vue 3 单文件组件的更新版本:

      package.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

      /**
       * 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);
        });
      });
      

      【讨论】:

        猜你喜欢
        • 2020-08-08
        • 1970-01-01
        • 2012-09-23
        • 2013-11-11
        • 1970-01-01
        • 1970-01-01
        • 2021-04-20
        • 1970-01-01
        • 2020-05-31
        相关资源
        最近更新 更多