简体   繁体   English

Vue3 + typescript + composition api - 使用 .ts 文件而不是 SFC/.vue 文件从外部加载模板内容

[英]Vue3 + typescript + composition api - loading template content externally using .ts files not SFCs/.vue files

I'm trying to use the Composition API to defineComponent to define a component instance.我正在尝试使用defineComponent API 来定义组件来定义组件实例。

This is taken from the starting project created using the vue create myapp command.这取自使用vue create myapp命令创建的起始项目。 The script has been put inside an about.ts file, the template content from the About.vue file into into an About.html file (which probably should be a .vue file as its not really html).该脚本已放入 about.ts 文件中,来自 About.vue 文件的模板内容放入了 About.html 文件(可能应该是 .vue 文件,因为它不是真正的 html)。

    import { defineComponent } from "vue";
    export default defineComponent({
      name: "About",
      props: {
        msg: String
      },
      template: require("./About.html").default
    });

This is held in about.ts .这是在about.ts中举行的。

Used in my router/index.ts like so:在我的router/index.ts中使用,如下所示:

    import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
    import Home from "@/views/Home.vue";
    import About from "@/views/About"
    const routes: Array<RouteRecordRaw> = [
      {
        path: "/",
        name: "Home",
        component: Home
      },
      {
        path: "/about",
        name: "About",
        component: About
      }
    ];

    const router = createRouter({
      history: createWebHistory(process.env.BASE_URL),
      routes
    });

    export default router;

It doesn't render anything.它不渲染任何东西。 Looking at the difference between my "about" view and the "home" view it looks like the only difference is the render routine is missing (which is there when you use the .vue file to create your component.查看我的“关于”视图和“主页”视图之间的区别,看起来唯一的区别是缺少渲染例程(当您使用 .vue 文件创建组件时会出现这种情况。

So let's define one:所以让我们定义一个:

    import { defineComponent } from "vue";
    export default defineComponent({
      name: "About",
      props: {
        msg: String
      },
      template: require("./About.html").default,
      render() {
        return "this is a test"
      }
    });

Adding a render routine, I get the rendered content添加渲染例程,我得到渲染的内容

So it seems defineComponent isn't doing what I would expect because I'm using it incorrectly.所以看起来 defineComponent 没有做我期望的事情,因为我使用不正确。 It doesn't define a component as it fails to create a render routine unless it is run inside a script tag.它没有定义组件,因为它无法创建渲染例程,除非它在脚本标签内运行。 So how can I use externally loaded template content with a typescript module?那么如何将外部加载的模板内容与打字稿模块一起使用?

Others are looking at: https://github.com/vuejs/rfcs/issues/96其他人在看: https ://github.com/vuejs/rfcs/issues/96

I'm trying to work out the best way to achieve the goal which is a separation of the templates and associated code.我正在尝试找出实现目标的最佳方法,即分离模板和相关代码。 Presumably the vue file is rendered into seperate parts so what function achieves that?大概 vue 文件被渲染成单独的部分,那么什么功能可以实现呢?

How do you separate all your components out correctly?您如何正确地将所有组件分开?

The template and render options are mutually exclusive, so you should remove render . templaterender选项是互斥的,所以你应该删除render The reason your template isn't appearing is because the template option requires the runtime compiler (it's normally excluded as an optimization, as most users employ precompiled templates).您的模板没有出现的原因是template选项需要运行时编译器(它通常被排除在优化之外,因为大多数用户使用预编译模板)。 You should see a console warning if you try to use template at runtime without the compiler.如果您尝试在没有编译器的情况下在运行时使用template ,您应该会看到控制台警告。

To enable the runtime compiler in a Vue CLI project, set the runtimeCompiler flag :要在 Vue CLI 项目中启用运行时编译器,请设置runtimeCompiler标志

// vue.config.js
module.exports = {
  runtimeCompiler: true,
}

To require the HTML file into a string for the template option, use raw-loader like this: require HTML 文件转换为template选项的字符串,请使用raw-loader ,如下所示:

export default defineComponent({
  template: require('raw-loader!./HelloWorld.html').default
})

Sticking with SFCs...坚持使用 SFC...

Another way to do this is to move the <template> , <script> , and <style> parts into .html , .ts , and .css files respectively, and then import them in the SFC:另一种方法是<template><script><style>部分分别移动到.html.ts.css文件中,然后将它们导入 SFC:

<!-- HelloWorld.vue -->
<template src="./HelloWorld.html"></template>
<script src="./HelloWorld.ts" lang="ts"></script>
<style src="./HelloWorld.css"></style>

The app would still import the component as usual:该应用程序仍将照常导入组件:

<script>
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

Caveat警告

Splitting files out like this would cost IDE support afforded by Vetur .像这样拆分文件会花费Vetur提供的 IDE 支持。 For instance, in the HTML file, you won't get IntelliSense for props declared in the script file.例如,在 HTML 文件中,您不会获得脚本文件中声明的道具的 IntelliSense。

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

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