MVVM 開發總結 —— Vue 元件(你所需要知道的)

源自世界發表於2019-03-04

隨著模組化開發的理念越來越被開發者所重視,如何快速高效的開發專案成為了開發中所要注意的重點。在vue.js中元件系統作為一個重要的概念,它提供的元件可以獨立、重複的使用來構建大型的應用。元件可以擴充套件HTML元素,封裝可重用的HTML程式碼,我們可以將元件看作自定義的HTML元素。

元件的使用步驟:

1.使用 Vue.extend()建立元件構造器
2.使用 Vue.componnet()註冊元件
3.在 Vue的例項作用域範圍內使用元件

vue元件——最簡單的demo例項

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-元件</title>
    <script type="text/javascript" src="http://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <my-component></my-component>
    </div>

    <script>
        // 建立元件構造器
        var myComponent = Vue.extend({
            template: `<div>this is a component!</div>`
        });
        // 全域性註冊元件
        Vue.component(`my-component`, myComponent)

        var vm = new Vue({
            el: `#app`
        })
    </script>
</body>
</html>複製程式碼

這個例子是我們常見的一個元件使用,這是vue1.x中的元件的寫法,vue2.x提出了更加語義化的寫法,但要注意vue.extend()的使用,這裡不做贅述,詳情看下文。
提醒:這裡需要注意,元件註冊需要在Vue例項之前,這裡和自定指令需要注意的事項一致。

元件的全域性註冊和區域性註冊

元件和指令一樣都可以分為全域性的和區域性的。
上面的示例就是一個全域性的元件,在開發中我們可能更多的需要的不是全域性元件,而是區域性元件。元件包含在其他元件內的情況出現的機率比較大,這時我們可以用選項的components物件屬性實現區域性註冊元件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-元件</title>
    <script type="text/javascript" src="http://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <my-component1></my-component1>
        <my-component2></my-component2>
    </div>

    <script>
        var myComponent1 = Vue.extend({
            template: `<div>this is a component1!</div>`
        });

        var myComponent2 = Vue.extend({
            template: `<div>this is a component2!</div>`
        });

        var vm = new Vue({
            el: `#app`,
            components: {
                `myComponent1`: myComponent1,
                `myComponent2`: myComponent2
            }
        })
    </script>
</body>
</html>複製程式碼

這種區域性註冊元件的方式使我們常用的形式之一。

我們也經常見到這樣的元件使用方式,如下圖示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-元件</title>
    <script type="text/javascript" src="http://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <div v-text="parentMsg"></div>
        <!-- 元件1 -->
        <my-component1></my-component1>
        <!-- 元件2 -->
        <my-component2></my-component2>
        <!-- 元件3 -->
        <div id="component"></div>
        <!-- 掛載元件 -->
        <div id="globalComponent"></div>
    </div>

    <script>
        var myComponent1 = {
            template: `<div v-text="child-msg"></div>`,
            props: [`childMsg`],
            data: function(){
                return {
                    msg: `this is a component1!` 
                }
            }
        };

        var myComponent2 = {
            template: `<div v-text="msg"></div>`,
            data: function(){
                return {
                    msg: `this is a component2!`
                }
            }
        };

        var myComponent3 = {
            template: `<div v-text="msg"></div>`,
            data: function(){
                return {
                    msg: `this is a component3!`
                }
            }
        };

        // 全域性元件
        var myGlobalComponent = Vue.component(`my-component1`, myComponent1);

        // 擴充套件例項的構造器元件
        var myCmopnentExtend = Vue.extend(myComponent3);

        // 例項化的構造器元件可以自由的繫結在任意元素按上
        var vc = new myCmopnentExtend().$mount(`#component`);

        // 建立vm 例項,使用區域性元件
        var vm = new Vue({
            el: `#app`,
            data: {
                parentMsg: `haha`
            },
            components: {
                `myComponent2`: myComponent2
            }
        });

        // 掛載元件
        var vb = new myGlobalComponent().$mount(`#globalComponent`);
    </script>
</body>
</html>複製程式碼

這種使用方法vue.js官網提供的方法,vue2.x在中推薦使用的,前者是在vue1.0中推薦的。
但是在這裡我們需要注意的是,vue.extend()這種建立構造器和vue.component()全域性註冊元件,可以通過$mount(`xxx`)繫結到任意指定的元素(在VUE2.0中這種function component,它不是vue的例項,只能進行檢視的渲染而不能進行邏輯操作)。

元件間的通訊

父子元件間的通訊用vue.js開發文件中的介紹就是props down, events up;
非父子元件間的通訊,可以使用一個空Vue例項,來作為中央事件匯流排。

<script>
    var bus = new Vue();
    //     子元件1
    var childOne = {
        name: `childOne`,
        props: [`childMsg`],
        template: `<div v-text="childMsg" @click="commit" class="msg1"></div>`,
        data: function(){
            return {
                msg: `component1`
            }
        },
        methods:{
            commit: function(){
                bus.$emit(`oneToTwo`, {
                    msg: `i am component1`
                });
            }
        },
        mounted(){
            bus.$on(`twoToOne`, (data) => {
                this.msg = data.msg
            })
        }
    };
    //     子元件2
    var childTwo = {
        name: `childTwo`,
        props: [`childMsg`],
        template: `<div v-text="msg" @click="btnClick" class="msg2"></div>`,
        data: function(){
            return {
                msg: `component2`
            }
        },
        mounted(){
            bus.$on(`oneToTwo`, (data) => {
                this.msg = data.msg;
            })
        },
        methods:{
            btnClick: function(){
                this.$emit(`backmsg`);
            }
        }
    };
    // 父組建
    var vm = new Vue({
        el: `#app`,
        data: {
            sTitle:`元件間的通訊`,
            parentMsg:`i am parent component`
        },
        components: {
            `mcOne`: childOne,
            `mcTwo`: childTwo
        },
        methods: {
            strReverse: function(){
                this.parentMsg = this.parentMsg.split(``).reverse().join(``);
            }
        }
    });
</script>複製程式碼

這個小demo包含了3部分父元件,子元件1,子元件2,父元件通過props向子元件1傳遞資訊,子元件1通過空元件bus中央匯流排向子元件2傳遞資訊,子元件2通過event 向父元件傳遞資訊。

在開發中小型應用時這樣的狀態資訊傳遞已經可以滿足大部分專案的要求,但對中大型專案來說,隨著狀態資訊的增多,業務邏輯的複雜,就需要統一的狀態管理模式來保證應用中所有的元件的正確狀態。我們就需要vuex來進行狀態資訊的處理和傳遞了。

vuex本文不做論述。

相關文章