标签:
React 的核心思想是:封装组件,各个组件维护自己的状态和 UI,当状态变更,自动重新渲染整个组件。
最近前端界闹的沸沸扬扬的技术当属react
了,加上项目需要等等原因,自己也决定花些时间来好好认识下这个东西。然后花时间自己写了一个demo:react-todos
, 你可以先点这里去看react-todo
react首先值得拍手称赞的是它所有的开发都基于一个组件(component)
,组件和组件之间传递方法,而且每个组件都有一个状态(state)
,当方法改变了这个状态值时,整个组件就会重绘
,从而达到刷新,另外,说到重绘就要提到虚拟dom
了,就是用js模拟dom结构,等整个组件的dom更新完毕,才渲染到页面,简单来说只更新了相比之前改变了的部分,而不是全部刷新,所以效率很高。
大家先新建一个项目文件夹,在里面建一个项目信息的文件package.json
:
{
"name": "react-todos",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"react": "^0.13.3",
"sass": "^0.5.0"
},
"devDependencies": {
"babel-core": "^5.5.8",
"babel-loader": "^5.1.4",
"css-loader": "^0.14.5",
"file-loader": "^0.8.4",
"jsx-loader": "^0.13.2",
"node-libs-browser": "^0.5.2",
"node-sass": "^3.2.0",
"sass-loader": "^1.0.2",
"style-loader": "^0.12.3",
"url-loader": "^0.5.6",
"webpack": "^1.9.11"
}
}
建好之后,运行命令:
npm install
安装项目依赖的所有模块。安装好之后,另外还有一点,项目数据是存储在本地浏览器的,所以我找到一个小模块用来操作localStorage,它的原理就是,通过将数据格式化成JSON字符串进行存储,使用的时候就解析JSON字符串。他的代码点这里看localDb可以看到,你可以复制一份,放在node_modules的文件夹内。
项目使用的技术方案是:webpack+react+es6
。关于es6的文章,我之前简单的介绍过,可以点这里去看es6,关于webpack的学习,我这里不详述了,看以后有时间再出篇文章吧。在项目文件夹下新建一个webpack.config.js
:
‘use strict‘;
module.exports = {
entry: [
"./src/entry.js"
],
output: {
path: ‘./out/‘,
filename: "bundle.js"
},
externals: {
‘react‘: ‘React‘
},
module: {
loaders: [
{ test: /\.js$/, loader: "jsx!babel", include: /src/},
{ test: /\.css$/, loader: "style!css"},
{ test: /\.scss$/, loader: "style!css!sass"},
{ test: /\.(png|jpg)$/, loader: ‘url?limit=8192‘}
]
}
};
上面的文件可以看到:入口文件是在src文件夹里的entry.js,然后输出文件放在out文件夹的bundle.js里。externals属性是告诉webpack当遇到require(‘react‘)的时候,不去处理并且默认为全局的React变量。这样子,我们就需要在index.html单独用src去加载js。最后看看配置的loaders:
jsx-loader
和babel-loader
来编译js文件。sass-loader
编译成css文件。!
连接。先来看一下项目的目录结构,最重要的就是src目录:
index.html
是项目的入口页面。components
文件夹存放项目拆分出来的各个组件文件。vendor
文件夹存放项目依赖的框架,这里只有react。先来看index.html:
<body>
<header>
<h1 class="todo-title">React-Todos</h1>
</header>
<div class="container todo-container">
<div id="app"></div>
</div>
<script src="./src/vendor/react.min.js"></script>
<script src="./out/bundle.js"></script>
</body>
entry.js :
‘use strict‘;
require(‘./styles/main.scss‘); // 引入样式表
require(‘./components/App‘); // 引入组件
webpack会将入口文件进行合并和整理,最后输出一个bundle.js,所以所有的逻辑都在这个js文件中,因此在index.html中,只需要引入react框架和bundle.js就好了。
这个todo的项目,我们可以分为三个部分:头部,中间部分,尾部。那我们就来逐一的分析一下这些组件:
‘use strict‘;
import React from ‘react‘;
import LocalDb from ‘localDb‘;
import TodoHeader from ‘./TodoHeader.js‘;
import TodoMain from ‘./TodoMain.js‘;
import TodoFooter from ‘./TodoFooter.js‘
//es6写法
class App extends React.Component { //定义组件,继承父类
constructor() { //定义App类的构造函数
super(); //调用父类的构造函数
this.db = new LocalDb(‘ReactDemo‘);
this.state = { //定义组件状态
todos: this.db.get(‘todos‘) || [],
isAllChecked: false
};
}
// 判断是否所有任务的状态都完成,同步底部的全选框
allChecked() {
let isAllChecked = false;
if (this.state.todos.every(todo => todo.isDone)) {
isAllChecked = true;
}
this.setState({ //改变状态,组件重绘
todos: this.state.todos,
isAllChecked: isAllChecked
});
}
// 添加任务,是传递给Header组件的方法
addTodo(todoItem){
this.state.todos.push(todoItem); //todo列表
this.db.set(‘todos‘, this.state.todos);
this.allChecked();
}
// 删除当前的任务,传递给TodoItem的方法
deleteTodo(index){
this.state.todos.splice(index, 1);
this.setState({todos: this.state.todos}); //改变状态
this.db.set(‘todos‘, this.state.todos);
}
// 清除已完成的任务,传递给Footer组件的方法
clearDone(){
let todos = this.state.todos.filter(todo => !todo.isDone); //过滤掉数组中todo.isDone为true的item。
this.setState({
todos: todos,
isAllChecked: false
});