React+Redux实现简单的待办事项列表ToDoList


Posted in Javascript onSeptember 29, 2019

使用Redux做了一个简单的ToDoList待办事项列表,具体如下

这个例子也是源于Redux作者Dan Abramov的视频demo
还要特别说明一下
我还没有使用react-redux库进行解耦(可能以后加)
也没有拆分成多个文件等等优化
为了单纯的练习redux
适合初步学习redux的同学
本人学疏才浅,发现可以优化的地方或者问题还请大家指正,谢谢

功能样式

React+Redux实现简单的待办事项列表ToDoList

样子就是这样的
在输入框输入待办事项
功能很简单
鼠标点击Add或者键盘按下Enter输出
ShowAll显示全部待办事项
ShowActive显示未完成的待办事项(未划掉的)
ShowCrossed显示已完成的待办事项(划掉的)

配置文件

使用Webpack构建的文件夹如下

React+Redux实现简单的待办事项列表ToDoList

webpack.config.js配置文件

module.exports = {
 entry: {
 index: './src/js/entry.js'
 },
 output: {
 path: './static/dist/',
 publicPath: 'http://localhost:8080/static/dist/',
 filename: '[name].js'
 },
 module: {
 loaders: [
 {
 test: /\.js$/,
 loader: 'babel',
 exclude:/node_modules/,
 query: {
 presets: ['react', 'es2015']
 }
 },
 {
 test: /.less$/,
 loader: 'style!css!less'
 }
 ]
 }
}

package.json的依赖项

{
 "name": "react-demo",
 "version": "1.0.0",
 "description": "",
 "main": "webpack.config.js",
 "scripts": {
 "test": "echo \"Error: no test specified\" && exit 1",
 "diy": "webpack-dev-server --progress --colors --devtool sourcemap"
 },
 "author": "Payson",
 "license": "ISC",
 "devDependencies": {
 "babel-core": "^6.22.1",
 "babel-loader": "^6.2.10",
 "babel-preset-es2015": "^6.22.0",
 "babel-preset-react": "^6.22.0",
 "css-loader": "^0.26.1",
 "jquery": "^3.1.1",
 "less": "^2.7.2",
 "less-loader": "^2.2.3",
 "react": "^15.4.2",
 "react-dom": "^15.4.2",
 "react-redux": "^5.0.2",
 "redux": "^3.6.0",
 "style-loader": "^0.13.1",
 "webpack": "^1.14.0",
 "webpack-dev-server": "^1.16.2"
 }
}

html文件

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>React</title>
</head>
<body>
 <div id="root"></div>
 <script src="http://localhost:8080/static/dist/index.js"></script>
</body> 
</html>

脚本文件

没有细拆文件
直接写在入口文件entry.js了
注释就写在代码里了

require('../less/index.less'); //行间样式受限制不能添加伪类伪元素,所以还是添加了less(css)控制样式
import React from 'react';
import {Component} from 'react'
import ReactDom from 'react-dom';
import {createStore, combineReducers} from 'redux';

