Vue 教程第六篇—— 組件

組件

組件(Component)是前端在單頁面應用(SPA)上最好的一種實現方式,把全部功能模塊拆解成單獨的組件,每一個組件都有獨立的做用域,且還能夠相互通訊javascript

認識單頁面應用(SPA)

在傳統的頁面之間跳轉,是經過刷新,從新渲染一個頁面而實現,在渲染的過程當中勢必要加載外部資源文件,頁面在服務器中渲染出來是經過一系列的生命週期,在這個過程當中會由於網速等硬件問題直接影響頁面的加載速度,爲解決這一問題,前端在新的設計模式上引入了組件的概念,頁面之間的跳轉變成了組件之間的切換,不須要從新加載整個頁面,也不用考慮頁面的生命週期,換成組件的生命週期,在性能上大大的提高了。html

Vue 的組件實現

全局組件

<div id="app">
        <!--組件的使用-->
        <global-component></global-component>
    </div>
//組件的定義 Vue.component(組件名稱, {template})
    Vue.component('global-component', {
        template: '<h1>全局組件</h1>'
    })

    var vm = new Vue({
        el: '#app'
    })

最終渲染的效果前端

<div id="app">
        <h1>全局組件</h1>
    </div>

局部組件

<div id="app">
        <!--組件的使用-->
        <private-component></private-component>
    </div>
//組件的定義 Vue.component(組件名稱, {template})
    var vm = new Vue({
        el: '#app',
        components:{
            'private-component': {
                template: '<h1>局部組件</h1>'
            }
        }
    })

最終渲染的效果vue

<div id="app">
        <h1>局部組件</h1>
    </div>

組件是一個單獨的做用域

每一個組件都有單獨的做用域java

<div id="app">
        <p>{{count}}</p>
        <component1/>
    </div>
var vm = new Vue({
        el: '#app',
        data: {
            count: 10
        },
        methods: {
            increment: function(){
                this.count += 1;
            }
        },
        components:{
            'component1': {
                template: '<button v-on:click="increment">{{ count }}</button>',
                data: function(){
                    //在組件裏面 data 必定是 function 並返回一個對象
                    return {
                        count: 0
                    }
                },
                methods: {
                    increment: function(){
                        this.count += 1;
                    }
                }
            }
        }
    })

渲染結果爲git

<div id="app">
        <p>10</p>
        <!--
            此按鈕每次點擊都會自增 1,而 p 標籤永遠都是爲 10
            緣由爲組件的做用域是單獨的
        -->
        <button>0</button>
    </div>

效果預覽github

特殊的 HTML 結構中使用 is

好比在下拉列表(select)元素裏面,子元素必須爲 option,則在使用組件的時候用 is設計模式

<div id="app">
        <select>
            <option is="privateOption"></option>
        </select>
    </div>
var vm = new Vue({
        el: '#app',
        components: {
            'privateOption': {
                template: '<option value=1>1</otpion>'
            }
        }
    })

渲染結果服務器

<div id="app">
        <select>
            <option value="1">1</option>
        </select>
    </div>

動態組件 - :is

<div id="app" style="display: none;">
    <input type="button" value="changeLight" @click="changeLight" />
    <br/>
    <p :is="show"></p>
</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            show: 'red',
        },
        methods:{
            changeLight: function(){
                this.show = this.show == 'red' ? 'green' : 'red';
            }
        },
        components: {
            red: {
                template: '<h1>Red</h1>'
            },
            green: {
                template: '<h1>Green</h1>'
            }
        }
    })
</script>

組件屬性

組件的屬性要先聲明後使用,props: ['屬性名'...]app

<div id="app">
        <!--組件的使用-->
        <private-component title="組件屬性" :text="mess"></private-component>
    </div>
//組件的定義 Vue.component(組件名稱, {template})
    var vm = new Vue({
        el: '#app',
        data: {
            mess: '-動態屬性'
        }
        components:{
            'private-component': {
                template: '<h1>{{title + text}}</h1>',
                props: ['title', 'text']
            }
        }
    })

最終渲染的效果

<div id="app">
        <h1>組件屬性-動態屬性</h1>
    </div>

組件自定義事件

和組件屬性不同的在於 <組件名 v-bind:屬性名="">,屬性名要在組件中先聲明再使用:props: ['屬性名']
自定義事件:<組件名 v-on:自定義事件名="">,自定義事件名不須要聲明,直接用 $emit() 觸發

<div id="app">
        <p>{{total}}</p>
        <increment-total v-on:count="incrementTotal"></increment-total>
    </div>
var vm = new Vue({
        el: '#app',
        data: {
            total: 0
        },
        methods: {
            incrementTotal: function(){
                this.total += 1;
            }
        },
        components: {
            'incrementTotal': {
                template: '<input type="button" @click="incrementTotal" value="Total" />',
                data: function(){
                    return {
                        total: 0
                    }
                },
                methods: {
                    incrementTotal: function(){
                        this.total += 1;
                        this.$emit('count')
                    }
                }
            }
        }
    })

slot 分發內容

Vue 組件默認是覆蓋渲染,爲了解決這一問題,Vue 提出了 slot 分發內容

<div id="app">
        <component1>
            <h1>Sam</h1>
            <h1>Lucy</h1>
        </component1>
    </div>
Vue.component('component1', {
        template: `
            <div>
                <h1>Tom</h1>
                <slot></slot>
            </div>
        `
    })

最終渲染的效果

<div id="app">
        <component1>
            <h1>Tom</h1>
            <!--
                若是在組件定義的 template 當中沒有 <slot></slot>,那麼下面兩個 h1 標籤將不會存在
                換句話說就是 <slot></slot> = <h1>Sam</h1><h1>Lucy</h1>
                <slot></slot>能夠放到 <h1>Tom</h1> 上面進行位置調換
            -->
            <h1>Sam</h1>
            <h1>Lucy</h1>
        </component1>
    </div>

具名 slot

若是要將組件裏面不一樣的子元素放到不一樣的地方,那就爲子元素加上一個屬性 slot="名稱",而後在組件定義的時候用名稱對應位置 <slot name="名稱"></slot>,其它沒有 slot 屬性的子元素將統一分發到 <slot></slot> 裏面

<div id="app">
        <component1>
            <h1>Sam</h1>
            <h1 slot="lucy">Lucy</h1>
        </component1>
    </div>
Vue.component('component1', {
        template: `
            <div>
                <slot name="lucy"></slot>
                <h1>Tom</h1>
                <slot></slot>
            </div>
        `
    })

最終渲染的效果

<div id="app">
        <component1>
            <!--<slot name="lucy"></slot> = <h1 slot="lucy">Lucy</h1>-->
            <h1>Lucy</h1>
            <h1>Tom</h1>
            <!--其它沒有 slot 屬性的子元素將所有分發到 <slot></slot> 標籤-->
            <h1>Sam</h1>
        </component1>
    </div>

模版寫法

<template id="component1">
        <div>
            <input type="text" v-model="name"/>
            <p>{{name}}</p>            
        </div>
    </template>

    <div id="app">
        <component1/>
    </div>
var vm = new Vue({
        el: '#app',
        components: {
            'component1': {
                template: '#component1',
                data: function(){
                    return {name: 'Tom'};
                }
            }
        }
    })
相關文章
相關標籤/搜索