redux操作购物车每个商品的count

1,做一个类似饿了么的商品页,在商品列表和购物车两处能同步操作商品的购买数量。应该如何管理reducer。

2,数据结构如下Goods:[

{
    name: '热销',
    foods:[
        {
            name: '粥',
            price: 10,
            count: 0
        }
        {
            name: '饼',
            price: 5,
            count: 0
        }
    ]
},
{
    name: '饮料',
    foods:[
        {
            name: '可乐',
            price: 5,
            count: 0
        }
        {
            name: '雪碧',
            price: 5,
            count: 0
        }
    ]
}

]
3,每一个food有组件可+-数量,另有购物车组件内也能+-已选food的数量,要求这两处的操作对food的count同步
4,使用vuex可以直接更新food的count,会自动刷新组件。但redux没有想到合理的解决方案。
请帮忙给出解决思路或方案,谢谢~

阅读 5.6k
2 个回答

这概念可以说很简单的,但前提是你需要对Redux有一定的理解。

首先,由题中的应用说明,你的数据模型实际上应该至少有两个。一个是商品,另一个是购物车,这就是把商品加到购买清单之上的。

基本的数据正规化时,商品必定要有id值,这也是购物车数据模型上需要的,购物车数据模型上只需记载id、数量等等,可以到商品数据中反查出商品的数据,不需要重覆记录这事。商品列表中有记录加减数量的count值是没那么恰当,较为合适的作用来说,商品列表只是纯提供商品信息的作用。一个组件呈现的数据,并没有说数据来源只能来自一个,也可以来自多个。

不过本题中是要讨论有关于数据同步更动的情况,因此就还是以两个数据模型中的都有各自的count属性来讨论。

数据模型决定后,就可以开始撰写reducer的部份,依照上面的数据模型,会有两个对应的reducer。reducer需要关联"动作"的发送情况,也就是会发生什么动作,以及该如何对应作状态的更动。

这里的关键是当事件触发时,例如这里的"用户更动数量"事件触发时,这个动作在发送到store后,能否在reducer中同步更动到商品与购物车两者的数据?

这里的知识是有关于在Redux中的动作与状态更动的关系,一个动作能否更动到两个不同的状态,这与使用vuex或react没什么关系,在Redux能更动到状态,自然就会触发重渲染(透过react-redux或有订阅render函数)。

动作与状态更动的关系在Redux中是什么的?答案不是1对1的,是"多对多"的。也就是说,一个动作是可以触发多个状态中的更动,或是多个动作触发单个状态更动,或是更复杂的多个动作触发多个状态更动。

开发者会误解为动作与状态更动是1对1的,是因为大部份的教学演示的例子都很小,没有太复杂的数据模型,第二个原因是对于combineReducer这个Redux中的方法并没有很彻底理解它是怎么运行的,只是大概知道它作了合并多个reducer们,变为一个reducer。

在简单的演示中,你都会看到reducer的基本写法是用switch语句来区分不同的动作,以此来决定要如何作状态的更动,像下面的代码例子:

function firstReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
            // 处理动作 x 的状态更动
        case ACTION_Y:
            // 处理动作 y 的状态更动
    }
}

如果两个不同的动作,执行同一份reducer的中的代码,那就也是用switch语句写在一起就行了,例如以下的代码:

function firstReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
        case ACTION_Y:
            // 处理动作 x 或 y 的状态更动
    }
}

让开发者可以撰写多个不同的reducer,然后在创建store时先进行合并,只是一种便利的作法而已。这不代表在单一个Redux应用运行时,可以允许多个reducer,依然只能允许一个reducer,但这个合并过的reducer与我们所撰写的reducer的函数内容构造不太一样。以combineReducers过的reducer(通常称为rootReducer),它会产生一个包含有特别结构的函数,在运行时会依次运行加入合并的这些reducer函数们,不过顺序因为用的是对象,所以并没有保证顺序。

也就是说,当像下面这样的代码。动作X传入后会到第一个reducer中执行,执行更动对应的状态的代码,再到第二个reducer中执行,执行更动对应的状态的代码,都会作更动状态的动作,这就是一个动作更动到两个的不同状态的情况(这里省略掉用combineReducers方法合并的代码,次序可能不保证):

function firstReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
            // 处理动作 x 的状态更动
    }
}

function secondReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
            // 处理动作 x 的状态更动
    }
}

所以,只要是同步地情况下,你需要一个动作更动到不同的状态时、或多个动作更动到单个状态、甚至是多个动作更动到多个状态,用这个概念就可以写得出来了。

这种情况都会很常见到,例如在商城应用中,当一笔订单创建时,应该要从商品数据中把这笔订单中商品项,作相对应的存货量减少,这很明显的就是一个动作更动到两个不同的状态。

当然,如果涉及异步的运行,例如与服务器的相互沟通,或是计时器等等,这还需要用另外的方式来处理,redux-thunk的方式也是很容易可以作得到的,对于动作与状态更动的对应关系,不要误解了它们之间的关系。

把数量的加减通过action去dispatch到reducer

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