如何在VueJs中的模板中加载外部html文件

时间:2017-11-02 14:56:09

标签: vue.js vuejs2 vue-component vue-router

我是vue js的新手。 我只是创建一个简单的项目,我只是通过CDN包含vuejs。不使用node / npm或cli。

我将所有的html标记保存在单个html中,随着它的增长看起来很乱。我试图将html拆分为视图,并希望通过类似于ng-include angularJs

的内容来包含它

我之前在角度工作过,有ng-include加载外部html文件。我正在寻找类似于vue的东西。重点是将我的html文件拆分为更易于维护的单独文件。

遇到<template src="./myfile.html"/>,但它不起作用 有人能帮助我吗

6 个答案:

答案 0 :(得分:2)

你不能。您必须使用异步组件 - 阅读指南here

答案 1 :(得分:2)

这实际上非常简单,但你需要记住一些事情。在幕后,Vue将您的html模板标记转换为代码。也就是说,您看到定义为HTML的每个元素都会转换为javascript指令以创建元素。模板很方便,因此单文件组件(vue文件)不是没有像webpack这样的东西编译就能做到的。相反,您需要使用其他一些模板方法。幸运的是,还有其他方法可以定义不需要预编译的模板,并且可以在这种情况下使用。

1 - 字符串/模板文字

示例:template: '<div>{{myvar}}</div>'

2 - 渲染功能

示例:render(create){create('div')}

Vue还有其他几种创建模板的方法,但它们与标准不符。

以下是两个例子:

AddItem.js - 使用渲染函数

'use strict';
Vue.component('add-item', {
  methods: {
    add() {
      this.$emit('add', this.value);
      this.value = ''
    }
  },

  data () {
    return {
      value: ''
    }
  },

  render(createElement) {
    var self = this
    return createElement('div', [
      createElement('input', {
        attrs: {
          type: 'text',
          placeholder: 'new Item'
        },
        // v-model functionality has to be implemented manually
        domProps: {
          value: self.value
        },
        on: {
          input: function (event) {
            self.value = event.target.value
            // self.$emit('input', event.target.value)
          }
        }
      }),
      createElement('input', {
        attrs: {
          type: 'submit',
          value: 'add'
        },
        on: {
          click: this.add
        }
      }),
    ])
  }
});

ListItem.js - 使用模板文字(反向标记)

'use strict';
Vue.component('list-item', {
  template: `<div class="checkbox-wrapper" @click="check">
    <h1>{{checked ? '☑' : '☐'}} {{ title }}</h1>
  </div>`,
  props: [
    'title',
    'checked'
  ],
  methods: {
    check() {
      this.$emit('change', !this.checked);
    }
  }
});

和html

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.0/vue.js"></script>
  <script src="ListItem.js"></script>
  <script src="AddItem.js"></script>
</head>
<body>
<div id="app">
  <add-item @add='list.push({title:arguments[0], checked: false})'></add-item>
  <list-item v-for="(l, i) in list" :key="i" :title="l.title" :checked="l.checked" @change="l.checked=arguments[0]"></list-item>
</div>
<script type="text/javascript">
new Vue({
  el: '#app',
  data: {
    newTitle: '',
    list: [
      { title: 'A', checked: true },
      { title: 'B', checked: true },
      { title: 'C', checked: true }
    ]
  }
});
</script>
</body>
</html>


TL; DR;

请参阅:https://repl.it/OEMt/9

答案 2 :(得分:1)

实际上可以。这很容易。取决于您的需求和情况。但是,此代码在技术上并不正确,但是它将向您说明其工作方式,为您提供了极大的自由,并使原始vue实例更小。

要执行此操作,您将需要vue路由器(cdn可以),在这种情况下,需要axios或fetch(如果您不关心支持较旧的浏览器)。

我认为唯一的不足是,在内容文件中,您将需要添加其他调用参数 $ parent 。这将迫使vue正常工作。

