综合案例:图书管理——添加-排重-删除-编辑-禁止修改
效果演示
静态布局
- 实现表格基本布局
- 通过组件方式实现表格布局效果
- 数据临时填充假数据
准备假数据并动态填充页面
- 模拟异步方式获取假数据
componentDidMount () {
// 一般用于后台接口调用
let list = [{
id: 1,
bname: '智能时代'
}, {
id: 2,
bname: '肖申克的救赎'
}, {
id: 3,
bname: '阿甘正传'
}, {
id: 4,
bname: '浪潮之巅'
}]
setTimeout(() => {
this.setState({
list: list
})
}, 1000)
}
// 使用数据填充模板
// 根据数据动态生成表格行标签
let trInfo = this.state.list.map(book=>{
return (
<tr key={book.id}>
<td>{book.id}</td>
<td>{book.bname}</td>
<td>
<a href="#">编辑</a>
<span>|</span>
<a href="#">删除</a>
</td>
</tr>
);
})
加载提示效果
-
加载提示效果
- 数据在加载的过程中,应该进行提示;加载完数据之后再进行数据填充
{this.state.list.length===0&&<tr><td colspan='3'>正在加载数据...</td></tr>}
表单值处理
- 表单组件受控处理
constructor(props) {
super(props)
this.state = {
bookId: '',
bookName: '',
list: []
}
}
<div className="form">
<label htmlFor='bookId'>图书编号:</label>
<input value={this.state.bookId} onChange={this.handleId} type="text" id="bookId"/>
<label htmlFor='bookName'>图书名称:</label>
<input value={this.state.bookName} onChange={this.handleName} type="text" id="bookName"/>
<button onClick={this.handleSubmit}>提交</button>
</div>
handleId = (e) => {
this.setState({
bookId: e.target.value
})
}
handleName = (e) => {
this.setState({
bookName: e.target.value
})
}
- 多个表单输入域共享相同的监控事件函数
- ES6新特性:对象的属性名称可以是动态的
handleItem = (e) => {
this.setState({
// ES6新特性:对象的属性名称可以是动态的
[e.target.id]: e.target.value
})
}
添加图书
-
添加图书数据
- 不要直接修改state中的原有引用类型的数据,而是要复制一份再修改,然后整体更新
addBook = () => { // 添加图书 /* 1、获取表单数据组合为对象 2、复制原有的列表数据 3、把对象添加到数组中 4、整体更新数据列表 5、清空表单 */ let { bookId, bookName } = this.state let book = { id: bookId, bname: bookName } let list = [...this.state.list] list.push(book) this.setState({ list: list, bookId: '', bookName: '' }) }
表单非空判断与书名排重
- 添加图书表单非空判断
if(!this.state.bookId) {
alert('请输入图书编号')
return
}
if(!this.state.bookName) {
alert('请输入图书名称')
return
}
- id和书名排重
// 0、重复性验证
// some的作用:判断数组中是否包含符合条件的数据,只要有一个就返回true
let flag1 = this.state.list.some(book => {
return book.id === parseInt(this.state.bookId)
})
if(flag1) {
// ID已经存在,提示修改并终止
alert('图书ID已经存在')
return
}
let flag2 = this.state.list.some(book => {
return book.bname === this.state.bookName
})
if(flag2) {
// 名称已经存在,提示修改并终止
alert('图书名称已经存在')
return
}
删除图书
-
根据id删除图书信息
- 先获取要删除的图书的id
- 根据id获取数据索引
- 根据索引删除数组中数据
deleteBook = (id) => { // 删除图书 /* 1、获取要删除的图书ID 2、复制原始数据 3、根据id查询要删除的数据的索引 4、根据索引进行删除 5、整体更新 */ let list = [...this.state.list] let index = list.findIndex(book => { return book.id === id }) list.splice(index, 1) this.setState({ list: list }) }
编辑图书-查询信息
-
根据ID查询图书信息
- 获取要编辑的图书的id
- 根据id查询要编辑的图书信息
- 把找到的图书信息更新到表单
toEdit = (id) => { // 编辑操作第一步 /* 1、获取要编辑的图书id 2、根据id找到要编辑的数据 3、把找到的数据填充到表单 */ let ret = this.state.list.filter(book => { return id === book.id }) let book = ret[0] this.setState({ bookId: book.id, bookName: book.bname }) }
编辑图书-提交信息
-
修改图书信息后再次提交
- 先获取id
- 根据id查询要编辑的图书
- 找到后直接修改名称
editBook = () => { // 编辑数据 /* 1、复制原有数据 2、根据id查找到要编辑的数据进行修改 3、整体更新数据列表 4、清空表单 */ let list = [...this.state.list] list.forEach(book => { if(book.id === this.state.bookId) { // 找到了要修改的图书,直接修改 book.bname = this.state.bookName } }) this.setState({ list: list, bookId: '', bookName: '', // 编辑成功后重置状态位,用于实现再次添加 flag: true }) }
控制id不允许修改
- 可以使用readOnly属性进行控制
<input readOnly={!this.state.flag} type="text" id="id" value={this.state.id} onChange={this.idHandle} />