vue 父子间通讯问题 子组件可以改变父组件的状态,父组件可以改变子组件状态,但是却改变不了自己本身的状态。

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; //④外层调用组件方注册变更方法,将组件内的数据变更,同步到组件外的数据状态中

            }
        },
    }
</script>

<style>

问题:
我想做双向数据绑定的方式来控制,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的值保持一致。

阅读 3.5k
2 个回答

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

// 子组件

computed: {
has() {

   return this.hasCounter

}
}

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

然后子组件的 watch 监听可以移除了 data 中的 has 也可以移除了,父组件中的 @on-result-change='onResultChange' 回调也可以移除了

data() {
   return {
       has: this.hasCounter
   }
 }

这个用法有误

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题