react+flux 仿淘宝购物车

react+flux 仿淘宝购物车


    之前用react写了个表格的单表组件,然后在网上又看到别人家写的一些表格组件,瞬间感觉自己弄的东西好low。不过在写表格组件的时候遇到过一个关于react单向数据流传递的问题,通过一层一层子组件传递完成。而在网上却看到说可以用flux这个的store来方便实现。所以今天特地来实际操作一把,浅鄙见识大家多多指教。

目录结构

这是flux官方推荐的目录结构,其中组件放在components当中,stores中实现数据结构的存储,actions实现控制器的功能。这样就可以实现一个前端的mvc模型。因为react在前段将view层做得很好,不能单靠它实现mvc,所以facebook就又来了个flux两个组合实现一个前端mvc模型。其中app是启动应用。

具体代码

说了这么多,还是赶紧上代码。

先看看stores中存储的的东西。

/*
 *购物车商品模块
 */
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var Constants = require('../constants/Constants');
var assign = require('object-assign');


var CHANGE_EVENT = 'change';

var _moneyCateray = {};
var _storage = localStorage;
_moneyCateray = JSON.parse(_storage.getItem('_moneyCateray'));
/**
 *添加购物车商品
 */
function countsPur(purchase){
  /**
   *初始化检测
   */
  if(isEmpty()){
    _moneyCateray[purchase.id] = {
      price:0,
      count:1,
      detail:purchase
    };
    _moneyCateray[purchase.id].price += parseFloat(purchase.price);
    _storage.setItem('_moneyCateray',JSON.stringify(_moneyCateray));
    return;
  }
  /**
   *查看是否有同类单品
   */
  var flag = 0;
  for(var i in _moneyCateray){
    if(i == purchase.id){
      flag = 1;
      break;
    }
  }
  /**
   *将单品价格分类叠加
   */
  if(flag){
    _moneyCateray[purchase.id].price += parseFloat(purchase.price);
    _moneyCateray[purchase.id].count += 1;
  }
  else{
    _moneyCateray[purchase.id] = {
      price:0,
      count:1,
      detail:purchase
    };
    _moneyCateray[purchase.id].price += parseFloat(purchase.price);
  }
  _storage.setItem('_moneyCateray',JSON.stringify(_moneyCateray));
}

/**
 *删除商品
 */
function deletePur(id){
  delete _moneyCateray[id];
  _storage.setItem('_moneyCateray',JSON.stringify(_moneyCateray));
}

/**
 *删除一件商品的数量
 */
function deleteCount(id){
  if(_moneyCateray[id].count!=0){
    _moneyCateray[id].count -= 1;
  }else{
    _moneyCateray[id].count = 0;
  }
  _storage.setItem('_moneyCateray',JSON.stringify(_moneyCateray));
}

/**
 *检测_moneyCateray是否为空
 */
function isEmpty(){
  for(var i in _moneyCateray){
    return false;
  }
  return true;
}


var Store = assign({}, EventEmitter.prototype, {

  /**
   *获取总价
   */
   getMoney:function(){
    return JSON.parse(_storage.getItem('_moneyCateray'));
  },

  /**
   *侦听事件变化
   */
  emitChange: function() {
    this.emit(CHANGE_EVENT);
  },

  addChangeListener: function(callback) {
    this.on(CHANGE_EVENT, callback);
  },

  removeChangeListener: function(callback) {
    this.removeListener(CHANGE_EVENT, callback);
  }
});

/**
 *注册事件
 */
AppDispatcher.register(function(action) {
  var purchase;

  switch(action.actionType) {
    case Constants.PURCHASE_ADD:
      purchase = action.purchase;
      if (purchase !== '') {
        countsPur(purchase);
        Store.emitChange();
      }
      break;
    case Constants.PURCHASE_DELETE:
      deletePur(action.id);
      Store.emitChange();
      break;
    case Constants.PURCHASE_SUB:
      deleteCount(action.id);
      Store.emitChange();
      break;

    default:
      // no op
  }
});

module.exports = Store;

其中AppDispatcher是flux推荐的用来注册事件的,我个人感觉是通过这个来实现控制器功能,调用相应的函数功能。
下面来看看ui组件部分的代码

上面是把组件分拆出来的,如下图

将组件分拆,react官网上也这么推荐这样将一个组件尽量分拆出来http://facebook.github.io/react/docs/thinking-in-react.html

单个商品


var React = require('react');
//var Actions = require('../actions/Actions');


var Per = React.createClass({

	getInitialState: function(){
		/**
		 *商品id,价格,详情,图片地址
		 */
		return {
			id:this.props.id,
			price:this.props.purchase.price,
			detail:this.props.purchase.detail,
			url:this.props.purchase.url,
		}
	},

	render: function(){
		var price = this.state.price;
		return(
			<div className="per">
                <img src={this.state.url} />
                <h3>¥<span>{(parseFloat(price)).toFixed(2)}</span></h3>
                <div className="title">{this.state.detail}</div>
                <a href="javascript:void(0)" className="button orange addcart" onClick={this._OnSave}>加入购物车</a>
            </div>
			);
	},

	_OnSave: function(){
		this.props.OnSave(this.state);
	}
});

module.exports = Per;

商品列表

/*
 *购物列表
 */

var React = require('react');
var Per = require('./Per');
var Actions = require('../actions/Actions');
var Store = require('../stores/purchase');


var PerList = React.createClass({

	getInitialState: function(){
		/**
		 *商品id,价格,详情,图片地址
		 */
		return {
			list:this.props.lists
		};
	},

	componentWillUnmount: function(){

	},

	componentDidMount: function() {
	    Store.addChangeListener(this._onChange);
	},

	componentWillUnmount: function() {
	   Store.removeChangeListener(this._onChange);
	},

	render: function(){
		var list = [];
		var purchase = this.state.list;
		for(var i in purchase){
			list.push(<Per purchase={purchase[i]} key={i} id={i} OnSave={this._onSave} />);
		}
		return(
			<div className="demo">
			  {list}
            </div>
			);
	},

	_onChange: function() {
	    //this.setState(getTodoState());
	},

	_onSave: function(pur){
		Actions.addPur(pur);
	}
});

module.exports = PerList;

购物车

/*
 *购物车列表
 */

var React = require('react');
var Store = require('../stores/purchase');
var Actions = require('../actions/Actions');
var PurchaseItem = require('./PurchaseItem');

var PurchaseCar = React.createClass({

	getInitialState: function(){
		return {
			purchaseCar:Store.getMoney()
		};
	},

	componentDidMount: function() {
	    Store.addChangeListener(this._onChange);
	},

	componentWillUnmount: function() {
	   Store.removeChangeListener(this._onChange);
	},

	render: function(){
		var car = this.state.purchaseCar;
		var PuchaseCarList = [];
		for(var i in car){
			PuchaseCarList.push(
				<PurchaseItem 
				  key={i} 
				  purchase={car[i]} 
				  AddItem={this._addItem} 
				  SubItem={this._subItem}
				  DeleteItem={this._deleteItem}/>);
		}
		return(
			<div>{PuchaseCarList}</div>
			);
	},

	_onChange: function(){
		this.setState({purchaseCar:Store.getMoney()});
	},

	_addItem: function(pur){
		Actions.addPur(pur.detail);
	},

	_subItem: function(id){
		Actions.subPur(id);
	},

	_deleteItem: function(id){
		Actions.deletePur(id);
	}
});

module.exports = PurchaseCar;

通过上面几块代码就实现了一个简单的前端的mvc模型。具体效果如图

posted @ 2015-12-14 23:29  marvine  阅读(1034)  评论(0编辑  收藏  举报