VueJ模板化。如何加载外部模板


69

我是Vue.js的新手,我已经使用AngularJS一段时间了,并且在过去我们使用Angular来加载模板,例如,

template: '/sometemplate.html',
controller: 'someCtrl'

我们如何在Vue中做这样的事情,而不是像这样在JavaScript中保留大型HTML模板,

new Vue({
  el: '#replace',
  template: '<p>replaced</p>'
})

小型模板可以这样做,但大型模板是否可行?

有没有办法加载外部模板HTML或在Vue中的脚本标签内使用HTML模板?

<script type="x-template" id="template>HTML template goes here</html>

1
真是令人b目结舌……
Daniel F

Answers:


32

您可以通过仅参考脚本模板来使用脚本标签模板id

{
  template: '#some-id'
}

但是,我强烈建议使用vueify(如果 使用browserify)或vue-loader(如果使用webpack),这样就可以将组件存储在这样的漂亮小.vue文件中。

Vue文件

另外,Vue的作者写了一篇关于外部模板URL的主题的不错的文章:

https://vuejs.org/2015/10/28/why-no-template-url/


1
您是否可以lang='sass'像在<style>元素中设置模板一样,将模板的语言设置为Slim或Haml等?如果是这样,是否还有其他依赖关系才能使翻译工作?
詹姆斯·克莱因

1
回答了我自己的问题。可在此处找到
James Klein'1

11
该博客文章中唯一有价值的论点是有关请求数量的论点。其余的是观点和观点。使用.vue突出显示正确的语法?在必须使用.vue文件之前,我有正确的语法突出显示。
Nicu Surdu

“为什么没有模板网址”中的观点基本上不会使微前端成为不可能吗?
Sinaesthetic,

@NicuSurdu实际上,这正是使Angular如此肿胀又沉重的原因。我同意对于开发人员来说比较容易,但是客户遭受了很多痛苦。
克莱顿奥利维拉

17

您可以尝试以下操作:
对于Vue2:https : //github.com/FranckFreiburger/http-vue-loader
for Vue3:https : //github.com/FranckFreiburger/vue3-sfc-loader