class ToDoList extends Component {
 addHandler(){ //添加待办事项的listener
 let Inp = this.refs.Inp; //获取真实DOM的输入value
 if(!Inp.value){ //如果没有输入值,直接返回
 return;
 }
 store.dispatch( //dispatch一个添加项目的action,并传入输入数据
 {
 type: 'ADD_ITEM',
 newItem: Inp.value
 }
 )
 Inp.value = ''; //提交后,清空输入
 Inp.focus(); //重置输入焦点
 }
 toggleHandler(item){ //Action Creator:负责提交切换中划线的action
 store.dispatch(
 {
 type: 'TOGGLE_ITEM',
 changeID: item.ID
 }
 );
 }
 showAllHandler(){ //Action Creator:负责showAll的action
 store.dispatch(
 {
 type: 'SET_FILTER',
 filter: 'SHOW_ALL'
 }
 );
 }
 showActiveHandler(){ //Action Creator:负责showActive的action
 store.dispatch(
 {
 type: 'SET_FILTER',
 filter: 'SHOW_ACTIVE'
 }
 );
 }
 showCrossedHandler(){ //Action Creator:负责showCrossed的action
 store.dispatch(
 {
 type: 'SET_FILTER',
 filter: 'SHOW_CROSSED'
 }
 );
 }
 render(){ //渲染结构样式
 let _this = this; //缓存this
 let state = store.getState(); //缓存store的快照--state
 let {list, option} = state; //解构赋值获取两个子state
 //list是一个数组,内部数组元素是对象表示每一个列表项
 //option是一个字符串,表示当先选择的选项
 switch(option){ //通过判断当前的option字符串来决定是否过滤list数组
 case 'SHOW_ACTIVE':
 list = list.filter(function(item){
 return !item.del;
 });
 break;
 case 'SHOW_CROSSED':
 list = list.filter(function(item){
 return item.del;
 });
 break;
 }
 document.body.addEventListener('keydown', function(e){
 if(e.which == 13){
 _this.addHandler();
 }
 }); //绑定键盘enter事件
 return (
 <div>
 <input type="text" ref="Inp"/> //设置ref属性为了获取真实DOM节点
 <button onClick={_this.addHandler.bind(_this)}>Add</button>
 <ul className="option">
 <li onClick={_this.showAllHandler.bind(_this)}>
 <span style={{textDecoration: option!='SHOW_ALL' ? 'underline' : 'none'}}>ShowAll</span>
 </li>
 <li onClick={_this.showActiveHandler.bind(_this)}>
 <span style={{textDecoration: option!='SHOW_ACTIVE' ? 'underline' : 'none'}}>ShowActive</span>
 </li>
 <li onClick={_this.showCrossedHandler.bind(_this)}>
 <span style={{textDecoration: option!='SHOW_CROSSED' ? 'underline' : 'none'}}>ShowCrossed</span>
 </li> //判断option字符串来决定三个选项的样式
 </ul>
 <ul className="list">
 {
 list.map(function(item, index){ //通过list数组map映射为虚拟DOM节点
 return <li key={index}>
 <span style={{textDecoration: item.del ? 'line-through': 'none'}} 
 onClick={_this.toggleHandler.bind(_this, item)}>{item.item}</span>
 </li>
 })
 }
 </ul>
 </div>
 )
 }
}
const list = (state = [], action) => { //list-reducer
 switch(action.type){
 case 'ADD_ITEM':
 return [
 ...state, 
 {
 item: action.newItem, //列表项内容
 ID: state.length, //列表项ID
 del: false //列表项是否已划掉
 }
 ];
 case 'TOGGLE_ITEM':
 return state.map((item)=>{
 return Object.assign({},item,{
 del: action.changeID == item.ID ? !item.del : item.del
 });
 });
 default:
 return state;
 }
}
const option = (state = 'SHOW_ALL', action) => { //option-reducer
 switch(action.type){
 case 'SET_FILTER':
 return action.filter;
 default:
 return state;
 }
}
const reducer = combineReducers({list, option}); //利用redux库API-combineReducers()合并reducer
const store = createStore(reducer); //利用redux库API-createStore()创建store
const render = () => { //自定义的渲染函数
 ReactDom.render(
 <ToDoList/>,
 document.getElementById('root')
 );
}
store.subscribe(render); //绑定render函数,每次state更新时执行
render(); //首次渲染

样式文件

index.less文件加一些样式控制

