一前言
刚开始入门Vue的时候,是通过编写todoList入门的,同样,入门React,也通过react+antd编写一个简单的todoList小Demo,熟悉React的基本语法和开发流程。
二程序功能
- 显示当前的任务
- 加入/删除任务
- 可以将任务标记为已完成/未完成
三创建项目
- 下载Node.js
- 安装
React脚手架- npm i create-react-app -g
如果你以前全局安装过,可以忽略当前操作 - create-react-app todolist
- cd todolist
- npm i antd -S
- npm start
- npm i create-react-app -g
- 打开localhost:3000 查看页面,显示如下,表示成功启动。

四正文
- 4.1 引入sass
- 以前用vue-cli脚手架的时候,只需要引入sass的相关依赖即可。但是在crate-react-app,除了引入sass依赖
npm i sass-loader node-sass -S之外,还需要进行额外的配置:在node_modules/react-scripts/config/webpapack.config.js文件下,在module配置项的最后一添加:
{ test: '/\.scss$/', loaders: ['style-loader', 'scs-loader', 'sass-loader'] } - 以前用vue-cli脚手架的时候,只需要引入sass的相关依赖即可。但是在crate-react-app,除了引入sass依赖
- 4.2 引入css模块化
-
css的规则都是全局的,任何一个组件的样式规则,都对整个页面有效。
-
所以在
Vue中,我们为了避免组件样式全局污染,框架给我们提供了一个scoped的选项。通过如下定义:<style scoped> ... </style>我们可以避免不同组件之间的样式污染, 但是在React中是不存在这个选项的。React则是通过 css module 来防止对不同组件的全局样式污染。 -
其实在create-react-app中内置了css Module的配置,我们只需将所有的.
.css/.scss/.less等样式文件都修改成.module.css/.module.scss/.module.less, 然后在jsx文件中使用import的方式将其引入。import styled from './App.module.scss' <div className={styled.wrapper}> </div>

-
可以看到生成的类名是独一无二的,和Vue中scoped原理是一样的。
- 4.3 功能代码
import React, {Component, Fragment} from 'react';
import { Input, List , Checkbox } from 'antd'
import styled from './App.module.scss'
const {Search} = Input
class App extends Component {
constructor (props) {
super(props);
this.state = {
value: '',
list: [
{
title: '吃饭',
id: 1,
isCompleted: false
},
{
title: '睡觉',
id: 2,
isCompleted: false
},
{
title: '打豆豆',
id: 3,
isCompleted: true
}
]
}
}
render () {
return (
<div className={styled.wrapper}>
<h2>Todo-List</h2>
<Search
placeholder="请输入关键字~~"
enterButton="添加"
size="large"
allowClear
value={this.state.value}
onChange={this.handleChange}
onPressEnter={this.handlePressEnter}
onSearch={this.handleAdd}
/>
<List
bordered
className={styled.gaosen}
dataSource={this.state.list}
renderItem={(item, index) => <List.Item className={styled['list-item']}>
<Fragment>
<Checkbox checked={item.isCompleted} onChange={this.handleCheckChange.bind(this,item.id)}></Checkbox>
<span className={item.isCompleted ? styled['line-through'] : ''}>{item.title}</span>
</Fragment>
<span style={{color:'red'}} onClick={this.handleDelete.bind(this, item, index)}>删除</span>
</List.Item>}
/>
</div>
);
}
// 改变选中状态
handleCheckChange (id) {
this.setState((prevState) => {
console.log(prevState)
return {
list: prevState.list.map(todo => {
if (todo.id === id) {
todo.isCompleted = !todo.isCompleted
}
return todo
})
}
})
}
// 回车
handlePressEnter = () => {
this.handleAdd(this.state.value)
}
// change
handleChange = (e) => {
const value = e.target.value
this.setState({
value
})
}
// delete
handleDelete (item, index, e) {
let newList = JSON.parse(JSON.stringify(this.state.list))
newList.splice(index, 1)
this.setState({
list: newList
})
}
// add
handleAdd = (title) => {
if (!title) return
let copy = [...this.state.list, {title}]
this.setState({
list: copy,
value: ''
}, () => {
})
}
}
export default App;
- 4.4 页面效果
