1. 程式人生 > >Vue元件之單向資料流

Vue元件之單向資料流

子元件能夠通過自身的props選項獲取父元件上的資料,但是在預設情況下,props是單向繫結的---當父元件資料(屬性)發生變化的時候會傳遞給子元件,引起子元件的變化,但不能反過來並且不允許子元件直接改變父元件的資料,會報錯的。例如:

也就是說當通過一種方法改變父元件資料的時候,子元件與之相關聯的props資料也會發生改變,從而影響子元件,但是子元件直接改變從父元件拿過來的props資料卻不能影響父元件的原始資料。也就是說一般情況下只能是“父影響子,而不是子影響父”。

兩種情況:

1.如果子元件想將從父元件獲得的資料作為區域性資料來使用,可以將其給儲存到子元件的區域性變數data中(子元件中的變數),不影響父元件的資料;例如:

data:function(){
                                return {
                                    weather:{
                                        tempre:"22.3℃",
                                        weth:"rain",
                                        wind:this.ser
                                    }
                                }
                            },
這裡的this.sers就是來源於子元件的props資料。

2.如果子元件想修改資料並且同步更新到父元件,兩種解決方式

第一種:使用.sync加上顯式觸發的一個事件this.$emit("update:你要更改的props資料", 改變後的值),也就是在一個事件觸發的函式中通過this.$emit("update:你要更改的props資料", 改變後的值)來改變資料;例如:

HTML部分

 <div id= "container" v-cloak>
        <my-compon></my-compon>
    </div>
    <!-- 父元件模板 -->
    <template id="myComp">
        <div>
            <h3>大家好,我是{{animal.name}}貓,我已經和Jerry鬥爭了{{animal.age}}年了</h3>
		給繫結的資料使用.sync修飾符
            <my-comp-son v-bind:animalage.sync="animal.age"></my-comp-son>
        </div>
    </template>
    <!-- 子元件模板 -->
    <template id="myCompSon">
        <div>
            <h4>一隻皮毛是{{dog.hair}}色,身高是{{dog.height}}的狗狗,在散步。。。</h4>
            <h3>今天的天氣:{{weather.weth}},風力{{weather.wind}},溫度{{weather.tempre}},{{animalname}},{{animalage}}</h3>
            <button @click = "changeFatDaAge">點選父元件中的資料會跟著改變方式一</button>  
        </div> 
    </template>
JS部分
var app = new Vue({
            el:"#container",
            data:{
                house:{
                    date:"2017-10-10",
                    area:"144m²",
                    floor:6,
                },
                carBrand:"Benzi"
            },
            components:{
                "my-compon":{//父元件
                    template:"#myComp",
                    data:function(){
                        return {
                            animal:{
                                name:"Tom",
                                age:3,
                                skin:"black"
                            },
                            shoe:"鴻星爾克",
                            dog:{
                                hair:"brown",
                                height:1.25
                            }
                        }
                    },
                    methods: {
                        changeData:function () {//這裡的this指的是當前父元件的例項
                            this.animal.name = "Kitty"//改變父元件中的資料
                        }
                    },
                    components:{
                        "my-comp-son":{//子元件
                            template:"#myCompSon",
                            props:["animalname","animalage","dog"],//地位和data一樣,獲取方式也是一樣
                            data:function(){
                                return {
                                    weather:{
                                        tempre:"22.3℃",
                                        weth:"rain",
                                        wind:"3級"
                                    }
                                }
                            },
                            methods:{
                                // 給v-bind使用修飾符.sync,需要顯式地觸發一個更新事件(this.$emit("update:你要更改的props資料", 改變後的值))
                                changeFatDaAge:function(){
                                    // this.animalage = 19;
                                    this.$emit("update:animalage", 19)//通過這個方法來改變子元件props資料,並引起父元件相應資料的改變
                                }
                            }
                        }
                    }
                }
            }
        })
當點選按鈕的時候父元件上的原始資料也會發生改變,不過這種方式不常用,寫法也太麻煩,不建議使用;

      第二種:將父元件的資料包裝成物件並繫結到子元件上,在子元件中修改物件的屬性(其實並沒有真正改變該物件,因為物件是引用型別的資料,雖然屬性發生了變化,但指標並沒有發生變化),常用。例如:

HTML部分:

<div id= "container" v-cloak>
        <my-compon></my-compon>
    </div>
    <!-- 父元件模板 -->
    <template id="myComp">
        <div>
            <h4>一隻皮毛是{{dog.hair}}色,身高是{{dog.height}}的狗狗,在散步。。。</h4>
            <!-- 將父元件的資料包裝成物件並繫結到子元件上,在子元件中修改物件的屬性,在這是dog -->
            <my-comp-son :dog = "dog"></my-comp-son>
        </div>
    </template>
    <!-- 子元件模板 -->
    <template id="myCompSon">
        <div>
            <h4>一隻皮毛是{{dog.hair}}色,身高是{{dog.height}}的狗狗,在散步。。。</h4>
            <button @click="changeFondata">點選父元件中的資料會跟著改變方式二</button>
        </div> 
    </template>
JS部分

var app = new Vue({
            el:"#container",
            data:{
                house:{
                    date:"2017-10-10",
                    area:"144m²",
                    floor:6,
                },
                carBrand:"Benzi"
            },
            components:{
                "my-compon":{//父元件
                    template:"#myComp",
                    data:function(){
                        return {
                            animal:{
                                name:"Tom",
                                age:3,
                                skin:"black"
                            },
                            shoe:"鴻星爾克",
                            dog:{
                                hair:"brown",
                                height:1.25
                            }
                        }
                    },
                    methods: {
                        changeData:function () {//這裡的this指的是當前父元件的例項
                            this.animal.name = "Kitty"//改變父元件中的資料
                        }
                    },
                    components:{
                        "my-comp-son":{//子元件
                            template:"#myCompSon",
                            props:["animalname","animalage","dog"],//地位和data一樣,獲取方式也是一樣
                            data:function(){
                                return {
                                    weather:{
                                        tempre:"22.3℃",
                                        weth:"rain",
                                        wind:"3級"
                                    }
                                }
                            },
                            methods:{
                                //在子元件中修改物件的屬性
                                changeFondata:function(){
                                    this.dog.hair = "紅"
                                }
                            }
                        }
                    }
                }
            }
        })