鍍金池/ 問答/HTML/ vue 父子間通訊問題 子組件可以改變父組件的狀態(tài),父組件可以改變子組件

vue 父子間通訊問題 子組件可以改變父組件的狀態(tài),父組件可以改變子組件狀態(tài),但是卻改變不了自己本身的狀態(tài)。

rantings.vue

<template>
   <div class="rating">
       <ul class="list">
           <li @click='rate(star)' v-for="star in maxStars" :class="{ 'active': star <= stars }" class="star">
           <icon :name="star <= stars ? 'star' : 'star-o'"/>
           </li>
       </ul>
       <span v-show="hasCounter">{{ counter }}</span>
       <button @click='chang'></button>
   </div>
 </template>

<script>
   import 'vue-awesome/icons/star'
   import 'vue-awesome/icons/star-o'
   import Icon from 'vue-awesome/components/Icon'
   export default {
       components: {
           Icon
       },
       props: {
           stars: {
               type: Number,
               required: true
           },
           maxStars: {
               type: Number,
               default: 5
           },
           hasCounter: {
               type: Boolean,
               default: true
           }
       },
       data() {
           return {
               has: this.hasCounter
           }
       },
       computed: {
           counter() {
               return `${this.stars} of ${this.maxStars}`
           }
       },
       methods: {
           chang() {
               this.has = !this.has;
               // this.$emit(this.has)
           },
           rate(star) {
               this.stars = this.stars === star ? star - 1 : star;
           }
       },
       watch: {
           // result(val) {
           //     this.has = val;
           // },
           has(val) {
               console.log(val)
               this.$emit("on-result-change", val);
           }
       }
   }
</script>
<style scoped>
   .rating {
       font-family: 'Avenir', Helvetica, Arial, sans-serif;
       font-size: 14px;
       color: #a7a8a8;
   }
   
   .list {
       margin: 0 0 5px 0;
       padding: 0;
       list-style-type: none;
   }
   
   .list:hover .star {
       color: #f3d23e;
   }
   
   .star {
       display: inline-block;
       cursor: pointer;
   }
   
   .star:hover~.star:not(.active) {
       color: inherit;
   }
   
   .active {
       color: #f3d23e;
   }
   
   button {
       width: 100px;
       height: 100px;
   }
</style>

這是子組件的代碼

order.vue 這是父組件

<template>
<div class="order">
    <ranting :stars='rade' :maxStars='maxd' :hasCounter="has" @on-result-change='onResultChange'/> 
    <div class="hha" @click="change">dasd</div>
</div>
</template>

<script>
    import ranting from './rantings.vue'
    export default {
        components: {
            ranting
            // }
        },
        data() {
            return {
                rade: 4,
                maxd: 6,
                has: true
            }
        },
        methods: {
            change() {
                this.has = !this.has;
            },
            onResultChange(val) {

                this.has = val; //④外層調用組件方注冊變更方法,將組件內的數(shù)據(jù)變更,同步到組件外的數(shù)據(jù)狀態(tài)中

            }
        },
    }
</script>

<style>

問題:
我想做雙向數(shù)據(jù)綁定的方式來控制,span 的顯隱性

通過點擊子組件的button 可以雙向的控制has 和hasCounter 的值

clipboard.png

但是當點擊父組件的<div class="hha" @click="change">dasd</div>的時候雖然可以改變子組件中的hasCounter但是本身的has 并沒有改變,

第一次點擊:

clipboard.png

第二次點擊:

clipboard.png

所以這就導致了當has 和hasCounter的值不一樣的時候,點擊button 必須點擊兩次才能使span的顯隱性得到控制,并且has的值和hasCounter的值保持一致。

回答
編輯回答
喜歡你

// 父組件
<ranting :stars='rade' :maxStars='maxd' :hasCounter.sync="has" />

// 子組件

computed: {
has() {

   return this.hasCounter

}
}

chang() {
this.$emit('update:hasCounter', !this.hasCounter);
}

然后子組件的 watch 監(jiān)聽可以移除了 data 中的 has 也可以移除了,父組件中的 @on-result-change='onResultChange' 回調也可以移除了

2018年4月27日 21:19
編輯回答
墻頭草
data() {
   return {
       has: this.hasCounter
   }
 }

這個用法有誤

2017年11月8日 18:17