问题
不记得什么时候在哪里看到过这样的一个组件开发规范:“子组件应当自己维护自己的内部状态””,所以正常情况下子组件的内部状态由data函数初始化供自身调用。可是我在实际项目开发过程中却是经常遇到下面的情况。
- 不同组件之间需要通信状态
- 一个组件的状态的改变需要与另一些组件的状态保持同步
举个例子
示意图
从图中可以看出来有这么一些状态需要这个页面维护:
- 是否全选
- 是否显示对话框
- 是否显示删除按钮
而子组件的内部状态有这样的:
- 商品是否选中
- 全选状态的变更
- 对话框是否关闭
思考
如果子组件自身维护内部状态将只能通过vuex
来更新父组件的状态。
可是我项目明明用了vuex
的,可我为什么不喜欢在子组件里用vuex
呢?原因其实也很简单,因为vuex
的state已经很复杂了,并且这些状态只适合在这个页面使用没必要全局共享,而且也会让子组件和vuex
的数据耦合起来。所以怎么办呢?
只能够子组件通过props
接收父组件的状态再$emit
交由父组件更新props
达到状态交互的效果。
因此:和业务相关的组件状态有时候有必要暴露给父组件
组件示意代码
<template>
<div class="ys-cart-wrapper">
<YsHeader class="header" :show-back="false" :show-right-text="true" :right-text="rightText" @onRightClicked="manage">购物车</YsHeader>
<div class="cart">
<ul v-if="!isNull">
<CartItem v-for="(item,index) in cartItem" v-bind:key="index" v-bind="item" @handleSelect="onItemSelected" @handleQuantity="onQuantityChange" ></CartItem>
</ul>
<template v-else>
<figure>
<img src="../../assets/image/no-goods.png" alt="购物车空空如也~">
<figcaption>
购物车空空如也
</figcaption>
</figure>
<a href="javascript:;" @click="goIndex">前往购买</a>
</template>
</div>
<CartBottom :checked="selectedAll" v-bind:total="getTotal" class="bottom" :show-delete="showDelete" @selectAll="handleSelectAll" @checkOut="checkOut" @delete="confirm"/>
<Dialog v-show="showDialog" :isShow="showDialog" title="大人,三思而后行啊~" left-btn-text="我再想想" right-btn-text="确认" @cancel="cancel" @ok="ok" @maskClicked="maskClicked"/>
</div>
</template>