可以在渲染的html中使用带有模板的VueJS SFC组件吗?

时间:2017-10-06 21:14:19

标签: vue.js vue-component

我有单页应用和多页应用(经典网站)的经验。在过去,我在每个页面上都使用过AngularJS 1.x,它非常有用,因为所有组件都可以存在于单独的文件中,并按照它们在每个页面上的显示执行。

我现在正在考虑使用VueJS来取代AngularJS,但却不容易理解如何构建我的多页面应用程序。

正如预期的那样,我想在所有页面上使用一些组件,有些只在几页上使用。

示例:

components

我使用ES2015遇到了 SFC - 单个文件组件,看起来很有前景,但我的后端是Java,它从JSP输出我的html。似乎.vue文件是由webpack预编译的,但是如果我的模板只在呈现页面时才准备好,那么它会不可能吗?

如何构建解决方案以使每个组件都是模块化的,但在html中使用 x-template 并以某种方式将其附加到.vue SFC,或者是否有其他方法可以使用可以使用ES2015导入的单独文件中的组件?

我希望这是有道理的,似乎无法弄清楚。

2 个答案:

答案 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如何处理渲染和组件的提示......