react新手demo——TodoList
react-todolist.gif
一: 写在文章开头
今天我们就使用 react
来实现一个简易版的 todolist
,我们可以使用这个 demo
进行 list
的增删改差,实际效果如上图所示。大家可以clone
下来查看:react-todolist
这篇文章我们就不使用 redux
,因为这个 demo
本身比较简单,不需要通过 redux
来管理我们的状态。
redux中也有非常有名的一句话叫做:
"如果你不知道是否需要 Redux,那就是不需要它。"
我们废话不多说,直接进入正题。
二:项目的目录结构
. ├── app // 开发的文件夹,组件放在这个文件夹中
│ ├── components // 项目的组件
│ │ ├── App.js // 最外层包含下面组件的总组件
│ │ ├── AppFooter.js // App的三个筛选按钮的组件
│ │ ├── AppForm.js // 添加list的form
│ │ ├── AppList.js // 显示list数据的智能组件
│ │ └── AppTodos.js // 显示list的木偶组件
├── css // 放css文件的地方。
│ ├── semantic.css // 我们的文件用到了semantic.css,
├── node_modules // 第三方的依赖
├── .babelrc // babel配置文件
├── .gitignore // git上传时忽略的文件
├── bundle.js // webpack build之后的文件
├── index.html // 项目的模版文件
├── main.js // 项目的入口文件
├── webpack.config.js // webpack配置文件
├── README.md // readme文件
└── package.json // 当前整一个项目的依赖
三:前期准备,安装依赖
1,首先我们新建一个todolist文件夹,根据我的目录结构建好相应的文件,如果大家嫌麻烦,大家可以clone我的项目,然后看着我的代码,我会一一进行说明的。package.json我们可以自己创建。
$ mkdir todolist$ cd todolist
2,建立package.json
文件
npm init
3,安装相应的依赖,我先解释一下这些依赖的作用
首先安装Babel,Babel 是一个 JavaScript 编译器,他可以将es6或者es7的语法转化为浏览器能识别的javascript。
npm install babel-cli babel-core --save-dev
其次安装我们的主角,
react
npm install react react-dom --save-dev
安装
webpack
,打包工具;和webpack-dev-server
,用于来给我们开启一个服务的。npm install webpack webpack-dev-server --save-dev
安装
loader
打包,通过使用不同的loader
,webpack
有能力调用外部的脚本或工具,实现对不同格式的文件的处理,比如说分析转换scss为css,或者把下一代的JS文件(ES6,ES7)转换为现代浏览器兼容的JS文件,对React的开发而言,合适的Loaders可以把React的中用到的JSX文件转换为JS文件。大家想了解更多的webpack的内容,可以参考webpack中文文档
npm install css-loader babel-loader style-loader --save-dev
然后我们在
webpack.config.js
中引用这些依赖,具体的格参数的意思,大家可以参考webpack各文档说明,我下面也会简单的注释一下。module.exports = {
entry: './main.js', // webpack打包的入口文件
output: {
filename: './bundle.js' // 输出之后的文件名
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader' // babel的loader,jsx文件使用babel-loader处理
}, {
test: /\.css$/,
exclude: /node_modules/,
loader: 'style!css' // css和styleloader,对css后缀的文件进行处理
}
]
},
devtool: 'cheap-source-map',
}
同时要让我们的
babel
能在react
中生效,同时支持es6
,我们需要安装下面的插件npm install babel-preset-es2015 babel-preset-react babel-preset-stage-0 --save-dev
安装完依赖后,我们在
.babelrc
文件中引入这几个依赖{
"presets": ["es2015","react",'stage-0']
}
其次为了当我们每次添加list的时候有一个唯一的id,我们使用
uuid
npm install uuid --save-dev
四:组件的编写,是我们的页面能够显示出来
编写模版文件
index.html
在这个模版文件里面,我们引入
semantic.css
文件,然后建立一个id=app
的<div>
为了我们后续的react
操作。<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>react-todolist</title>
<link rel="stylesheet" type="text/css" href="/css/semantic.css">
<style>
.active { color: red }
.line{
display: inline-block;
border-bottom: 1px solid #222222;
width:100px;
position: absolute;
left:0;
top:7px;
}
.ui.comments .comment{
padding:0;
margin:2em 0 0;
}
</style>
</head>
<body>
<div class="ui container" style="padding:30px;">
<div id="app"></div>
</div>
<script src="./bundle.js"></script>
</body>
</html>
编写入口文件
main.js
这边的
data
是我们的模拟数据,将其传入到<App/>
组件,在子组件中可以通过props.data
的方法获取data
。对于react的基础知识,大家可以参考来自一位react新手的react入门须知。import React from 'react'
import ReactDOM from 'react-dom'
import App from './app/component/App'
let data = [
{id: 0, text: '天气不错哦!!!', complete: false},
{id: 1, text: '天气不错哦!!!', complete: false},
{id: 2, text: '出去玩啊!!!', complete: true},
]
ReactDOM.render(
<App data={data}/>,
document.getElementById('app')
)
编写
component
里面的组件App.js
这个组件我们可以认为是一个容器组件,我们会把
AppForm
、AppList
、AppFooter
放在这个组件中。import React from 'react'
import AppList from './AppList.js'
import AppForm from './AppForm.js'
import AppFooter from './AppFooter.js'
class App extends React.Component {
state = {
choosevalue : 1,
data: this.props.data
}
render () {
const { data } = this.state;
return (
<div className='ui comments'>
<h1>My Todo with React</h1>
<div className='ui divider'></div>
<AppForm />
<AppList data={data}/>
<AppFooter />
</div>
)
}
}
export default App;
AppForm.js
这个组件是我们添加
list
用的一个form
组件,其中下面的styles
这个对象那个也是jsx
中申明样式的一种方式,我们还可以使用className
来添加样式名字。import React from 'react';
import uuid from 'uuid';
var styles = {
'title': {
width: 200,
display: 'inline-block',
marginRight: 10,
verticalAlign: 'top'
}
}
class AppForm extends React.Component {
render () {
return (
<form className='ui reply form'>
<div className='field' style={styles.title}>
<input type='text' placeholder='TODO' ref='text' />
</div>
<button type='submit' className='ui blue button'>
添加
</button>
</form>
)
}
}
export default AppForm;
AppList.js
这个组件是我们在
react
中常说的智能组件,得到数据lists
后通过map
方法遍历数据,然后进行渲染。这里的map
方法是用到了es6
中的解构赋值,大家可以参考react新手必须懂得es6的基础知识,然后将值一一传递到子组件中去。import React from 'react'
import AppTodos from './AppTodos'
class AppList extends React.Component {
render () {
const a = this.props.data.map(({ id, text, complete }, index) => {
return
<AppTodos
key={index}
id={id}
text={text}
complete={complete}
/>
})
return (
<div> { a } </div>
)
}
}
export default AppList;
AppTodos.js
这个组件是我们在
react
中常说的木偶组件,就是得到数据渲染组件。import React from 'react'
var styles = {
'title': {
paddingLeft: '20px',
paddingRight: '50px',
position: 'relative'
},
'delete': {
marginLeft: '20px',
marginRight: '50px'
}
}
class AppTodos extends React.Component {
render () {
return (
<div className='comment'>
<div className='content'>
<span
className='author'
style={styles.title}
>
{this.props.text}
<span
className={this.props.complete ? 'line' : ''}
/>
</span>
<span className='author'
style={styles.title}>
{this.props.complete ? '已完成' : '未完成'}
</span>
<span className='author'>{this.props.id}</span>
<span className='ui blue button'
style={styles.delete} >
删除
</span>
</div>
</div>
)
}
}
export default AppTodos;
AppFooter.js
这个组件就是下面的三个按钮
全部
、未完成
、已完成
。import React from 'react'
var styles = {
'title': {
marginRight: 10,
fontSize: 20
},
'top': {
marginTop: 20
}
}
class AppFooter extends React.Component {
render () {
return (
<div>
<h2 style={styles.top}>show</h2>
<button
type='submit'
style={styles.top}
className='ui blue button'
value='1'
ref='all'
>
全部
</button>
<button
type='submit'
style={styles.top}
className='ui blue button'
value='2'
ref='active'
>
还未完成
</button>
<button
type='submit'
style={styles.top}
className='ui blue button'
value='3'
ref='complete'
>
已完成
</button>
</div>
)
}
}
export default AppFooter;
然后我们在命令行输入,会开启一个服务。
npm run server
打开浏览器,输入
http://localhost:8080
,可看到:react-demo_1.png
5,实现list
的添加操作
首先理一下流程
首先在
form
输入待办事情,点击添加触发一个handleSubmit
点击函数,但是我们的data
是通过<App />
组件来分发的,而list
是组件AppList
渲染的。这里涉及到了从子组件传递值给父组件
,其实也很简单,就从父组件中传一个函数给子组件,子组件将值通过函数再传递出去,大家可以参考react父子组件间的交流。在组件
App.js
中,我们加入一个OnAddTodoItem
函数,并传入到AppForm
组件中,我们新建函数中将传进来的newItem
通过concat()
现在的data
,然后更新state
。...
OnAddTodoItem (newItem) {
let newdata = this.state.data.concat(newItem);
this.setState({data : newdata});
}
render () {
const { data } = this.state;
return (
<div className='ui comments'>
<h1>My Todo with React</h1>
<div className='ui divider'></div>
<AppForm
AddTodoItem={this.OnAddTodoItem.bind(this)} />
<AppList
data={data}/>
<AppFooter />
</div>
)
}
}
export default App;
在组件
AppForm.js
中,我们加入一个handleSubmit
函数,并在form
表单添加一个onClick
函数,将用户输入的数据,通过uuid生成的id
、输入的text
、以及是否完成false
。通过函数传递给父组件。...
handleSubmit (event) {
event.preventDefault()
let text = this.refs.text.value
if (!text.trim()) {
alert("Input can't be null")
return
}
let id = uuid();
this.props.AddTodoItem({id,text,complete:false});
}
render () {
return (
<form
className='ui reply form'
onSubmit={this.handleSubmit.bind(this)}>
<div
className='field'
style={styles.title}>
<input type='text' placeholder='TODO' ref='text' />
</div>
<button type='submit' className='ui blue button'>
添加
</button>
</form>
)
}
}
export default AppForm;
你可以看到如下效果:
react-add2.gif
6,完成筛选功能
首先里一下流程
我们给下面的三个按钮设置了不同的
value
,1
代表全部、2
代表未完成、3
代表已完成,然后我们根据相应的value
,展示相应的list,给三个按钮分别加上handleAll
、handleActive
、handleComplete
三个方法,在onClick
时触发。App.js
添加一个加上
choosevalue
的state
,默认为1
,即全选,同时将其传入到<AppList/>
中去,同时添加chooseValue
的方法,然后传入到AppFooter
组件中去。...
state = {
choosevalue : 1,
data: this.props.data
}
ChooseValue (id) {
this.setState({choosevalue:id});
}
...
<AppList
data={this.state.data}
choosevalue={this.state.choosevalue}
/>
<AppFooter
SubmitChooseValue={this.ChooseValue.bind(this)}
/>
AppFooter.js
...
handleAll () {
let all = this.refs.all.value;
this.props.SubmitChooseValue(all);
}
handleActive () {
let active = this.refs.active.value;
this.props.SubmitChooseValue(active);
}
handleComplete () {
let complete = this.refs.complete.value
this.props.SubmitChooseValue(complete);
}
render () {
return (
<div>
<h2 style={styles.top}>show</h2>
<button
type='submit'
style={styles.top}
className='ui blue button'
value='1'
ref='all'
onClick={this.handleAll.bind(this)}
>
全部
</button>
<button
type='submit'
style={styles.top}
className='ui blue button'
value='2'
ref='active'
onClick={this.handleActive.bind(this)}
>
还未完成
</button>
<button
type='submit'
style={styles.top}
className='ui blue button'
value='3'
ref='complete'
onClick={this.handleComplete.bind(this)}
>
已完成
</button>
</div>
)
}
}
export
以上是 react新手demo——TodoList 的全部内容, 来源链接: utcz.com/z/383961.html