意思是:避免修改prop值,因為父組件一旦re-render,這個值就會被覆蓋;
另外,盡管在這個按鈕上實現(xiàn)了顯示狀態(tài)的切換,但是點擊其他區(qū)域的時候,并不會隱藏它,原因是:子組件prop值的變化并沒有影響到父組件,因此showCancel的值一直保持初始值沒有變化,而只有在這個值被更新時才會觸發(fā)子組件中相關(guān)值的更新。
——好吧,那么老老實實的用一個計算屬性接收showCancel值,這樣實現(xiàn)點擊子組件控制系統(tǒng)菜單的狀態(tài)切換;
獲得了計算屬性ifShowCancel,組件相應的變成了v-show="ifShowCancel",我試圖在綁定事件里通過this.ifShowCancel=!this.ifShowCancel切換菜單狀態(tài),報錯,得到報錯信息:Computed property "ifShowCancel" was assigned to but it has no setter;
明白了,要以直接賦值的形式改變計算屬性ifShowCancel的值,需要一個setter函數(shù),但是setter函數(shù)中無法修改prop值,因此在getter中也就無法通過return this.showCancel來更新這個計算屬性,所以這個方法貌似也行不通;
到此為止,好像路都成了堵死狀態(tài):prop值不能改->要用計算屬性;計算屬性不能改->需要setter;而寫入了getter、setter,計算屬性的值依賴于prop值->prop值不能改。——一個堪稱完美的閉環(huán)誕生了!
走投無路之際我想起了$emit和$on這一對。
3. 父子互相通信
前邊的prop實現(xiàn)了從父到子的單向通信,而通過$emit和$on,就可以實現(xiàn)從子組件到父組件的通信:這不能直接修改父組件的屬性,但卻可以觸發(fā)父組件的指定綁定事件,并將一個值傳入父組件。
在這一步我摒棄了點擊按鈕時的去操作子組件內(nèi)屬性的想法,既然計算屬性ifShowCancel依賴于prop值,那么就在點擊按鈕時,通過$emit觸發(fā)父組件的事件,并將需要修改的屬性值傳入父組件,于是:
/*父組件自定義元素綁定switch-show事件*/ <t-header :showCancel=showCancel @switch-show="switchShow"></t-header> // 父組件js methods: { //會被子組件$emit觸發(fā)的方法 switchShow(val) { this.showCancel = val; } } // 子組件js methods: { //按鈕上的綁定click事件 switchCancelBoard() { this.$emit("switch-show", this.ifShowCancel); } }
這樣處理流程就變成了:點擊按鈕->作為計算屬性的ifShowCancel值傳入父組件并觸發(fā)父組件事件,對showCancel賦值->父組件屬性更新->觸發(fā)子組件prop更新->觸發(fā)重新compute,更新ifShowCancel值->v-show起作用。
另外在點擊其他區(qū)域時,通過父組件綁定的click事件,就可以重置showCancel值,進而隱藏掉出現(xiàn)的系統(tǒng)菜單。
下邊放出這個功能的完整代碼。
4. 完整代碼
/*父組件*/ <template> <p id="app" @click="hideCancel"> <t-header :showCancel=showCancel @switch-show="switchShow"></t-header> <!-- <router-view/> --> </p> </template> <script> import THeader from "./components/t-header/t-header"; export default { name: "app", components: { THeader }, data() { return { showCancel: false }; }, methods: { hideCancel() { this.showCancel = false; }, switchShow(val) { this.showCancel = val; } } }; </script> <style scope lang="stylus"> </style> /*子組件*/ <template> <p class="header-wrapper"> <p class="title-wrapper"> <p class="logo"></p> <h2 class="title">Title</h2> </p> <p class="info-wrapper"> <span class="username">你好,管理員!</span> <span class="cancel" @click.stop="switchCancelBoard"> <p class="cancel-p" v-show="ifShowCancel"> <ul> <li @click.stop="doSomething" title="用戶設置">設置 </li> <li @click.stop="doSomething" title="退出登錄">退出 </li> </ul> </p> </span> </p> </p> </template> <script> export default { props: { showCancel: { type: Boolean } }, methods: { doSomething() {}, switchCancelBoard() { // this.ifShowCancel = !this.showCancel; this.$emit("switch-show", !this.ifShowCancel); } }, computed: { ifShowCancel() { return this.showCancel; } } }; </script> <style lang="stylus" rel="stylesheet/stylus" scoped> .header-wrapper background: #1C60D1 color: #fff width: 100% height: 50px line-height: 50px position: fixed top: 0px left: 0px font-size: 0 .title-wrapper display: block position: relative float: left height: 50px .logo display: inline-block background-image: url('./logo.png') background-size: 30px 30px background-repeat: no-repeat width: 30px height: 30px margin-top: 10px .title display: inline-block font-size: 16px height: 50px line-height: 50px margin: 0px auto 0px 16px font-weight: normal vertical-align: top .info-wrapper display: block position: relative float: right height: 50px width: 160px font-size: 0 .username display: inline-block height: 50px line-height: 50px font-size: 14px vertical-align: top .cancel display: inline-block vertical-align: middle background-image: url('./cancel.png') background-size: 32px 32px cursor: pointer background-repeat: no-repeat width: 32px height: 32px .cancel-p position: absolute display: block width: 60px height: 80px background: #fff z-index: 50 top: 40px right: 16px font-size: 14px color: #646464 box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.4) ul padding-left: 0px margin: 0px li width: 100% height: 40px line-height: 40px text-align: center list-style-type: none &:hover background-color: #eaeaea </style>
相信看了本文案例你已經(jīng)掌握了方法,更多精彩請關(guān)注Gxl網(wǎng)其它相關(guān)文章!
推薦閱讀:
JS做出哈希表功能
vue地區(qū)選擇組件使用步驟詳解
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com