范例(Vue2):

 new Vue({
        components: {
            'my-component': httpVueLoader('my-component.vue')
        },
        ...

范例(Vue3):

Vue.createApp({
  components: {
    'my-component': Vue.defineAsyncComponent(() => loadModule('./myComponent.vue', opts))
  },
  ...

1
不幸的是,不建议在生产中使用。看起来像使用npm并且webpack是唯一的选择。
saidfagan

...是推荐的选择,而不是唯一的选择
Franck Freiburger

2
好吧,如果您作为此插件的创建者,请考虑一下,所以我将尝试一下。
saidfagan

14

David,这是一个很好的例子,但是确保DOM编译的最佳方法是什么?

https://jsfiddle.net/q7xcbuxd/35/

当我模拟异步操作时(如上例所示),它可以工作。但是,一旦我“快速”加载外部页面,Vue就会抱怨,因为DOM还没有准备好。更具体地说: 是否有比在加载页面时调用更好的方法?我尝试过使用,但没有帮助。Uncaught TypeError: Cannot set property 'vue' of undefined$compile$mount

更新: 没关系,我终于想出了办法:

Vue.component('async-component', function (resolve, reject) {
    vue.$http.get('async-component.html', function(data, status, request){
        var parser = new DOMParser();
        var doc = parser.parseFromString(data, "text/html");
        resolve({
            template: doc
        });
    });
});

在实际模板中,我删除了

<script id="someTemplate" type="text/x-template"></script>

标签,仅包含html。

(此解决方案需要来自https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.1.10/vue-resource.min.js的http加载器)


4

1.在Vue 2.x中,我建议使用.vue文件坚持约定,但相反,请反转导入顺序:

// template.vue
<template>
  <div class="helloworld">
      <h1>Hello world</h1>
  </div>
</template>

<script>
  import src from './src'
  export default src
</script>

并在单独的文件中

// src.js
export default {
  name: 'helloworld',
  props: {},
  ...
}

然后在您的组件注册

import helloworld from './helloworld/template.vue'

new Vue({
 components: {
 'helloworld': helloworld
},
...})

这样一来,您就可以兼顾两全其美,而不必强迫自己在字符串中构建模板。

2.如果您想延迟加载,显然在Vue 2.x中可以这样做。

new Vue({
 components: {
 'helloworld': () => import(/* webpackChunkName: "helloworld" */ './helloworld/template.vue')
},
...})

这将根据浏览器中该页面的请求加载helloworld.js(将包含该组件的所有代码)。

当然,以上所有条件均假设您正在使用具有以下import功能的ES6


1
Vue文档中描述可实现延迟加载的“异步组件”的部分:vuejs.org/v2/guide/…–
ako977

浏览器默认情况下是否启用ES6?如果没有,我应该如何启用它?
saidfagan

1
您可以在此处看到@saidfagankangax.github.io/compat-table/es6 Chrome,Firefox和Safari的最新版本支持90%以上的ES6功能,Microsoft Edge的最新版本也相当不错。如果担心,IE11将成为“相关浏览器”支持的落后者。无论哪种方式,如果您要确保可以始终使用Babel这样的编译器来构建与香草兼容的Javascript
ako977

这正是我要做的事情,谢谢您的回答。
saidfagan

4

我已经尝试过http-vue-loader,并且工作正常。该库易于使用,并具有良好的文档和示例

尽管您无法直接从模板中加载模板,但仍可以将html保留在单独的单文件组件中。您甚至可以跳过<script>...</script>一部分。

用法(来自加载程序的文档)

my-component.vue

<template>
    <div class="hello">Hello {{who}}</div>
</template>

index.html

<!doctype html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/http-vue-loader"></script>
  </head>

  <body>
    <div id="my-app">
      <my-component></my-component>
    </div>

    <script type="text/javascript">
      new Vue({
        el: '#my-app',
        components: {
          'my-component': httpVueLoader('my-component.vue')
        }
      });
    </script>
  </body>
</html>

两个文件应放在同一级别的一个文件夹中


1

比尔·克里斯威尔(Bill Criswell)已经提到了至少两种实现您想要的方法(x模板),但是我认为值得添加一个示例

  1. 这样定义您的组件

    Vue.component('my-checkbox', { // id of x-template template: '#my-template' });

  2. 使用x模板添加html文件(ID应与组件中指定的ID匹配)

    <script type="text/x-template" id="my-template">...</script>

另一种方法(我更喜欢这种方法)是使用内联模板

  1. 像这样定义您的模板

    Vue.component('my-template', {});

  2. 添加带有组件和模板的html文件

    <my-template inline-template>place for your html</my-template>

只是不要忘记添加inline-template属性,否则它将无法正常工作


0

您可以将这种方法用于超级代理:

var promise = superagent.get("something.html")
    .end(function (error, response) {
        if (error) {
            console.error("load of something.html failed", error));
            return;
        }

        var parser = new DOMParser()
        var doc = parser.parseFromString(response.text, "text/html");
        document.body.appendChild(doc.scripts[0]);
    });

只需将<script>基于标签的模板放在something.html服务器上即可。

如果您使用的是jQuery,则.load应该可以工作。

只要确保在有关的DOM由Vue编译之前完成即可。或使用$ mount手动设置。


0

使用browserify捆绑所有内容,如下所示:

//Home.js

import Vue from 'vue';

var Home = Vue.extend({
    template: require('./Home.vue')
});

export default Home;

//Home.vue
<h1>Hello</h1>

// And for your browserify bundle use a transform called stringify

... .transform(stringify(['.html', '.svg', '.vue', '.template', '.tmpl']));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.