我有单页应用和多页应用(经典网站)的经验。在过去,我在每个页面上都使用过AngularJS 1.x,它非常有用,因为所有组件都可以存在于单独的文件中,并按照它们在每个页面上的显示执行。
我现在正在考虑使用VueJS来取代AngularJS,但却不容易理解如何构建我的多页面应用程序。
正如预期的那样,我想在所有页面上使用一些组件,有些只在几页上使用。
示例:
我使用ES2015遇到了 SFC - 单个文件组件,看起来很有前景,但我的后端是Java,它从JSP输出我的html。似乎.vue文件是由webpack预编译的,但是如果我的模板只在呈现页面时才准备好,那么它会不可能吗?
如何构建解决方案以使每个组件都是模块化的,但在html中使用 x-template 并以某种方式将其附加到.vue SFC,或者是否有其他方法可以使用可以使用ES2015导入的单独文件中的组件?
我希望这是有道理的,似乎无法弄清楚。
答案 0 :(得分:3)
一种可能的方法是为内嵌的Vue组件设置模板。所以这将是一个像
这样的组件文件Home.vue:
<script>
export default {
data() {
return {
msg: 'text',
}
}
}
</script>
将其导入为Vue的全局组件(使用require,import等)
Vue.component('home', require('./components/Home.vue'));
并且在您的服务器生成的HTML中,您必须使用内联模板,该模板具有普通模板的所有灵活性
针对home.jsp:
<home inline-template>
<h2 v-text="msg"></h2>
</home>
<强>更新强>
我在GitHub here
上添加了一个示例答案 1 :(得分:1)
如果我理解您的问题,您需要使用HTML制作单个文件组件。
如果是这种情况,您应该使用render()函数和常规组件。
渲染功能决定使用什么作为组件的模板:
<!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<div id="app">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
render (createElement) {
return createElement({
template: '<div>Hello World</div>'
})
},
})
</script>
</body>
</html>
会将Hello World
呈现给屏幕。
现在,让我们看看这个功能是如何被动的:
<script type="text/javascript">
new Vue({
el: '#app',
data: {
count: 0
},
render (createElement) {
return createElement({
template: '<div>Hello World ' + this.count + '</div>'
})
},
created () {
setTimeout(() => {
this.count++
}, 2000)
}
})
</script>
这里,2秒后,<div>Hello World ' + this.count + '</div>
中的计数器将从0增加到1。
现在,如果我们想将模板与数据分开怎么办?
<script type="text/javascript">
new Vue({
el: '#app',
render (createElement) {
return createElement({
template: '<div>Hello World {{ count }}</div>',
data () {
return {foo: 'bar'}
}
})
}
})
</script>
此代码将显示Hello World bar
。
现在,让我们看看如果我们尝试通过http加载模板会发生什么。我们将使用axios
库来执行此操作。让我们创建一个remote.html
文件来包含我们的HTML代码:
<div>
I'm a remote component {{ foo }}
</div>
现在,让我们尝试通过Ajax加载它:
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.min.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
template: null
},
render (createElement) {
return createElement({
template: this.template ? this.template : '<div>Hello World {{ foo }}</div>',
data () {
return {foo: 'bar'}
}
})
},
created () {
axios({
url: '/remote.html',
method: 'get'
}).then(response => {
this.template = response.data
})
}
})
</script>
只要从浏览器加载I'm a remote component {{ foo }}
,此代码就会显示remote.html
。
请注意,传递给createElement函数的对象实际上是一个组件结构。你可以使用相同的方法:
render (createElement) {
return createElement({
template: this.template ? this.template : '<div>Hello World {{ foo }}</div>',
data () {
return {foo: 'bar'}
},
mounted () {
alert('Hello from mounted')
}
})
}
将在浏览器上触发alert
。
无论如何,这是一个包含嵌套组件的完整示例:
的index.html
<!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<div id="app">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.min.js"></script>
<script type="text/javascript">
const headerComponent = {
data () {
return {
template: '<div>Loading...</div>'
}
},
render (createElement) {
return createElement({
template: this.template,
data () {
return {
search: ''
}
}
})
},
created () {
axios('/header.html').then(response => {
this.template = response.data
})
}
}
new Vue({
el: '#app',
data: {
template: null
},
render (createElement) {
return createElement({
template: this.template ? this.template : 'Loading...',
data () {
return {foo: 'bar'}
},
components: {
'my-header': headerComponent
}
})
},
created () {
axios({
url: '/remote.html',
method: 'get'
}).then(response => {
this.template = response.data
})
}
})
</script>
</body>
</html>
了header.html
<div>
<label>Search</label>
<input v-model="search" name=""> The search is: {{ search }}
</div>
我不确定这是否真的是最好的方法,如果我真的回答了这个问题,但它会在列表中给出一些关于Vue如何处理渲染和组件的提示......