React问题,我有一个交互的table,不知道将那个定于成state,求指教
 发布于 10 年前  作者 xushao0305  7846 次预览  最后一次回复是 10 年前  来自 问答 

untitled1.png

方案1的话 table每个item的 禁用启用交互不知道该如何操作 方案2的话 这么大的数据作为state,感觉有点大

大神们给点意见

多谢了

13 回复
xushao0305

顶个。各位大侠们帮忙啊

ypmei

把每一个tr作为一个对象,每次“操作”都是更新tr这个对象的state就可以了。

think2011

话说有 react 的中文社区,你可以去那里问问。

yuyang041060120

先列举下需要的类库

react.js react-with-addons.js EventEmitter.js 事件管理 underscore.js 数据处理

Github代码地址 获取代码后,直接打开index.html即可看到效果

代码

var ID = 123459; //自增长ID
var ee = new EventEmitter();
var update = React.addons.update;

var data = [
	{
		id: 123456,
		number: '漫道:xxxxxx',
		tplName: '模板1',
		content: '内容1',
		inUse: true,
		desc: '备注1'
	},
	{
		id: 123457,
		number: '盈信道:xxxxxx',
		tplName: '模板2',
		content: '内容2',
		inUse: false,
		desc: '备注2'
	},
	{
		id: 123458,
		number: '漫道:xxxxxx',
		tplName: '模板3',
		content: '内容3',
		inUse: true,
		desc: '备注3'
	}
];


var App = React.createClass({
	getInitialState: function () {
		return {data: this.props.data || []};
	},
	componentDidMount: function () {
		ee.on('update', this.handleUpdate);
		ee.on('add', this.handleAdd);
		ee.on('delete', this.handleDelete);
		ee.on('search', this.handleSearch);
	},
	handleUpdate: function (index, data, callback) {
		var newData = this.state.data.slice();
		_.extend(newData[index], data);
		this.setState({data: newData}, function () {
			callback && callback();
		});
	},
	handleAdd: function () {
		if (!this.state.data[0].id) {
			return;
		}

		var newData = update(this.state.data, {
			$unshift: [{
				number: '',
				tplName: '',
				content: '',
				desc: ''
			}]
		});

		this.setState({data: newData});
	},
	handleDelete: function (index) {
		var newData = update(this.state.data, {
			$splice: [[index, 1]]
		});
		this.setState({data: newData});
	},
	handleSearch: function (obj) {
		var result = _.filter(this.state.data, function (item) {
			return item[obj.searchType].indexOf(obj.searchValue) > -1;
		});

		this.setState({data: result});
	},
	render: function () {
		return (
			<div className="container">
				<Search />
				<TplBox data={this.state.data}/>
			</div>
		)
	}
});

var Search = React.createClass({
	handleSearch: function () {
		ee.emit('search', {
			searchType: this.refs.searchType.getDOMNode().value,
			searchValue: this.refs.searchValue.getDOMNode().value
		});
	},
	handleNew: function () {
		ee.emit('add');
	},
	render: function () {
		return (
			<div className="row" style={{marginBottom:30}}>
				<div className="col-lg-3">
					<select className="form-control input-sm" ref="searchType">
						<option value="number">模板号</option>
						<option value="tplName">模板名</option>
						<option value="content">短信内容</option>
						<option value="desc">备注</option>
					</select>
				</div>
				<div className="col-lg-3">
					<input type="text" className="form-control input-sm" ref="searchValue"/>
				</div>
				<div className="col-lg-1">
					<button className="btn btn-primary btn-sm" onClick={this.handleSearch}>搜索</button>
				</div>
				<div className="col-lg-offset-2 col-lg-2">
					<button className="btn btn-warning btn-sm pull-right" onClick={this.handleNew}>新建短信模板</button>
				</div>

			</div>
		)
	}
});

var TplBox = React.createClass({
	render: function () {
		return (
			<table className="table table-striped table-hover ">
				<thead>
				<tr>
					<th>序号</th>
					<th>模版号</th>
					<th>模板名</th>
					<th>短信内容</th>
					<th>状态</th>
					<th>备注</th>
					<th>操作</th>
				</tr>
				</thead>
				<TplList data={this.props.data}/>
			</table>
		)
	}
});


var TplList = React.createClass({
	render: function () {
		return (
			<tbody>
			{this.props.data.map(function (tpl, index) {
				return <TplItem data={tpl} index={index} key={index}/>
			})}
			</tbody>
		)
	}
});


var TplItem = React.createClass({
	getInitialState: function () {
		return {isEdit: false};
	},
	handleToggleEdit: function () {
		this.setState({
			isEdit: !this.state.isEdit
		});
	},
	render: function () {
		var tpl = this.props.data;
		return !tpl.id ?
			<TplItemNew index={this.props.index}/> :
			this.state.isEdit ?
				<TplItemEdit data={tpl} index={this.props.index} toggleEdit={this.handleToggleEdit}/> :
				<TplItemShow data={tpl} index={this.props.index} toggleEdit={this.handleToggleEdit}/>;
	}
});