索引

<div id="app">

  <router-link v-for="route in this.$router.options.routes" :to="route.path" :key="route.path">{{ route.name }}</router-link>

  <section style="margin-top:50px;">
     <component :is="magician && { template: magician }" />
  </section>

</div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

  <script>
     const viewer = axios.create({ baseURL: location.origin });

     const routes = [
       {"name":"Hello","slug":"hello","path":"/lol/index.html"},
       {"name":"Page One","slug":"page_one","path":"/lol/page-one.html"},
       {"name":"Page Two","slug":"page_two","path":"/lol/page-two.html"}
     ];

     const app = new Vue({
       router,
       el: '#app',
       data: {
          magician: null,
       },
       watch: {
          $route (to) {
              this.loader(to.path);
          }
       },
       mounted() {
          this.loader(this.$router.currentRoute.path);
       },
       methods: {
          viewer(opt) {
              return viewer.get(opt);
          },
          loader(to) {
              to == '/lol/index.html' ? to = '/lol/hello.html' : to = to;
              this.viewer(to).then((response) => {
                  this.magician = response.data;
              }).catch(error => {
                  alert(error.response.data.message);
              })
          },
          huehue(i) {
            alert(i);
          }
       }
     });
  </script>

hello.html内容

<button v-on:click="$parent.huehue('this is great')">Button</button>

page-one.html内容

<select>
   <option v-for="num in 20">{{ num }}</option>
</select>

page-two.html内容

// what ever you like

路由器说明

要使此功能完美运行,您将需要找到一种正确的方法来配置htaccess,以在第一个视图后的当前页面未建立索引时呈现所有内容。其他一切都应该正常工作。

如您所见,如果它是索引,它将加载hello内容文件。

答案 3 :(得分:0)

ng-include对于为路由器加载模板确实很棒。另一种选择是使用fetch并实现自己的诺言。

答案 4 :(得分:0)

我遇到了同样的问题,这就是我解决它的方法,我还制作了一个关于这个问题的视频https://www.youtube.com/watch?v=J037aiMGGAw

  1. 为你的组件(逻辑)创建一个 js 文件,我们称之为“aaaa.vue.js”
  2. 为您的模板创建一个 HTML 文件,该文件将被注入到您的“aaaa.vue.js”中,我们称之为“aaaa.html”

组件文件(逻辑文件javascript)

const aaaa = {
  name:"aaaa",
  template: ``,
  data() {
    return {
      foo:"aaaa"
    };
  },    
  methods: {
    async test() {
      alert(this.foo)
    },
  },
};

模板文件 (HTML)

<!--template file-->
<div>
  <button @click="test" > click me plz </button>
</div>

index.html

<html>
  <head>
    <title>my app</title>
  </head>

  <body>
    <div id="app" class="main-content col-12">
      <aaaa></aaaa>
    </div>
  </body>
</html>

<script src="axios.min.js"></script>
<script src="vue.js"></script>

<!-- load js file (logic) -->
<script src="aaaa.vue.js"></script>

<script>
  document.addEventListener("DOMContentLoaded", async function () {
    //register components
    let html = await axios.get("aaaa.html"); // <---- Load HTML file
    aaaa.template = html.data;
    Vue.component("aaaa", aaaa);

    new Vue({
      el: "#app",
      name: "main",
      //... etc
    });
  });
</script>

更新: 我还在 github 上创建了一个示例来查看它的实际效果

https://github.com/nsssim/Vue-CDN-load-component

enter image description here

答案 5 :(得分:-1)

当然可以,这就是我们在应用的所有组件中的做法。

<template src="../templates/the_template.html"></template>

<script>
export default {
    name: 'ComponentName',
    props: {},
    computed: {},
    methods: {},
};
</script>

<style lang="scss">
@import '../styles/myscss_file';
</style>

需要添加

runtimeCompiler: true

到你的 vue.config.js 文件。就是这样。