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

父子元件2.0

在前面總結過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));