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树形控件脚本代码
Jul 24 Javascript
js onpropertychange输入框 事件获取属性
Mar 26 Javascript
ExtJS 2.0实用简明教程 之获得ExtJS
Apr 29 Javascript
window.onload 加载完毕的问题及解决方案(上)
Jul 09 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 图片库
Jan 09 Javascript
Vue表单实例代码
Sep 05 Javascript
vuejs2.0实现一个简单的分页示例
Feb 22 Javascript
JS实现的缓冲运动效果示例
Apr 30 Javascript
微信小程序实现红包雨功能
Jul 11 Javascript
JS中注入eval, Function等系统函数截获动态代码
Apr 03 Javascript
浅析vue cli3 封装Svgicon组件正确姿势(推荐)
Apr 27 Javascript
JavaScript实现矩形块大小任意缩放
Aug 25 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
CodeIgniter图像处理类的深入解析
2013/06/17 PHP
javascript静态的url如何传递
2007/05/03 Javascript
JavaScript 变量基础知识
2009/11/07 Javascript
javascript 闭包
2011/09/15 Javascript
JavaScript中的onerror事件概述及使用
2013/04/01 Javascript
jqeury-easyui-layout问题解决方法
2014/03/24 Javascript
window.returnValue使用方法示例介绍
2014/07/03 Javascript
详解JavaScript正则表达式之RegExp对象
2015/12/13 Javascript
底部悬浮通栏可以关闭广告位的实现方法
2016/06/01 Javascript
Js遍历键值对形式对象或Map形式的方法
2016/08/08 Javascript
jQuery实现点击查看大图并以弹框的形式居中
2016/08/08 Javascript
微信小程序去哪里找 小程序到底如何使用(附小程序名单)
2017/01/09 Javascript
js仿淘宝评价评分功能
2017/02/28 Javascript
jQuery插件HighCharts绘制的2D堆柱状图效果示例【附demo源码下载】
2017/03/14 Javascript
详解vue表单——小白速看
2018/04/08 Javascript
nodeJS模块简单用法示例
2018/04/21 NodeJs
原生js实现Flappy Bird小游戏
2018/12/24 Javascript
最简单的vue消息提示全局组件的方法
2019/06/16 Javascript
layui 数据表格复选框实现单选功能的例子
2019/09/19 Javascript
小程序跨页面交互的作用与方法详解
2020/01/07 Javascript
VUE实现自身整体组件销毁的示例代码
2020/01/13 Javascript
使用JavaScript获取Django模板指定键值数据
2020/05/27 Javascript
vue 动态添加class,三个以上的条件做判断方式
2020/11/02 Javascript
[05:15]2018年度CS GO社区贡献奖-完美盛典
2018/12/16 DOTA
python3之微信文章爬虫实例讲解
2017/07/12 Python
python自定义函数实现最大值的输出方法
2019/07/09 Python
浅谈OpenCV中的新函数connectedComponentsWithStats用法
2020/07/05 Python
HTML5 图片悬停放大的实现代码示例
2019/12/04 HTML / CSS
在网上学习全世界最好的课程:Coursera
2017/11/07 全球购物
进口业务员岗位职责
2014/04/06 职场文书
村委会换届选举方案
2014/05/03 职场文书
小学秋季运动会报道稿
2014/09/30 职场文书
2014年幼儿园个人工作总结
2014/11/10 职场文书
学雷锋广播稿大全
2015/08/19 职场文书
导游词之日本富士山
2020/01/06 职场文书
CSS SandBox应用场景及常见问题
2022/06/25 HTML / CSS