【问题标题】:VueJs templating. How to load external templatesVueJs 模板。如何加载外部模板
【发布时间】:2015-10-16 11:40:30
【问题描述】:

我是 Vue.js 的新手,我使用 AngularJS 已经有一段时间了,我们曾经在 Angular 中加载模板,例如,

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

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

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

这对小模板没问题,但对于大模板,这实用吗?

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

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

【问题讨论】:

  • 真糟糕...
  • 所以基本上 vuejs 是纯粹的时尚

标签: javascript jquery angularjs vue.js


【解决方案1】:

您可以使用脚本标签模板,只需参考其id

{
  template: '#some-id'
}

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

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

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

【讨论】:

  • 您能否像在&lt;style&gt; 元素中设置lang='sass' 一样将模板的语言设置为Slim 或Haml 之类的语言?如果是这样,是否有其他依赖项可以使转译工作?
  • 回答了我自己的问题。支持的引擎是found here
  • 那篇博文中唯一有价值的论点是关于请求数量的论点。其余的都是意见和bs。使用 .vue 来突出显示正确的语法?在我不得不使用 .vue 文件之前,我有正确的语法高亮。
  • “为什么没有模板 url”中提出的观点不是基本上使微前端成为不可能吗?
  • @NicuSurdu 实际上这正是 Angular 如此臃肿和沉重的原因。我同意这对开发人员来说更容易,但客户遭受了很多痛苦。
【解决方案2】:

你可以试试这个:
对于 Vue2:https://github.com/FranckFreiburger/http-vue-loader
对于 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))
  },
  ...

【讨论】:

  • 不推荐在生产环境中使用,很遗憾。看起来使用npmwebpack 是唯一的选择。
  • ...是推荐的选择,而不是唯一的选择
  • 好吧,如果你,作为这个插件的创造者,我会试试看。
【解决方案3】:

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

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

当我模拟一个异步操作时,就像上面的例子一样,它可以工作。但是,一旦我“动态”加载外部页面,Vue 就会抱怨,因为 DOM 还没有准备好。 进一步来说: Uncaught TypeError: Cannot set property '<strong>vue</strong>' 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 loader)

【讨论】:

    【解决方案4】:

    我试过http-vue-loader,效果很好。 这个库很容易使用并且有很好的文档和examples

    虽然您不能直接从文件中加载模板,但您仍然可以将 html 保存在单独的单个文件组件中。你甚至可以跳过&lt;script&gt;...&lt;/script&gt; 部分。

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

    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>
    

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

    【讨论】:

      【解决方案5】:

      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

      【讨论】:

      • Vue 文档中描述可以实现延迟加载的“异步组件”部分:vuejs.org/v2/guide/…
      • 浏览器是否默认启用 ES6?如果没有,我应该如何启用它?
      • @saidfagan 你可以在这里看到:kangax.github.io/compat-table/es6 最新版本的 Chrome、Firefox 和 Safari 支持超过 90% 的 ES6 功能,最新版本的 Microsoft Edge 也相当不错。如果担心的话,IE11 将成为“相关浏览器”支持的落后者。无论哪种方式,如果您想确保始终可以使用像 Babel 这样的转译器来构建与原生兼容的 Javascript
      • 这正是我要做的,谢谢你的回答。
      【解决方案6】:

      至少有 2 种方法可以实现你想要的,其中比尔克里斯韦尔已经提到过(x 模板),但我认为值得添加一个示例

      1. 像这样定义你的组件

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

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

        &lt;script type="text/x-template" id="my-template"&gt;...&lt;/script&gt;

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

      1. 这样定义你的模板

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

      2. 添加包含组件和模板的 html 文件

        &lt;my-template inline-template&gt;place for your html&lt;/my-template&gt;

      只是不要忘记添加inline-template属性,否则不起作用

      【讨论】:

        【解决方案7】:

        您可以将此方法与 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]);
            });
        

        只需将基于 &lt;script&gt; 标记的模板放在服务器上的 something.html 内即可。

        如果你使用 jQuery,.load 应该可以工作。

        只需确保在 Vue 编译相关 DOM 之前完成此操作。或使用$mount 手动设置。

        【讨论】:

          【解决方案8】:

          使用 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']));
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-09-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多