1. 程式人生 > >Vue元件--父子元件以及元件間的互相通訊

Vue元件--父子元件以及元件間的互相通訊

父子元件

在一個元件內定義另一個元件,稱之為父子元件。

但是要注意的是:1.子元件只能在父元件內部使用(寫在父元件tempalte中);

    2.預設情況下,子元件無法訪問父元件上的資料,每個元件例項的作用域是獨立的;

例如:

JS部分

var compo1 = new Vue({
                el:"#container1",
                data:{
                    goods:"洗衣液",
                    car:"Benzi"
                },
                components:{
                    "your-compo":{//父元件,在這裡"your-compo"只是元件id
                        template:"#aps",
                        data:function(){
                            return {
                                food:"麵條"
                            }
                        },
                        components:{
                            "yourson-compo":{//子元件,同上
                                template:"#apsSon",
                                data:function(){
                                    //some codes
                                }
                            }
                        }
                    }
                }
            })

HTMl部分

<div id="container1">
         <your-compo></your-compo>//父元件
    </div>
    <!-- 父元件模板 -->
    <template id="aps">
        <div>
            <h3>{{food}}</h3>
            <yourson-compo></yourson-compo>//在父元件中嵌入子元件
        </div>
    </template>
    <!-- 子元件模板 -->
    <template id="apsSon">
        <div>
            <h1>我是模擬出來的第二個子元件</h1>
        </div>
    </template>
子元件只能在父元件內部使用,這裡的內部指的是父元件模板template內部,也就是說要寫在父元件template中, 預設情況下,元件之間的作用域是獨立的。
元件間的資料通訊:

但是即便是這樣,元件之間還是要實現通訊的,那麼父子元件間是怎麼通訊的呢?Vue有著自己的一套解決方案:

1.子元件訪問父元件的資料

a)將父元件的資料通過v-bind繫結到子元件的自定義屬性上;
        b)在子元件內部,通過props選項宣告你要接收的資料,也就是接收來自父元件上的資料(props選項可以是物件或者陣列);
                   i:如果props選項是陣列,裡面就是由那些自定義屬性組成的字串陣列;
                   ii:如果props選項是物件,那麼此時可以配置高階的設定,如型別判斷,資料校驗,設定預設值,是否必傳等,具體見官網上的例子所示;

JS部分

var app = new Vue({ //根元件
                el: "#container",
                data: {
                    name: "張三"
                },
                components: {
                    "my-comp": { //父元件
                        template: "#fatherComp",
                        data: function() {
                            return {
                                greeting: "我是父元件my-comp",
                                user: {
                                    id: "9527",
                                    name: "唐伯虎"
                                },
                                car: "Benzi",
                                animal: "",
                                plant: ""
                            }
                        },
                        components: {
                            "my-compson": { //子元件一
                                template: "#sonComp",
                                data: function() {
                                    return {
                                        animal: {
                                            classes: "Dog",
                                            height: 120
                                        },
                                        plant: "玫瑰花"
                                    }
                                },
                                props: ["greeting", "user", "car"] //子元件通過props來接收資料,props可以是陣列,也可以是物件
                            }
                        }
                    }
                }
            })

如果這裡的props是個物件,那麼就如下這樣

"my-compson1": {
                                template: "#sonComp1",
                                props: { //props也可以是物件
                                    greeting: Number, //規定greeting必須是數值型別,
                                    user: {
                                        type: Object, //
                                        default: function() { //物件或者陣列的預設值必須使用函式的形式來返回,
                                            return {
                                                id: "9900",
                                                name: "如花"
                                            }
                                        }
                                    },
                                    car: {
                                        type: String,
                                        default: "BMW", //當沒有傳,但卻必須要使用自定義屬性car的時候,顯示default值
                                        required: true //在元件的自定義屬性中必傳car屬性,由於此時沒有傳,所以顯示預設值
                                    }
                                }
                            }