var TplItemShow = React.createClass({
	handleEdit: function () {
		this.props.toggleEdit();
	},
	handleUse: function (index, use) {
		ee.emit('update', index, {inUse: use});
	},
	render: function () {
		var index = this.props.index;
		var tpl = this.props.data;
		return (
			<tr>
				<td>{index + 1}</td>
				<td>{tpl.number}</td>
				<td>{tpl.tplName}</td>
				<td>{tpl.content}</td>
				<td>{tpl.inUse ? <p className="text-success">已启用</p> : <p className="text-danger">已禁用</p>}</td>
				<td>{tpl.desc}</td>
				<td>
					{tpl.inUse ?
						<button className="btn btn-danger btn-xs" onClick={this.handleUse.bind(this,index,!tpl.inUse)}>
							禁用</button> :
						<button className="btn btn-success btn-xs" onClick={this.handleUse.bind(this,index,!tpl.inUse)}>
							启用</button>
					}
					<button className="btn btn-info btn-xs" onClick={this.handleEdit}>编辑</button>
				</td>
			</tr>
		)
	}
});

var TplItemEdit = React.createClass({
	handleCancel: function () {
		this.props.toggleEdit();
	},
	handleSave: function (index) {
		ee.emit('update', index, {
			number: this.refs.number.getDOMNode().value,
			tplName: this.refs.tplName.getDOMNode().value,
			content: this.refs.content.getDOMNode().value,
			desc: this.refs.desc.getDOMNode().value
		}, function () {
			this.props.toggleEdit();
		}.bind(this));
	},
	render: function () {
		var index = this.props.index;
		var tpl = this.props.data;
		return (
			<tr>
				<td>{index + 1}</td>
				<td><input ref="number" type="text" className="form-control input-sm" defaultValue={tpl.number}/></td>
				<td><input ref="tplName" type="text" className="form-control input-sm" defaultValue={tpl.tplName}/></td>
				<td><input ref="content" type="text" className="form-control input-sm" defaultValue={tpl.content}/></td>
				<td>{tpl.inUse ? <p className="text-success">已启用</p> : <p className="text-danger">已禁用</p>}</td>
				<td><textarea ref="desc" type="text" className="form-control input-sm" defaultValue={tpl.desc}/></td>
				<td>
					<button className="btn btn-primary btn-xs" onClick={this.handleSave.bind(this,index)}>
						保存
					</button>
					<button className="btn btn-default btn-xs" onClick={this.handleCancel}>取消</button>
				</td>
			</tr>
		)
	}
});

var TplItemNew = React.createClass({
	handleCancel: function (index) {
		ee.emit('delete', index);
	},
	handleCreate: function (index) {
		ee.emit('update', index, {
			id: ID++,
			number: this.refs.number.getDOMNode().value,
			tplName: this.refs.tplName.getDOMNode().value,
			content: this.refs.content.getDOMNode().value,
			inUse: false,
			desc: this.refs.desc.getDOMNode().value
		});
	},
	render: function () {
		var index = this.props.index;

		return (
			<tr>
				<td>{index + 1}</td>
				<td><input ref="number" type="text" className="form-control input-sm"/></td>
				<td><input ref="tplName" type="text" className="form-control input-sm"/></td>
				<td><input ref="content" type="text" className="form-control input-sm"/></td>
				<td>
					<p className="text-danger">已禁用</p>
				</td>
				<td><textarea ref="desc" type="text" className="form-control input-sm"/></td>
				<td>
					<button className="btn btn-primary btn-xs" onClick={this.handleCreate.bind(this,index)}>
						新增
					</button>
					<button className="btn btn-default btn-xs" onClick={this.handleCancel.bind(this,index)}>取消</button>
				</td>
			</tr>
		)
	}
});

React.render(<App data={data}/>, document.body);

截图

Image 1.png

yuyang041060120

写的不好,大致一个思路吧。没有用到Flux,也没用的后端交互,然并卵啊!

xushao0305

@yuyang041060120 非常感谢啊。 我现在用的仅仅是react,交互也是直接传递进去的。 多谢了,我看看先。回头再聊

xushao0305

@yuyang041060120 刚看了下你的代码,state的方式和我的一致,但是我方法是硬生生的给传递给各个子组件,借鉴你的思路,EventEmitter 明天把它用进去。 搞好以后贴代码

yuyang041060120

@xushao0305 试着用用reflux或redux。 最好加上服务端和校验,这样才能有实际运用的意义。

joney-pinkman

虽然没在项目中用过react,但我还是要安利下这个东东riot,很好很强大

xushao0305

@xushao0305 马上会和服务端进行交互。得空了以后在用下flux吧