<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                >[success] # 組件通信(三) ~~~ 1.了解'$on'與'$emit' 2.根據Vue.js 1.x 的 '$dispatch' 與 '$broadcast' 兩方法思路偽造一個, 屬于vue.js 2.x 系列同樣的方法.其中 '$dispatch'子傳父或者孫子傳爺爺, '$broadcast' 則相反,但是只會找到最近的觸發 ~~~ >[info] ## 了解 '$on'與'$emit' ~~~ 1.使用 $on(eventName) 監聽事件第二個參數是個方法, 使用 $emit(eventName) 觸發事件第二個參數是傳值, 這兩個方法常見的使用場景就是'bus' 2.要注意 '$on' 監聽需要在 mounted 或 created 鉤子中來監聽。 3.可以參考筆者另一個筆記內容'前端知識 -- 學習整理',這個思路就是設計 模式中的'發布訂閱'模式 ~~~ >[danger] ##### 不是只有bus 才能用 ~~~ 1.$on 監聽了自己觸發的自定義事件 test,因為有時不確定何時會觸發事件, 一般會在 mounted 或 created 鉤子中來監聽。 ~~~ * 自己觸發自己的$emit 和 $on,下面寫法多此一舉建議直接handleEmitEvent觸發alter ~~~ <template> <div> <button @click="handleEmitEvent">觸發自定義事件</button> </div> </template> <script> export default { methods: { handleEmitEvent () { // 在當前組件上觸發自定義事件 test,并傳值 this.$emit('test', 'Hello Vue.js') } }, mounted () { // 監聽自定義事件 test this.$on('test', (text) => { window.alert(text); }); } } </script> ~~~ * 運行效果 ![](https://box.kancloud.cn/e0e510d7ef4262335aca864d09748cc2_649x190.png) >[info] ## 自定義 dispatch 和 broadcast 方法 思路 ~~~ 1.在vue1.x 中'$dispatch' 是子孫組件向父爺組件傳遞,'broadcast '則相反, 但是只會找到最近的觸發 2.兩者都是使用'$on' 觸發 ~~~ >[danger] ##### 定義前看一下vue1.x版本使用 ~~~ 1.在這里 還要強調說明監聽的'$on'要在 mounted 或 created 鉤子中來監聽。 ~~~ * 在子組件定義 ~~~ <!-- 注意:該示例為 Vue.js 1.x 版本 --> <!-- 子組件 --> <template> <button @click="handleDispatch">派發事件</button> </template> <script> export default { methods: { handleDispatch () { this.$dispatch('test', 'Hello, Vue.js'); } } } </script> ~~~ * 在父組件中使用 ~~~ <!-- 父組件,部分代碼省略 --> <template> <child-component></child-component> </template> <script> export default { mounted () { this.$on('test', (text) => { console.log(text); // Hello, Vue.js }); } } </script> ~~~ >[danger] ##### 封裝思路 ~~~ 1.通過上面1.x案例可以看出來,大體上需要兩個參數一個是觸發的事件名字,一個是傳 遞的參數,但是我們自定義的需要使用一個標記參數,來找到我們需要匹配的組件,如何 找這里就利用創建組件的使用name屬性如下圖 ~~~ ![](https://box.kancloud.cn/07b1a1d66d13d37193f498972742ea8a_539x151.png) >[info] ## 正式封裝 ~~~ 1.思路其實就是利用 '$on' 和 '$emit' 配合,通過我們自己寫的這個方法,讓對應 要調用的父組件或者子組件,this指向他本身,這樣形成給其自身加入對應的方法, 但可以有子組件或父組件的傳值 2.首先明確一點'$emit' 和 '$on' 是典型的發布的訂閱模式,'$on'通過訂閱的方式,來接受'$emit' 發布的內容,當然他的發布和訂閱 必須是同一個'this',因此利用vue自帶的'$parent' 和'$children' 從父組件開始找也好,從子組件開始找也好,原理就是層級向上找讓彼此可以發布訂閱在一起 ~~~ 代碼參考[iView](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Fiview%2Fiview%2Fblob%2F2.0%2Fsrc%2Fmixins%2Femitter.js)。 >[danger] ##### 從子組件傳遞給父組件甚至爺爺組件 ~~~ 1.獲取當前組件的'parent',因為剛才構想過,我們需要傳遞三個參數,其中一個參數要匹配 的目標組件名字,因此邏輯就是去找'parent' 和要匹配的名字是否一致,找到符合的'parent' 給這個父組件添加'$emit'事件,在這個父組件中使用'$on' 去觸發 ~~~ ~~~ // 子傳父,孫子傳爺爺或者爸爸 /* * @params:componentName 對應組件名 ,eventName 事件名稱,params 函數參數 * */ dispatch(componentName, eventName, params) { let parent = this.$parent || this.$root; let name = parent.$options.name; console.log(this.$options) console.log(this.$options.name) // 遞歸一層一層找 while (parent && (!name || name !== componentName)) { parent = parent.$parent; // 有父組件名稱 在去找組件name,如果沒有了 就不用特意去找 if (parent) { name = parent.$options.name; } } if (parent) { parent.$emit(parent, [eventName].concat(params)); // parent.$emit(eventName,params); } }, ~~~ >[danger] ##### 從爺爺組件給孫子組件,父傳子 ~~~ 1.思路就找每一個children,找到是否 有和名字匹配的并且綁上$emit()事件 ~~~ ~~~ function broadcast(componentName, eventName, params) { this.$children.forEach(child => { const name = child.$options.name; if (name === componentName) { child.$emit.apply(child, [eventName].concat(params)); } else { broadcast.apply(child, [componentName, eventName].concat([params])); } }); } ~~~ >[danger] ##### 將所有代碼放到mixins進行存儲使用(最后的封裝) ~~~ function broadcast(componentName, eventName, params) { // 當前的this 指向是在methods broadcast 中被改變了 // 因此現在的this 是每一個組件的this this.$children.forEach(child => { const name = child.$options.name; if (name === componentName) { child.$emit.apply(child, [eventName].concat(params)); } else { // 遞歸 更改新的this,獲取新的組件中的children,也就是更新成當前父組件的this broadcast.apply(child, [componentName, eventName].concat([params])); } }); } export default { methods: { // 子傳父,孫子傳爺爺或者爸爸 /* * @params:componentName 對應組件名 ,eventName 事件名稱,params 函數參數 * */ dispatch(componentName, eventName, params) { let parent = this.$parent || this.$root; let name = parent.$options.name; console.log(this.$options) console.log(this.$options.name) while (parent && (!name || name !== componentName)) { parent = parent.$parent; // 有父組件名稱 在去找組件name,如果沒有了 就不用特意去找 if (parent) { name = parent.$options.name; } } if (parent) { parent.$emit.apply(parent, [eventName].concat(params)); // parent.$emit(eventName,params); } }, broadcast(componentName, eventName, params) { // 當前this 也就是其中的父組件 有了broadcast方法 broadcast.call(this, componentName, eventName, params); } } }; ~~~ >[danger] ##### 使用 ~~~ 1.要注意'$on' 要放到mounted 或 created 去使用 ~~~ * 父組件 ~~~ <!-- A.vue --> <template> <div> <button @click="handleClick">觸發事件</button> <my-button class="aaa" id="222" index="666"></my-button> </div> </template> <script> import Emitter from '../mixins/emitter.js'; import MyButton from '@/components/MyButton' export default { name: 'componentA', mixins: [ Emitter ], methods: { handleClick () { // 父傳子 this.broadcast('componentB', 'on-message', 'Hello Vue.js'); }, }, created(){ // 子傳父接受 this.$on('test', (val)=>{ console.log(val) }) }, components:{ MyButton } } </script> ~~~ * 子組件 ~~~ <template> <div index="987"> <button @click="clickToPranent">點擊</button> </div> </template> <script> import Emitter from '@/mixins/emitter'; export default { inheritAttrs: false, name: 'componentB', // 使用封裝 mixins: [ Emitter ], created () { // 接收父傳子 this.$on('on-message', this.showMessage); }, methods: { showMessage (text) { console.log(1) window.alert(text); }, clickToPranent(){ // 調用子傳父 this.dispatch('componentA','test','aaa') }, } } </script> <style scoped> </style> ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看