Vue中組件開發

本文講解vue中的組件開發

 

先上代碼:

1.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <span :style='{"font-size":fontSize+"px"}'>{{startMsg}}</span>
        <br> 請輸入組件描述:
        <input type="text" v-model='inputDes'>
        <!-- 父組件要接受值,就要監聽子組件規定的事件,要獲取到參數值,使用規定的$event -->
        <btn-counter :des='inputDes' @add-size='addSize($event)'></btn-counter>
        <br>
        <!-- 兄弟組件之間傳值:使用事件中心,$on(監聽事件),$off(銷燬事件),$emit(觸發事件),mounted(模板已加載完畢準備就緒) -->
        <lingbug-tom des='我是tom,點我可以給jerry增加'></lingbug-tom>
        <br>
        <lingbug-jerry des='我是jerry,點我可以給tom增加'></lingbug-jerry>
        <br>
        <button @click='destroyEventHub'>銷燬兄弟間傳值事件</button>
        <!-- 父組件向子組件傳值:插槽slot(一般用戶固定文本,但是一些內容需要父組件動態傳遞,如:異常信息) -->
        <error-box>自定義異常信息</error-box>
        <error-box>用戶名已存在</error-box>
        <error-box></error-box>

        <!-- 具名插槽:可以有多個插槽,通過name來指定 -->
        <error-box-detail>
            <h1 slot='title'>異常標題:要註冊的用戶名已存在</h1>
            <p>異常詳情:用戶名lingbug已存在,請修改後重試!</p>
            <h3 slot='remark'>建議修改爲ling-bug or lingbug1</h3>
        </error-box-detail>
        <!-- 如果內容比較多,可以使用template包裹起來 -->
        <error-box-detail>
            <template slot='title'>
                <p>異常標題:</p>
                <p>要註冊的用戶名已存在</p>
                <p>用戶名:lingbug</p>
            </template>
            <template>
                <p>異常詳情:</p>
                <p>用戶名lingbug已存在,請修改後重試!</p>
            </template>
            <template slot='remark'>
                <p>修復建議:</p>
                <p>ling-bug or lingbug1</p>
            </template>
        </error-box-detail>

        <!-- 作用域插槽:子組件可以將數據傳遞給父組件讓父組件進行處理 -->

        <user-list :list='userList'>
            <!-- 使用規定的slot-scope來獲取子組件的插槽數據 -->
            <!-- 注意:vue版本低於2.6無法使用作用域插槽 -->
            <template slot-scope="slotProps">
                <span v-if='slotProps.info.age >= 18' style="color: orange;">姓名:{{slotProps.info.name}},性別:{{slotProps.info.sex}},年齡:{{slotProps.info.age}}</span>
                <span v-else>姓名:{{slotProps.info.name}},性別:{{slotProps.info.sex}},年齡:{{slotProps.info.age}}</span>
            </template>
        </user-list>
    </div>

</body>

</html>
<!-- <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> -->
<script src="./vue-2.6.11.min.js"></script>
<script src="./index.js"></script>

 

2.js

// 註冊全局組件
Vue.component('btn-counter', {
    props: ['des'],
    data: function() {
        return {
            clickCount: 0,
            fontSize: 10
        };
    },
    // 這個template的語法是ES6的語法
    template: `
    <div>
        <span>組件描述:{{des}}</span>
        <button @click="selfclick">我被點擊了{{clickCount}}下</button>
        <button @click='$emit("add-size",fontSize)'>增大字體</button>
    </div>
    `, //子組件向父組件傳值,使用規定好的$emit(事件名,參數)
    methods: {
        selfclick: function() {
            this.clickCount += 2;
        }
    }
});

// 初始化一個vue實例作爲事件中心
var eventHub = new Vue();

// 兄弟組件之間傳值:使用事件中心,$on(監聽事件),$off(銷燬事件),$emit(觸發事件),mounted(模板已加載完畢準備就緒)
Vue.component('lingbug-tom', {
    props: ['des'],
    template: `
    <div>
        <span>{{des}}</span>
        <button @click='addCount'>{{count}}</button>
    </div>
    `,
    data: function() {
        return {
            count: 0
        };
    },
    methods: {
        addCount: function() {
            eventHub.$emit('add-jerry', 2);
        }
    },
    mounted: function() {
        eventHub.$on('add-tom', r => this.count += r);
    }
});
Vue.component('lingbug-jerry', {
    props: ['des'],
    template: `
    <div>
        <span>{{des}}</span>
        <button @click='addCount'>{{count}}</button>
    </div>
    `,
    data: function() {
        return {
            count: 0
        };
    },
    methods: {
        addCount: function() {
            eventHub.$emit('add-tom', 1)
        }
    },
    mounted: function() {
        eventHub.$on('add-jerry', r => this.count += r);
    }
});

// 父組件向子組件傳值:插槽slot(一般用戶固定文本,但是一些內容需要父組件動態傳遞,如:異常信息)
Vue.component('error-box', {
    template: `
    <div>
        <span>程序有異常發生,Error:</span>
        <slot>沒有異常</slot>
    </div>
    ` //如果父組件不傳遞內容,可以使用slot裏面的默認內容
});

// 具名插槽:可以有多個插槽,通過name來指定
Vue.component('error-box-detail', {
    template: `
    <div>
            <header>
                <slot name='title'></slot>
            </header>
            <main>
                <slot></slot>
            </main>
            <footer>
                <slot name='remark'></slot>
            </footer>
        </div>
    `
});

// 作用域插槽:子組件可以將數據傳遞給父組件讓父組件進行處理
Vue.component('user-list', {
    props: ['list'],
    // 插槽:將數據綁定到slot上,這樣父組件中就可以獲取到數據
    // 注意:vue版本低於2.6無法使用作用域插槽
    template: `
    <div>
            <ul>
                <li :key='user.id' v-for='(user,index) in list'>
                    <slot :info='user'>
                        {{index}}.姓名:{{user.name}},性別:{{user.sex}},年齡:{{user.age}}
                    </slot>
                </li>
            </ul>
        </div>
    `
});

var vm = new Vue({
    el: '#app',
    data: {
        startMsg: 'Hello World~',
        inputDes: '',
        fontSize: 5,
        userList: [{
                id: 1,
                name: '張三',
                sex: '男',
                age: 20
            },
            {
                id: 2,
                name: '李四',
                sex: '女',
                age: 12
            },
            {
                id: 3,
                name: '王五',
                sex: '男',
                age: 15
            }
        ]
    },
    methods: {
        addSize: function(value) {
            this.fontSize += value;
        },
        destroyEventHub: function() {
            eventHub.$off('add-tom');
            eventHub.$off('add-jerry');
            alert('銷燬完成!');
        }
    }
});

 

總結:
一、vue組件:Vue.component(組件名稱,{});  *注意:在vue中儘量不要使用大寫字母,也就是不要使用駝峯命名,儘量使用-分開,否則導致不必要的錯誤*
    1.第二個參數option的屬性:
        a.template:模板(ES6中可以使用``來使模板代碼可讀性更好)
        b.data:數據(使用方法,返回一個對象)
        c.methods:組件的方法
        d.props:組件的屬性,外部可以傳入
        e.mounted:方法(在組件模板準備就緒時調用)

二、子組件傳值給父組件:
    1.在子組件中定義事件:使用$emit(事件名,參數)
    2.父組件監聽子組件定義的事件:v-on:事件名 或者 :事件名
    3.要想獲取到參數,使用$event  :事件名($event)

三、兄弟組件之間傳值:使用事件中心
    1.實例化一個vue對象作爲事件中心:var eventHub = new Vue();
    2.在組件模板準備就緒時(mounted)將事件註冊到事件中心($on):eventHub.$on('事件名, 邏輯);
    3.在自己的方法中調用兄弟組件註冊的事件($emit):eventHub.$emit(兄弟組件的事件名, 要傳遞的參數);
    4.銷燬註冊的事件($off):eventHub.$off(事件名);

四、插槽(slot):
    1.在組件中定義插槽slot:
        a.<slot>默認值</slot>
        b.多個插槽使用name來區分:      <header>
                                    <slot name='title'></slot>
                                </header>
                                <main>
                                    <slot></slot>
                                </main>
                                <footer>
                                    <slot name='remark'></slot>
                                </footer>
    2.父組件使用子組件時,填寫數據到插槽中:
        a.<error-box>自定義異常信息</error-box>
        b.如果爲空則使用子組件的插槽默認值:<error-box></error-box>
        c.多個插槽使用slot = name來區分:<h1 slot='title'>異常標題:要註冊的用戶名已存在</h1>
                                   <p>異常詳情:用戶名lingbug已存在,請修改後重試!</p>
                                   <h3 slot='remark'>建議修改爲ling-bug or lingbug1</h3>
        d.內容比較多,可以使用template:         <error-box-detail>
                                    <template slot='title'>
                                        <p>異常標題:</p>
                                        <p>要註冊的用戶名已存在</p>
                                        <p>用戶名:lingbug</p>
                                    </template>
                                    <template>
                                        <p>異常詳情:</p>
                                        <p>用戶名lingbug已存在,請修改後重試!</p>
                                    </template>
                                    <template slot='remark'>
                                        <p>修復建議:</p>
                                        <p>ling-bug or lingbug1</p>
                                    </template>
                                </error-box-detail>
    3.作用域插槽(子組件將數據傳遞給父組件,由父組件來進行一些邏輯處理):注意:只有在2.6版本以上vue纔可以使用
        1.定義子組件數據,使用slot和v-bind來指定父組件可操作的數據:
            <ul>
                        <li :key='user.id' v-for='(user,index) in list'>
                            <slot :info='user'>
                                {{index}}.姓名:{{user.name}},性別:{{user.sex}},年齡:{{user.age}}
                            </slot>
                        </li>
                    </ul>
        2.父組件中使用template和slot-scope來獲取到子組件的數據:
            <template slot-scope="slotProps">
                        <span v-if='slotProps.info.age >= 18'>成年人</span>
                        <span v-else>未成年</span>
                    </template>
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章