HTML部分

 <div id="container" v-cloak>
        <my-comp></my-comp>
    </div>
    <div id></div>
    <!-- 父元件引用模板 -->
    <template id="fatherComp">
        <div>
            <h3>{{greeting}}</h3>
            <h3>{{user.id}}{{user.name}}</h3>
            <hr>
            <!-- 父元件通過v-bind將資料繫結到子元件 -->
            <my-compson :greeting="greeting" :user = "user" :car = "car" @sondata ="getData"></my-compson>
        </div>
    </template>
    <!-- 子元件一引用模板 -->
    <template id="sonComp">
        <div>
            <h5>{{greeting}},{{user.id}},{{user.name}},{{car}}</h5>
            <!-- 子元件自帶的資料 -->
            <h1>{{animal.height}}</h1>
           
        </div>
    </template>

 總結:父元件向子元件傳遞資料是通過v-bind將父元件資料繫結到子元件上,子元件內部通過props選項來接收資料
注:元件的資料來源data,props,計算屬性

2.父元件訪問子元件中的資料

a)在子元件中使用vm.$emit("自定義事件名","子元件資料一","子元件資料二",...)方法(在這裡vm指的是當前子元件本身),來扔出一個自定義事件和資料,事件名自定義;
b)在父元件中使用(寫有)子元件的地方偵聽子元件扔出來的事件名(一旦偵聽到,就會觸發相應的函式),並在父元件中定義一個函式用來獲取並儲存資料;例如:

JS部分

var app = new Vue({ //根元件
                el: "#container",
                data: {
                    name: "張三"
                },
                components: {
                    "my-comp": { //父元件
                        template: "#fatherComp",
                        data: function() {
                            return {
                                greeting: "我是父元件my-comp",
                                user: {
                                    id: "9527",
                                    name: "唐伯虎"
                                },
                                car: "Benzi",
                                animal: "",
                                plant: ""
                            }
                        },
                        methods: { //在父元件中定義一個函式用來儲存子元件傳送過來的資料
                            getData: function(ele1, ele2) {
                                this.animal = ele1; //第一個引數就代表傳遞過來的第一個子元件資料
                                this.plant = ele2 //同理,以此類推
                            }
                        },
                        components: {
                            "my-compson": { //子元件一
                                template: "#sonComp",
                                data: function() {
                                    return {
                                        animal: {
                                            classes: "Dog",
                                            height: 120
                                        },
                                        plant: "玫瑰花"
                                    }
                                },
                                methods: {
                                    emitData: function() {
                                        //這裡的this指的是當前子元件例項
                                        this.$emit("sondata", this.animal, this.plant) //扔出一個自定義事件sondata和子元件的資料,多個數據用","號隔開
                                    }
                                }
                            }
                        }
                    }
                }
            })
HTML部分

    <div id="container" v-cloak>
        <my-comp></my-comp>
    </div>
    <div id></div>
    <!-- 父元件引用模板 -->
    <template id="fatherComp">
        <div>
            <!-- 剛開始animal和plant都是空值,當點選子元件的按鈕的時候就會拿到子元件上的資料並進行展示-->
            <h1>{{animal}},{{plant}}</h1>
            <hr>
            <!-- 父元件在使用子元件的地方偵聽子元件扔出來的事件名,這裡是sondata,並執行了儲存資料的函式 -->
            <my-compson :greeting="greeting" :user = "user" :car = "car" @sondata ="getData"></my-compson>
        </div>
    </template>
    <!-- 子元件一引用模板 -->
    <template id="sonComp">
        <div>
            <h5>{{greeting}},{{user.id}},{{user.name}},{{car}}</h5>
            <!-- 子元件自帶的資料 -->
            <h1>{{animal.height}}</h1>
            <button type="button" @click = "emitData">扔出來一個自定義事件和子元件的資料</button>
        </div>
    </template>
總結:子元件通過一個事件(如click等)給父元件傳送訊息:"我扔出來一個自定義事件和一些資料",父元件偵聽到自定義事件,並執行在該自定義事件下的函式來接收並儲存資料