1. 程式人生 > >父子組件2.0

父子組件2.0

類型 code box lan event 報錯 EDA 對象引用 官方

在前面總結過vue1.0中的組件通信,現在根據vue2.0的變化比較一下兩者的不同之處。

首先還是用一個例子回顧一下之前的父子組件通信。

vue1.0

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue</title>
    <script src="vue1.0.js"></script> 
</head>
<body>
     <template id="child"
> <div> <span>我是子組件</span> <input type="button" value="按鈕" @click="change"> <strong>{{msg}}</strong> </div> </template> <div id="box"> 父級: ->{{a}} <br> <
child-com :msg="a"></child-com> </div> <script> new Vue({ el:#box, data:{ a:我是父組件數據 }, components:{ child-com:{ props:[msg], template:
#child, methods:{ change(){ this.msg=被更改了 } } } } }); </script> </body> </html>

技術分享圖片技術分享圖片

在上面的例子中,子組件是可以更改父組件的數據的,甚至可以通過添加sync實現同步修改,但是當我們把上面的js改為vue2.0的時候,會發現程序直接報錯了。

技術分享圖片

這是因為在vue2.0中的prop中提出了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,但是反過來則不行。這樣會防止從子組件意外改變父級組件的狀態,從而導致你的應用的數據流向難以理解。額外的,每次父級組件發生更新時,子組件中所有的 prop 都將會刷新為最新的值。這意味著你不應該在一個子組件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制臺中發出警告。

針對子組件需要更改prop傳過來的值,官方文檔給出了兩種辦法。

本地data

第一種方法是這個prop用來傳遞一個初始值,當子組件希望將這個初始值用作一個本地數據使用時,最好定義一個本地的data屬性並將這個prop用作其初始值。在下面的例子中,我們希望在子組件中使用父組件的數據a,首先在父組件中通過prop將這個數據傳遞到子組件,然後在子組件中定義一個b,這個b的初始值就是a,然後在子組件中對b進行操作。所以,此時只能更改b,並不能同步更改a。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue</title>
    <script src="vue.js"></script> 
</head>
<body>
     <template id="child">
        <div>
            <span>我是子組件</span>
            <input type="button" value="按鈕" @click="change">
            <strong>{{b}}</strong>
        </div>
    </template>
    <div id="box">
        父級: ->{{a}}
        <br>
        <child-com :msg="a"></child-com>
    </div>
    <script>
        new Vue({
                el:#box,
                data:{
                    a:我是父組件數據
                },
                components:{
                    child-com:{
                        props:[msg],
                        data(){
                            return {
                                b:this.msg
                            }
                        },
                        template:#child,
                        methods:{
                            change(){
                                this.b=被更改了
                            }
                        }
                    }
                }
            });
    </script>
</body>
</html>

技術分享圖片技術分享圖片

官方中還提供了一種使用計算屬性的方法。可以直接在官方查看,這裏就不再演示了。

對象引用

除此之外,還有另外一種方法,那就是對象之間的引用,父組件不再是傳遞單一的基本類型數據給子組件,而是使用對象的形式進行傳遞,此時不僅能夠實現子組件數據更改,還能同步更改父組件數據。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue</title>
    <script src="vue.js"></script> 
</head>
<body>
     <template id="child">
        <div>
            <span>我是子組件</span>
            <input type="button" value="按鈕" @click="change">
            <strong>{{msg.a}}</strong>
        </div>
    </template>
    <div id="box">
        父級: ->{{giveData.a}}
        <br>
        <child-com :msg="giveData"></child-com>
    </div>
    <script>
        new Vue({
                el:#box,
                data:{
                    giveData:{
                        a:我是父組件數據
                    }
                },
                components:{
                    child-com:{
                        props:[msg],
                        template:#child,
                        methods:{
                            change(){
                                this.msg.a=被改了;
                            }
                        }
                    }
                }
            });
    </script>
</body>
</html>

技術分享圖片 技術分享圖片

單一事件管理組件通信。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue</title>
    <script src="vue.js"></script> 
</head>
<body>
    <div id="box">
        <com-a></com-a>
        <com-b></com-b>
        <com-c></com-c>
    </div>
    <script>
        //準備一個空的實例對象
        var Event=new Vue();

        var A={
            template:`
                <div>
                    <span>我是A組件</span> -> {{a}}
                    <input type="button" value="把A數據給C" @click="send">
                </div>
            `,
            methods:{
                send(){
                    Event.$emit(a-msg,this.a);
                }
            },
            data(){
                return {
                    a:我是a數據
                }
            }
        };
        var B={
            template:`
                <div>
                    <span>我是B組件</span> -> {{a}}
                    <input type="button" value="把B數據給C" @click="send">
                </div>
            `,
            methods:{
                send(){
                    Event.$emit(b-msg,this.a);
                }
            },
            data(){
                return {
                    a:我是b數據
                }
            }
        };
        var C={
            template:`
                <div>
                    <h3>我是C組件</h3>
                    <span>接收過來的A的數據為: {{a}}</span>
                    <br>
                    <span>接收過來的B的數據為: {{b}}</span>
                </div>
            `,
            data(){
                return {
                    a:‘‘,
                    b:‘‘
                }
            },
            mounted(){
                //接收A組件的數據
                Event.$on(a-msg,function(a){
                    this.a=a;
                }.bind(this));

                //接收B組件的數據
                Event.$on(b-msg,function(a){
                    this.b=a;
                }.bind(this));
            }
        };

        new Vue({
            el:#box,
            components:{
                com-a:A,
                com-b:B,
                com-c:C
            }
        });
    </script>
</body>
</html>

技術分享圖片 技術分享圖片 技術分享圖片

主要包括三個步驟:

  • 準備一個空的實例對象 var Event=new Vue();
  • 發送數據 Event.$emit(事件名稱, 數據)
  • 接收數據 Event.$on(事件名稱,function(data){ }.bind(this));

父子組件2.0