如何在 VueJs 的模板中加载外部 html 文件
How to load external html file in a template in VueJs
我是 vue js 的新手。
我只是在创建一个简单的项目,我只是通过 CDN 包含 vuejs。不使用 node/npm 或 cli.
我将所有 html 标记保存在单个 html 中,随着它的增长看起来很乱。我试图将 html 拆分为视图,并希望通过类似于 angularJs
的 ng-include
的方式包含它
我以前在 angular 工作过,那里 ng-include
可以加载外部 html 文件。我正在寻找类似于 vue 中的东西。重点是将我的 html 文件拆分为更易于维护的单独文件。
遇到过<template src="./myfile.html"/>
但是没用
有人可以帮我吗
你不能。您必须使用异步组件 - 阅读指南 here
这实际上非常简单,但您需要记住一些事情。在幕后,Vue 将您的 html 模板标记转换为代码。也就是说,您看到的每个定义为 HTML 的元素都会转换为 javascript 指令以创建一个元素。模板很方便,所以如果不使用 webpack 之类的东西进行编译,就无法实现单文件组件(vue 文件)。相反,您需要使用其他一些模板化方式。幸运的是,还有其他定义模板的方法不需要预编译并且可用于这种情况。
1 - string/template 文字
示例: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;博士;
在以下位置查看实际效果:https://repl.it/OEMt/9
其实你可以。这有点简单。取决于您的需求和情况。但是,这段代码在技术上并不正确,但是它会向您解释它是如何工作的,给您很大的自由度并使您的原始 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>
页面-one.html内容
<select>
<option v-for="num in 20">{{ num }}</option>
</select>
页面-two.html内容
// what ever you like
路由器说明
为了使这项工作完美进行,您需要找到一种正确的方法来配置您的 htaccess,以便在第一个视图之后的当前页面不是索引时呈现所有内容。其他一切都应该工作正常。
如你所见,如果是index,就会加载hello内容文件。
我遇到了同样的问题,我就是这样解决的,我还制作了一个关于这个问题的视频https://www.youtube.com/watch?v=J037aiMGGAw
- 为您的组件(逻辑)创建一个 js 文件,我们将其命名为“aaaa.vue.js”
- 为您的模板创建一个 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
当然可以,我们在应用程序的所有组件中都采用这种方式。
<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 文件。就是这样。
我是 vue js 的新手。 我只是在创建一个简单的项目,我只是通过 CDN 包含 vuejs。不使用 node/npm 或 cli.
我将所有 html 标记保存在单个 html 中,随着它的增长看起来很乱。我试图将 html 拆分为视图,并希望通过类似于 angularJs
的ng-include
的方式包含它
我以前在 angular 工作过,那里 ng-include
可以加载外部 html 文件。我正在寻找类似于 vue 中的东西。重点是将我的 html 文件拆分为更易于维护的单独文件。
遇到过<template src="./myfile.html"/>
但是没用
有人可以帮我吗
你不能。您必须使用异步组件 - 阅读指南 here
这实际上非常简单,但您需要记住一些事情。在幕后,Vue 将您的 html 模板标记转换为代码。也就是说,您看到的每个定义为 HTML 的元素都会转换为 javascript 指令以创建一个元素。模板很方便,所以如果不使用 webpack 之类的东西进行编译,就无法实现单文件组件(vue 文件)。相反,您需要使用其他一些模板化方式。幸运的是,还有其他定义模板的方法不需要预编译并且可用于这种情况。
1 - string/template 文字
示例: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;博士;
在以下位置查看实际效果:https://repl.it/OEMt/9
其实你可以。这有点简单。取决于您的需求和情况。但是,这段代码在技术上并不正确,但是它会向您解释它是如何工作的,给您很大的自由度并使您的原始 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>
页面-one.html内容
<select>
<option v-for="num in 20">{{ num }}</option>
</select>
页面-two.html内容
// what ever you like
路由器说明
为了使这项工作完美进行,您需要找到一种正确的方法来配置您的 htaccess,以便在第一个视图之后的当前页面不是索引时呈现所有内容。其他一切都应该工作正常。
如你所见,如果是index,就会加载hello内容文件。
我遇到了同样的问题,我就是这样解决的,我还制作了一个关于这个问题的视频https://www.youtube.com/watch?v=J037aiMGGAw
- 为您的组件(逻辑)创建一个 js 文件,我们将其命名为“aaaa.vue.js”
- 为您的模板创建一个 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
当然可以,我们在应用程序的所有组件中都采用这种方式。
<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 文件。就是这样。