React问题,我有一个交互的table,不知道将那个定于成state,求指教
发布于 9 年前 作者 xushao0305 6900 次浏览 最后一次编辑是 8 年前 来自 问答

untitled1.png

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

大神们给点意见

多谢了

13 回复

顶个。各位大侠们帮忙啊

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

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

先列举下需要的类库

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

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

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

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

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

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

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

回到顶部