简体   繁体   English

VueJs 模板。 如何加载外部模板

[英]VueJs templating. How to load external templates

I'm new to Vue.js, I've used AngularJS for some time and in angular we used to load templates such as,我是 Vue.js 的新手,我使用 AngularJS 有一段时间了,在 angular 中我们曾经加载过模板,例如,

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

How can we do such a thing in Vue, instead of keeping large HTML templates inside JavaScript like this,我们如何在 Vue 中做这样的事情,而不是像这样在 JavaScript 中保留大型 HTML 模板,

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

This is OK for small templates but for large templates is this practical?这对于小模板来说是可以的,但是对于大模板来说这实用吗?

Is there a way to load external template HTML or use HTML template inside a script tag like in Vue?有没有办法像 Vue 一样加载外部模板 HTML 或在脚本标签内使用 HTML 模板?

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

You can use the script tag template by just referring to its id .您可以通过引用其id来使用脚本标记模板。

{
  template: '#some-id'
}

Though, I highly recommend using vueify (if you use browserify) or vue-loader (if you use webpack) so you can have your components stored in nice little .vue files like this.不过,我强烈建议使用vueify (如果您使用browserify )或vue-loader (如果您使用 webpack),这样您就可以将您的组件存储在像这样的.vue小文件中。

vue 文件

Also, the author of Vue wrote a nice post about the topic of external template urls:另外,Vue 的作者写了一篇关于外部模板 url 主题的好文章:

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

You can try this:你可以试试这个:
for Vue2 : https://github.com/FranckFreiburger/http-vue-loader对于 Vue2: https : //github.com/FranckFreiburger/http-vue-loader
for Vue3 : https://github.com/FranckFreiburger/vue3-sfc-loader对于 Vue3: https : //github.com/FranckFreiburger/vue3-sfc-loader

Example (Vue2) :示例(Vue2):

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

Example (Vue3) :示例(Vue3):

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

David, that is a nice example, but what's the best way to make sure the DOM is compiled?大卫,这是一个很好的例子,但确保 DOM 被编译的最佳方法是什么?

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

When I simulate an async operation, like in the example above, it works.当我模拟一个异步操作时,就像上面的例子一样,它可以工作。 But as soon as I load an external page "on the fly", Vue complains because the DOM is not ready.但是一旦我“即时”加载外部页面,Vue 就会抱怨,因为 DOM 还没有准备好。 More specifically: Uncaught TypeError: Cannot set property ' vue ' of undefined Is there a better way to do this than to call $compile when the page has loaded?更具体地说: Uncaught TypeError: Cannot set property ' vue ' of undefined有没有比在页面加载时调用$compile更好的方法来做到这一点? I've tried with $mount , but that didn't help.我试过$mount ,但这没有帮助。

UPDATE: Never mind, I finally figured out how to do it:更新:没关系,我终于想出了怎么做:

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

And in the actual template, I removed the在实际模板中,我删除了

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

tags and only included the html.标签,只包含 html。

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

I've tried http-vue-loader and it works fine.我试过http-vue-loader ,它工作正常。 This library is easy to use and has good documentation and examples这个库很容易使用并且有很好的文档和例子

Although you can't load templates from filed directly you still can keep html in separate single-file components.尽管您不能直接从文件中加载模板,但您仍然可以将 html 保存在单独的单文件组件中。 You can even skip <script>...</script> part.您甚至可以跳过<script>...</script>部分。

Usage (from loader's documentation)用法(来自加载程序的文档)

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>

Both files should be placed in one folder at the same level两个文件应该放在同一个文件夹中

1. In Vue 2.x I recommend sticking with convention by using .vue files but instead, inverting the order of imports: 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>

and in a separate file并在一个单独的文件中

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

Then in your component registration然后在您的组件注册中

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

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

This way you get the best of both worlds and you don't have to force yourself to build templates within a string.通过这种方式,您可以两全其美,而不必强迫自己在字符串中构建模板。

2. If you want to lazy load, apparently there is a way to do so in Vue 2.x 2.如果你想延迟加载,显然在Vue 2.x中有一种方法可以做到

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

This will load helloworld.js (which will contain all that component's code) on request of that page in the browser.这将根据浏览器中该页面的请求加载 helloworld.js(它将包含所有该组件的代码)。

Of course, all the above assumes you are using ES6 with import capabilities当然,以上所有假设您使用具有import功能的 ES6

there are at least 2 ways to achieve what you want, on of them (x-templates) already mentioned by Bill Criswell, but I think it worth to add an example至少有 2 种方法可以实现你想要的,其中(x 模板)已经被 Bill Criswell 提到过,但我认为值得添加一个例子

  1. Define your component like this像这样定义你的组件

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

  2. Add html file with your x-template (id should match the one you specified in the component)添加带有 x-template 的 html 文件(id 应与您在组件中指定的匹配)

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

Another approach (and I like this one better) would be to use inline template另一种方法(我更喜欢这个方法)是使用内联模板

  1. Define your template like this像这样定义你的模板

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

  2. Add html file with your component and template inside it添加包含组件和模板的 html 文件

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

Just don't forget to add inline-template attribute, otherwise it won't work只是不要忘记添加inline-template属性,否则它将不起作用

You can use this approach with superagent:您可以将此方法与超级代理一起使用:

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]);
    });

Just put your <script> tag based template inside of something.html on your server.只需将基于<script>标签的模板放在服务器上的something.html

If you are using jQuery, .load should work.如果您使用 jQuery, .load应该可以工作。

Just make sure this completes before the DOM in question is compiled by Vue.只需确保在 Vue 编译有问题的 DOM 之前完成。 Or use $mount to manually set things up.或者使用$mount手动设置。

Use browserify to bundle everything like this:使用 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']));

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

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