最近在学 React.js,也写了一些练习的项目,以前参考网上的一些代码写了一个很简单的 to-do list。对于初学者来讲,写个基本的 to-do list 对于理解 React 中的一些概念及语法却是挺有帮助的。javascript
如今不少的 React 项目中已经开始使用 ES6 来写了,不过由于我在学习 React 的时候看的教程大多都是用 ES5 写的,我这里仍是用的仍是更熟悉的 ES5 写法,虽然有点落伍了,但若想改为 ES6 版本倒也挺方便的。css
在正式的生产项目中,使用 webpack 能够很方便地对咱们的文件进行打包,这里由于程序比较简单,直接用 <script>
标签将 React 组件引入了。java
首先新建一个 index.html
文件,引入相关的资源文件。python
再新建一个 js
文件夹,咱们使用 React 须要这样的两个文件: react.js
和 react-dom.js
,你可使用 cdn 引入,这里直接将文件下载放在了 js
文件夹内。react
js
文件夹内还有一个 script.jsx
文件,咱们程序的主要内容就放在这个文件中。注意这里的后缀名是 jsx
,表示它是使用 React 的 jsx
语法来写的,引入它的时候按以下写法:webpack
<script type="text/babel" src="js/script.jsx"></script>
同时还须要一个 browser.js
文件,它可让 jsx
语法的文件在浏览器中运行。git
最后咱们再创建一个 css
文件夹,存放样式文件,个人项目中使用了 Bootstrap 的样式,因此须要下载 Bootstrap 的样式文件。github
做为一个最简单的 to-do list,这个程序没有过多的功能。能够从 demo 里看出,它的功能以下:web
显示每个任务
能够将任务标记为已完成,以区分未完成的任务
加入任务 / 删除任务
统计任务总数和完成的任务数量
做为一个示例程序,以上就是它的功能了。
咱们可使用 React 开发出各类组件(component),利用不一样组件的功能来实现一个应用。咱们这里建立的组件有:
TodoBox -TodoList -TodoItem -TodoFooter -TodoForm
TodoBox 是最外层的组件,其他的都是它的子组件
TodoList 是各个单独的待办任务的集合
TodoItem 即为一条单独的待办事项
TodoFooter 对上述的事项进行统计
TodoForm 用于加入新的项目
React 的组件有两种不一样的属性,state
和 props
。能够用一种简单的方法来区分它们:若是这个属性是其父组件传给它的,那么就是 props
,反之若是一个属性是组件本身的,那么就是 state
。
具体何时用 state
,何时用 props
,能够参考这几条:
Is it passed in from a parent via props? If so, it probably isn't state.
Does it change over time? If not, it probably isn't state.
Can you compute it based on any other state or props in your component? If so, it's not state.
这里咱们从代码来看看,属性是如何从父组件传递到子组件的。
每一条待办事项有这样的几个属性:
id: 任务的编号
task: 任务的具体内容
complete: 任务是否已经完成
咱们看看属性的传递过程。
首先在 TodoBox
组件的 state
中有一个 data
对象:
data: [ {"id": "0001", "task":"吃饭", "complete": "false"}, {"id": "0002", "task":"睡觉", "complete": "true"}, ... ]
TodoBox
组件的 render 函数中会有 TodoList
组件:
<TodoList data={this.state.data} // 其余的属性及方法写在这里 />
这样 TodoBox
组件的 data
属性就传递给了子组件 TodoBox
。在 TodoBox
中经过 this.props
来引用这一属性,即 this.props.data
。
TodoBox
组件还有子组件 TodoItem
,能够将属性继续传递下去。在 TodoList
组件的 render
函数中这样写:
var taskList = this.props.data.map(function(listItem) { return ( <TodoItem taskId={listItem.id} key={listItem.id} task={listItem.task} complete={listItem.complete} // 其余的属性及方法 ) }, this);
在 TodoItem
组件中就能够用 this.props.taskId
得到任务的 id 了。
咱们的程序中须要的函数有这几个:
handleTaskDelete: 根据id删除一项任务
handleToggleComplete: 切换一项任务的完成状态
handleSubmit: 新增一项任务
generateId: 给新增的任务一个随机的id
在 React 的组件中传递方法与传递属性相似,如今 TodoBox
组件中有一个 handleToggleComplete
函数,将它传递给 TodoList
组件:
<TodoList toggleComplete={this.handleToggleComplete} // 其余的属性及方法写在这里 />
这样你就能够在 TodoList
组件中经过 this.props.toggleComplete
来调用这一方法了,你也能够将这一方法继续向下一层的组件传递。
你能够下载 GitHub 上的项目文件,再用 python 开启一个 HTTP 服务器,就能够打开 http://localhost:8000/ 查看运行结果了。
git clone https://github.com/noiron/simplest-react-todolist.git cd simplest-react-todolist python -m SimpleHTTPServer // open a server with python
这篇博客里没有对整个项目全部的代码进行分析,更多内容仍是直接看代码更清楚。