.option {
 list-style-type: none;
 padding: 0;
 margin-top: 5px;
 font-size: 13px;
 li {
 float: left;
 margin-right: 15px;
 span {
 cursor: pointer;
 font-weight: bold;
 }
 }
 &::after {
 content: '';
 display: block;
 clear: both;
 }
}
.list {
 li {
 span {
 &:hover {
 color: #f40;
 cursor: pointer;
 }
 &::selection {
 color: #000;
 background-color: #fff;
 }
 }
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
关于文本限制字数的js代码
Apr 02 Javascript
jQuery 页面载入进度条实现代码
Feb 08 Javascript
Javascript事件热键兼容ie|firefox
Dec 30 Javascript
select标记美化--JS式插件、后期加载
Apr 01 Javascript
jQuery根据纬度经度查看地图处理程序
May 08 Javascript
js判断字符长度以及中英文数字等
Dec 31 Javascript
JS文本获得焦点清除文本文字的示例代码
Jan 13 Javascript
纯css实现窗户玻璃雨滴逼真效果
Aug 23 Javascript
jQuery插件实现带圆点的焦点图片轮播切换
Jan 18 Javascript
jQuery ztree实现动态树形多选菜单
Aug 12 Javascript
D3.js中强制异步文件读取同步的几种方法
Feb 06 Javascript
详细谈谈JavaScript中循环之间的差异
Aug 23 Javascript
JS回调函数简单易懂的入门实例分析
Sep 29 #Javascript
在vue中根据光标的显示与消失实现下拉列表
Sep 29 #Javascript
js 下拉菜单点击旁边收起实现(踩坑记)
Sep 29 #Javascript
微信小程序 行的删除和增加操作实现详解
Sep 29 #Javascript
微信小程序 轮播图实现原理及优化详解
Sep 29 #Javascript
为nuxt项目写一个面包屑cli工具实现自动生成页面与面包屑配置
Sep 29 #Javascript
React-redux实现小案例(todolist)的过程
Sep 29 #Javascript
You might like
php数组的概述及分类与声明代码演示
2013/02/26 PHP
PHP格式化MYSQL返回float类型的方法
2016/03/30 PHP
PHP使用xpath解析XML的方法详解
2017/05/20 PHP
关于ThinkPhp 框架表单验证及ajax验证问题
2017/07/19 PHP
PHP pthreads v3使用中的一些坑和注意点分析
2020/02/21 PHP
Javascript简单实现面向对象编程继承实例代码
2015/11/27 Javascript
浅析JavaScript Array和string的转换(推荐)
2016/05/20 Javascript
jQuery日程管理插件fullcalendar使用详解
2017/01/07 Javascript
详解Vue 实例中的生命周期钩子
2017/03/21 Javascript
node使用UEditor富文本编辑器的方法实例
2017/07/11 Javascript
vue拖拽组件使用方法详解
2018/12/01 Javascript
Vue $mount实战之实现消息弹窗组件
2019/04/22 Javascript
vue-i18n实现中英文切换的方法
2020/07/06 Javascript
[02:43]DOTA2英雄基础教程 德鲁伊
2014/01/13 DOTA
Django查找网站项目根目录和对正则表达式的支持
2015/07/15 Python
Python中str.format()详解
2017/03/12 Python
Python生成数字图片代码分享
2017/10/31 Python
python去掉空白行的多种实现代码
2018/03/19 Python
python3模块smtplib实现发送邮件功能
2018/05/22 Python
浅谈PYTHON 关于文件的操作
2019/03/19 Python
使用Python脚本从文件读取数据代码实例
2020/01/19 Python
python中关于数据类型的学习笔记
2020/07/19 Python
AmazeUI 模态窗口的实现代码
2020/08/18 HTML / CSS
中国综合性网上购物商城:当当(网上卖书起家)
2016/11/16 全球购物
Bally美国官网:经典瑞士鞋履、手袋及配饰奢侈品牌
2018/05/18 全球购物
俄罗斯奢侈品牌衣服、鞋子和配饰的在线商店:INTERMODA
2020/07/17 全球购物
区域销售经理职责
2013/12/22 职场文书
班主任工作年限证明
2014/01/12 职场文书
煤矿班组长竞聘书
2014/03/31 职场文书
爱国卫生月活动总结范文
2014/04/25 职场文书
党员承诺书范文
2014/05/19 职场文书
2014年车间工作总结
2014/11/21 职场文书
入党转正申请书范文
2019/05/20 职场文书
Python实现byte转integer
2021/06/03 Python
关于python pygame游戏进行声音添加的技巧
2021/10/24 Python
tomcat默认最大连接数及相关调整方法
2022/05/06 Servers