Vue.js-----輕量高效的MVVM框架(十、父子組件通信)


#1、父鏈

html:

<h3>#父鏈</h3>
<div>
    <div>子組件可以用 this.$parent 訪問它的父組件。根實例的后代可以用 this.$root 訪問它。父組件有一個數組 this.$children,包含它所有的子元素。</div>
    <div>
        盡管可以訪問父鏈上任意的實例,不過子組件應當避免直接依賴父組件的數據,盡量顯式地使用 props 傳遞數據。另外,在子組件中修改父組件的狀態是非常糟糕的做法,因為:
        <ul>
            <li>這讓父組件與子組件緊密地耦合;</li>
            <li>只看父組件,很難理解父組件的狀態。因為它可能被任意子組件修改!理想情況下,只有組件自己能修改它的狀態。
            </li>
        </ul>
    </div>
    <div id="dr01">
        <child01></child01>
    </div>
</div>

 

js: dr01作為父代組件,child01作為子代組件,grandson01作為孫代組件

//***************************************************************
//父鏈
//自定義子代組件child01
Vue.component("child01", {
    data: function() {
        return {
            cMsg: "this is child msg!",
            cParentMsg: this.$parent.dr01Msg, //child01的上級信息就是dr01的dr01Msg
            cRootMsg: this.$root.rootMsg, //child01的根信息就是dr01的rootMsg
        }
    },
    template: "<div>cMsg: {{cMsg}}, cParentMsg: {{cParentMsg}}, cRootMsg: {{cRootMsg}}</div>"
        +"<grandson01 :s-parent-msg='cMsg'></grandson01>"
});
//自定義孫代組件grandson01,
Vue.component("grandson01", {
    data: function() {
        return {
            sMsg: "this is grandsonMsg1",
            sRootMsg: this.$root.rootMsg, //grandson01根信息就是dr01的rootMsg
        }
    },
    //grandson01上級信息就是child01的cMsg,
  //在這里使用props屬性,將子代cMsg賦給孫代的“sParentMsg”,示例:在子代模板中:<grandson01 :s-parent-msg='cMsg'></grandson01>
props:["sParentMsg"], template: "<div>sMsg: {{sMsg}}, sParentMsg: {{sParentMsg}}, sRootMsg: {{sRootMsg}}</div>" }) var dr01 = new Vue({ el: "#dr01", data: { dr01Msg: "this is dr01Msg!", rootMsg: "this is rootMsg!", }, });

 結果:

#2、自定義事件

html:

<h3>#自定義事件</h3>
<template id="dr02-temp">
    <input v-model="msg" placeholder="please input your message!" />
    <button @click="notifyAdd(msg)">Dispatche Event</button>
</template>
<div id="dr02">
    <div>
        <span>每個 Vue 實例都是一個事件觸發器:</span>
        <ol>
            <li>使用 $on() 監聽事件;</li>
            <li>使用 $emit() 在它上面觸發事件;</li>
            <li>使用 $dispatch() 派發事件,事件沿着父鏈冒泡;</li>
            <li>使用 $broadcast() 廣播事件,事件向下傳導給所有的后代。</li>
        </ol>
    </div>
    <p>Messages: {{messages|json}}</p>
    <child02></child02>
</div>

js:

//***************************************************************
    //自定義事件
    Vue.component("child02", {
        //定義模板中初始化的值
        data: function() {
            return {
                msg: "hello",
            }
        },
        //指定模板為id為"dr02-temp"標簽
        template: "#dr02-temp",
        methods: {
            //當點擊按鈕時會觸發的事件
            notifyAdd: function(msg) {
                console.log("invoke notifyAdd()");
                if (msg.trim()) {
                    //將事件分發到vm實例中的"addMsg"事件中
                    this.$dispatch("addMsg", msg);
                    this.msg = "";
                }
            }
        }
    });
    var dr02 = new Vue({
        el: "#dr02",
        //初始化messages數組
        data: {
            messages: [],
        },
        events: {
            //分發事件到vm實例中, 在創建實例時 `events` 選項簡單地調用 `$on`
            addMsg: function(msg) {
                console.log("invoke events's addMsg()");
                this.messages.push(msg);
            }
        },
    });

結果:

  

#3、使用v-on綁定自定義事件

html:

<h3>使用v-on綁定自定義事件</h3>
<template id="dr03-temp">
    <input v-model="msg" placeholder="input msg..." />
    <button @click="dispatchMsg(msg)">處理msg</button>
</template>
<div id="dr03">
    <p>Messages: {{messages|json}}</p>
    <child03 v-on:dispatchMsg="addMsg"></child03>
</div>

 

js:

   //***************************************************************
    //使用v-on綁定自定義事件(在這里測試的時候發現,在dispatchMsg方法中依然要寫this.$dispatch,不然只能監聽到dispatchMsg方法,並不能向上冒泡)
    //這里哪兒不對,問題出現在哪里????
    //這里選擇使用局部注冊組件的方式測試。
    var child03 = Vue.extend({
        data: function() {
            return {
                msg: 'hello, child03!',
            }
        },
        template: "#dr03-temp",
        methods: {
            dispatchMsg: function() {
                console.log("invoke dispatchMsg()");
                if (this.msg.trim()) {
            //盡管使用了v-on綁定了自定義事件dispatchMsg到vm實例中的addMsg方法中,但是依然不會向上冒泡,這里事實上是有問題的。
this.$dispatch("addMsg", this.msg); this.msg = ''; } } } }); var dr03 = new Vue({ el: "#dr03", data: { messages: [], }, events: { addMsg: function(msg) { console.log("invoke addMsg() msg: " + msg); this.messages.push(msg); } }, components: { "child03": child03, } });

 

結果與上面類似,只是多了控制台的輸出

  

#子組件索引

html:

<h3>子組件索引</h3>
<div id="dr04">
    <div>
        盡管有 props 和 events,但是有時仍然需要在 JavaScript 中直接訪問子組件。為此可以使用 v-ref 為子組件指定一個索引 ID。
    </div>
    <child03 v-ref:c03></child03>
    <child04 v-ref:c04></child04>
</div>

 js:

//***************************************************************
//字組件索引
Vue.component("child03", {
    template: "<div>this is child03</div>"
});
Vue.component("child04", {
    template: "<div>this is child04</div>"
});
var dr04 = new Vue({
    el: "#dr04"
});
var child03 = dr04.$refs.c03;
var child04 = dr04.$refs.c04;
console.log("child03.$el: ");
console.log(child03.$el);
console.log("child04.$el: ");
console.log(child04.$el);

 

結果展示:

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM