react项目基本实践
localstorage 是浏览器端持久化方案之一,HTML5标准增加的技术
localstorage 是为了存储交互的数据,如json。
数据存储就是键值在不同域名下的存储
不同浏览器对单个域名下存储数据的长度支持不同,有的最多支持2MB如下
2 store.js其中sessionstorage是会话级别的存储,及就是临时存储。
localstorage 支持的浏览器最多而sessionstorage支持的浏览器却较少。
下面的indexedDB和web SQL 是和数据库存储有关,indexedDB:
一个域一个datatable
key-value 检索方式
建立在关系型数据库上,具有索引表,游标,事务等概念。
store.js是一个兼容所有浏览器的localstorage包装器,不需要借助cookie或者flash,store.js会根据浏览器自动选择使用localstorage,globalstorage或者 userdata来实现本地存储功能。
安装
npm i store --save //此处是在部署包中添加
介绍和相关说明
https://github.com/marcuswestin/store.js/
测试代码如下
var store = require('store') //导入模块store.set('user','test') //设置key,value值console.log(store.get('user')) //获取key,value值store.remove('user') //移除key,及其和对应的valueconsole.log(store.get('user','aaaaa')) //查询不存在时使用默认 store.clearAll() //清除所有 store.set('test','test') // 设置 store.each(function (value,key) { //遍历key和value,注意,此处是value,key console.log(key,'====',value)})
3 antd组件相关介绍结果如下
用户提交数据,需要表单控件,而这种用户提交的数据显示就是view层需要完成的功能,对于react来说是一个空间,但这些控件需要用户看到,为了美观,引入了antd。
ant Design 蚂蚁金服开源的reactUI库
antd官网
https://ant.design/index-cn
官方文档
https://ant.design/docs/react/introduce-cn
1 Input组件
使用一种较为简单的组件Input来完成输入功能
地址如下
https://ant.design/components/input-cn/
基础代码如下
import { Input } from 'antd';ReactDOM.render(<Input placeholder="Basic usage" />);
2 Card 组件输入框属性
addonAfter 带标签的 input,设置后置标签 string|ReactNode
addonBefore 带标签的 input,设置前置标签 string|ReactNode
placeholder="Basic usage" 占位词
size="smail" 小输入框,改为large就是大输入框
显示一个较为友好的界面
地址如下
https://ant.design/components/card-cn/
3 CheckBox多选框相关映射如下,最后面的style={{width:300}} 表示样式,其是指宽度
相关处理可以使用checkbox组件来完成,选中和取消选中
https://ant.design/components/checkbox-cn/#header
基础代码如下
import { Checkbox } from 'antd';function onChange(e) { console.log(`checked = ${e.target.checked}`); //打印选择结果 }//onChange 选中,取消时触发回调函数.checked 表示是否选中,若选中,则为true,未选中,则为false ReactDOM.render(<Checkbox onChange={onChange}>Checkbox</Checkbox>, mountNode);
4 栅格显示
https://ant.design/components/grid-cn/
布局上,ant design 和 bootstrap很像,都使用一套栅格系统,使用24栅格,也就是每一个内部都切分成24份
import React from 'react';import {Checkbox,Card,Row,Col} from 'antd';import 'antd/lib/row/style';import 'antd/lib/card/style';import 'antd/lib/Col/style';//一条待办事宜export default props => ( <Card style={{width:600}}> <Row> <Col span="4"><Checkbox /></Col> <Col span="20">{props.todo.title}</Col> </Row> </Card> );
5 Select 对的筛选和显示
过滤是指,过滤什么状态的待办事宜
应该有3种选择:未完成,完成的和全部的,和后面的completed 参数结合使用。使用select模块来完成选择框的使用,相关地址如下
https://ant.design/components/select-cn/
import { Select } from 'antd';const { Option } = Select;function onChange(value) { console.log(`selected ${value}`);}function onBlur() { console.log('blur');}function onFocus() { console.log('focus');}function onSearch(val) { console.log('search:', val);}ReactDOM.render( <Select showSearch style={{ width: 200 }} placeholder="Select a person" optionFilterProp="children" onChange={onChange} onFocus={onFocus} onBlur={onBlur} onSearch={onSearch} filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 } > <Option value="jack">Jack</Option> <Option value="lucy">Lucy</Option> <Option value="tom">Tom</Option> </Select>,
4 Map 用于数据的持久化处理
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map
相关测试代码如下
m=new Map();m.set(1,'a'); //定义key和value m.set(2,'b');m.set(3,'c');console.log(m); //查看结果 let t=m.forEach((value,key)=> [key,value]); // 此处无返回值 console.log(t); t=[...m.values()].map(item => item+100); // 对可迭代对象的解构,并进行处理,map 立即返回console.log(t)
5 状态管理Mobx结果如下
Redux 和 Mobx
上述项目中基本功能都实现了。但state的控制显得有些麻烦。
社区提供了状态管理库,有Redux和Mobx
Redux 代码优秀,使用严格的函数式编程思想,学习曲线陡峭,小项目使用的优势不明显
Mobx,稳定,使用简单方便,适合中小型项目的使用,使用面向对象的方式学习,容易学习和接受,现在,使用也非常广泛。
Mobx 官网
https://mobx.js.org/
中文网
https://cn.mobx.js.org/
Mobx实现了观察者模式
观察者模式
观察者观察某个目标,目标对象(Obserable)发生了变化,就会通知自己内部注册的观察者Observer
观察者模式,及就是一对多的广播模式
首先,需要观察者和被观察者
目标对象,及被观察者,obserable 指的是数据的源头,被观察者可以有多个,同时观察这个变化。只要被观察的对象有变化,则便会导致观察者做出相应的操作,state和props变化是我们关心的,
6 异步处理和打包部署@computed 的使用
mobx还提供了一个装饰器@computed,可以使用在任意类上属性的getter上使用,其所依赖的值发生了变化就会重新计算,否则直接返回到上次计算的结果。起到了缓存的作用,可直接用于filter的判断上,通过传入的值来进行相关匹配进而进行返回或计算。
异步处理axios
官网
http://www.axios-js.com/zh-cn/docs/
基础代码如下
// 为给定 ID 的 user 创建请求axios.get('/user?ID=12345') .then(function (response) { //返回成功执行的代码 console.log(response); }) .catch(function (error) { //返回失败执行的代码 console.log(error); });axios.post('/user', { //下面的两个表示key和value的值传递到服务器端 firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
二 业务需求和基本代码实现1 需求分析
2 代码实现1 服务层实现分层
视图层,负责显示数据,每一个react 组件一个js文件。服务层,负责业务数据处理逻辑,命名为xxxService.js。
model层,负责数据,这里使用localstore。
注意:未特别说明,这些层的代码都在项目跟目录的src中
此处仍使用上一节项目包,相关介绍如下
https://blog.51cto.com/11233559/2443713
项目包如下
链接:https://pan.baidu.com/s/1C-ZY9rWU-8ZugE4EwVveWw
提取码:744p具体项目介绍。请查看上一节 react项目基础
构建TodoService类,文件名为service.js,此目前放置在src的目录下
import store from 'store' export default class TodoService{ static NAMESPACE="todo" //定义存储前缀 todos=[]; //定义存储容器 // 创建todo create(title) { //定义函数,用于处理创建和存储数据 const todo = { //定义value类型 key: TodoService.NAMESPACE+(new Date()).valueOf(), /*毫秒时间戳*/ title :title, //定义相关类型 completed: false //定义数据状态 } this.todos.push(todo); //存储至容器中 //持久化处理 store.set(todo.key,todo); return todo }}
2 创建数据来源
title 从哪里来
从浏览器端,用户提交,也就是视图层提供的用户提交的文本框,通过Card和 INput来处理数据的接受和启动问题。
创建create.js 文件,其路径暂时存放与src目录下,此安装包antd默认已经在包中存在,若未安装,则需使用npm i antd进行安装
使用这两个组件组合,基础测试代码如下
import React from 'react';import { Card,Input } from 'antd';import 'antd/lib/card/style' //导入相关样式表 import 'antd/lib/Input/style'//缺省导出无状态组件react 中 export default props => ( <Card title="请输入" style={{ width: 300 }}> <Input /> <p>测试代码</p> </Card>)
开放接口层代码 index.js 相关代码如下
import React from 'react'; import ReactDOM from 'react-dom';import Create from './create' //引入模块 class Root extends React.Component { render(){ return (<div> hello world <hr/> <Create /> //引入显示 </div>) }}ReactDOM.render(<Root/>,document.getElementById('root'));
结果如下
输入框处理,为了能让用户提交信息,我们需要是哦有那个接受回车键的事件触发提交信息,键盘按下是一个事件,在Input中使用onPressEnter来收集键盘按下回车键的触发指令。
此处表明后面跟的是一个函数
修改如下
打印回车数据,其是通过event.target.value获取到Input框中的数据的
import React from 'react';import { Card,Input } from 'antd';import 'antd/lib/card/style' //导入相关样式表 import 'antd/lib/Input/style'//缺省导出无状态组件react 中 export default props => ( <Card title="请输入" style={{ width: 300 }}> <Input onPressEnter={(event) =>{console.log(event.target.value)}}/> {/*此处使用event表示触发的事件,其表示获取到用户数据*/} <p>测试代码</p> </Card>)
拿到用户数据,应该调用todoservice的create,但不适合在create.js中进行调用,通过props 进行组件之间的数据共享。使用props
Root组件中创建一个handleCreate(title),用于处理Input中的数据传输到后台,通过调用后台的函数方法来完成。index.js组件内容
import React from 'react';import ReactDOM from 'react-dom';import Create from './create'import TodoService from './service'class Root extends React.Component { constructor(props) { super(props); this.service = new TodoService(); //初始化类对象 } handleCreate(title){ console.log(title.target.value) //打印create.js中传输的数据 this.service.create(title.target.value) //调用todoserver的方法完成数据的持久化操作 } render(){ return (<div> hello world <hr/> <Create onCreate={this.handleCreate.bind(this)} /> {/*通过此处的传递将oncrete属性传递到后端用于相关的处理*/} </div>) }}ReactDOM.render(<Root/>,document.getElementById('root'));
create.js组件内容
import React from 'react';import { Card,Input } from 'antd';import 'antd/lib/card/style' //导入相关样式表 import 'antd/lib/Input/style'//缺省导出无状态组件react 中 export default props => ( <Card title="请输入" style={{ width: 300 }}> <Input onPressEnter={(event) => props.onCreate(event)}/> {/*此处通过外部的index.js中的数据传递 将handleCreate 传递过来进行相关的处理操作,其被作为props携带进入此处参与相关的处理和调度操作*/} <p>测试代码</p> </Card>)
3 创建添加数据显示问题结果如下
添加数据完成后显示问题,需要创建用于列表显示结果,需要创建的包如下,其仍然再src目录下:Todo.js
import React from 'react'import { Checkbox,Card,Row,Col } from 'antd'import 'antd/lib/card/style'import 'antd/lib/row/style'import 'antd/lib/card/style'import 'antd/lib/checkbox/style'export default props =>( <Card> <Row> <Col span={4}><Checkbox /> }/></Col> <Col span={20}>{props.todo.title}</Col> </Row> </Card>)
index.js代码如下
import React from 'react';import ReactDOM from 'react-dom';import Create from './create'import TodoService from './service'import Todo from './Todo';class Root extends React.Component { constructor (props) { super(props); this.service=new TodoService(); this.state={todos:this.service.todos} //变化引起的刷新操作 } handleCreate (event) { this.service.create(event); this.setState({todos:this.service.todos}); } render(){ return( <div> <Create onCreate={this.handleCreate.bind(this)} /> {/*自己定义一个属性,处理props事件的*/} {/*完成数据的显示*/} {/* {this.service.todos.forEach} 虽然遍历,但不返回任何结果 */} {this.service.todos.map(item=> <Todo key={item.key} todo={item} />)} {/*调用todo进行处理相关的函数问题,map后返回新的容器*/} </div> ); } } ReactDOM.render(<Root />,document.getElementById('root')); //NewRoot(props)
结果如下
4 数据持久化操作每添加一个元素,其会显示该元素。但其在网页刷新后其会不存在,但在localstorage中存储所有的数据,因此需要处理装载数据的函数。
修改代码如下
import store from 'store' export default class TodoService{ static NAMESPACE="todo" //定义存储前缀 todos= new Map(); //定义存储容器 // 创建todo constructor(){ this.load(); } load(){ store.each((value,key) => { if (key.startsWith(TodoService.NAMESPACE)) this.todos.set(key,value) } )} create(title) { //定义函数,用于处理创建和存储数据 const todo = { //定义value类型 key: TodoService.NAMESPACE+(new Date()).valueOf(), /*毫秒时间戳*/ title :title, //定义相关类型 completed: false //定义数据状态 } this.todos.set(todo.key,todo); //存储至容器中 //持久化处理 store.set(todo.key,todo); return todo }}
index.js 代码修改结果如下
import React from 'react';import ReactDOM from 'react-dom';import Create from './create'import TodoService from './service'import Todo from './Todo';import Filter from './filter'import { set } from 'mobx';class Root extends React.Component { constructor (props) { super(props); this.service=new TodoService(); } handleCreate (event) { this.service.create(event); this.setState({todos:this.service.todos}); } render(){ return( <div> <Create onCreate={this.handleCreate.bind(this)} /> {/*自己定义一个属性,处理props事件的*/} {/*完成数据的显示*/} {[...this.service.todos.values()].map( item=> <Todo todo={item}/>)} {/*调用todo进行处理相关的函数问题,map后返回新的容器*/} </div> ); } } ReactDOM.render(<Root />,document.getElementById('root')); //NewRoot(props) // Test(Root)(props)
5 后端状态的修改实现最终结果如下
无论如何刷新,其最终结果都将会完全显示
后端 completed 状态为false和true的实现,其主要是通过checkbox 实现
Todo.js修改代码如下
import React from 'react';import {Checkbox,Card,Row,Col} from 'antd';import 'antd/lib/row/style';import 'antd/lib/card/style';import 'antd/lib/Col/style';//一条待办事宜export default props => ( <Card style={{width:600}}> <Row> <Col span="4"><Checkbox onChange={(event) =>props.onChage(event.target.checked,props.todo.key)}/></Col> <Col span="20">{props.todo.title}</Col> </Row> </Card> );
后端service代码
import store from 'store' export default class TodoService{ static NAMESPACE="todo" //定义存储前缀 todos= new Map(); //定义存储容器 // 创建todo constructor(){ this.load(); } load(){ store.each((value,key) => { if (key.startsWith(TodoService.NAMESPACE)) this.todos.set(key,value) } )} create(title) { //定义函数,用于处理创建和存储数据 const todo = { //定义value类型 key: TodoService.NAMESPACE+(new Date()).valueOf(), /*毫秒时间戳*/ title :title, //定义相关类型 completed: false //定义数据状态 } this.todos.set(todo.key,todo); //存储至容器中 //持久化处理 store.set(todo.key,todo); return todo } todochaService(key,checked){ let todo=this.todos.get(key) //获取对应的值 todo.completed=checked; //赋值 console.log(todo.completed,checked) this.todos.set(key,todo) //刷新map store.set(key,todo) //刷新store }}
index.js端代码如下
import React from 'react';import ReactDOM from 'react-dom';import Create from './create'import TodoService from './service'import Todo from './Todo';class Root extends React.Component { constructor (props) { super(props); this.service=new TodoService(); } handleCreate (event) { this.service.create(event); this.setState({todos:this.service.todos}); } handleChange(checked,key) //此处主要是用于处理后端的completed的变化,因此需要传递key和对应的触发事件的值 { console.log(key,checked) //打印key和对应的值 this.service.todochaService(key,checked) } render(){ return( <div> <Create onCreate={this.handleCreate.bind(this)} /> {/*自己定义一个属性,处理props事件的*/} {/*完成数据的显示*/} {[...this.service.todos.values()].map( item=> <Todo onChage={this.handleChange.bind(this)} key={item.key} todo={item}/>)} {/*调用todo进行处理相关的函数问题,map后返回新的容器*/} </div> ); } } ReactDOM.render(<Root />,document.getElementById('root')); //NewRoot(props) // Test(Root)(props)
6 过滤查询实现结果如下
创建相关过滤模块,如下 仍然临时存储于src中,创建名为Filter.js,如下
Filter.js测试返回结果
import React from 'react';import { Select } from 'antd';const { Option } = Select;import 'antd/lib/select/style';export default props => ( <Select showSearch style={{ width: 200 }} defaultValue="uncompleted" onChange={(event) =>console.log(event)} > <Option value="uncompleted">未完成</Option> <Option value="completed">已完成</Option> <Option value="all">全部</Option> </Select>);
其中 defaultValue 用于显示默认设置
onChange={(event) =>console.log(event)} 用于查看选择引起的调度
<Option value="uncompleted">未完成</Option> 中中间的未完成用于显示,而value用于实际触发的传值。index.js中添加相关配置如下
import React from 'react';import ReactDOM from 'react-dom';import Create from './create'import TodoService from './service'import Todo from './Todo';import Filter from './filter'class Root extends React.Component { constructor (props) { super(props); this.service=new TodoService(); } handleCreate (event) { this.service.create(event); this.setState({todos:this.service.todos}); } handleChange(checked,key) //此处主要是用于处理后端的completed的变化,因此需要传递key和对应的触发事件的值 { console.log(key,checked) //打印key和对应的值 this.service.todochaService(key,checked) } render(){ return( <div> <Create onCreate={this.handleCreate.bind(this)} /> {/*自己定义一个属性,处理props事件的*/} {/*完成数据的显示*/} <Filter /> {[...this.service.todos.values()].map( item=> <Todo onChage={this.handleChange.bind(this)} key={item.key} todo={item}/>)} {/*调用todo进行处理相关的函数问题,map后返回新的容器*/} </div> ); } } ReactDOM.render(<Root />,document.getElementById('root')); //NewRoot(props) // Test(Root)(props)
结果如下
选择不同的选项会导致不同的触发结果,此处便可作为其条件进行相关操作
配置触发改变和相关显示
index.js
import React from 'react';import ReactDOM from 'react-dom';import Create from './create'import TodoService from './service'import Todo from './Todo';import Filter from './filter'class Root extends React.Component { constructor (props) { super(props); this.service=new TodoService(); this.state={todos:this.service.todos} this.state={filter:"uncompleted"} } handleCreate (event) { this.service.create(event); this.setState({todos:this.service.todos}); } handleChange(checked,key) //此处主要是用于处理后端的completed的变化,因此需要传递key和对应的触发事件的值 { console.log(key,checked) //打印key和对应的值 this.service.todochaService(key,checked) } handleFliter(value){ this.setState({filter:value}) this.state.filter=value; //修改状态 console.log(this.state.filter) } render(){ return( <div> <Create onCreate={this.handleCreate.bind(this)} /> {/*自己定义一个属性,处理props事件的*/} {/*完成数据的显示*/} <Filter onFilter={this.handleFliter.bind(this)}/> {[...this.service.todos.values()].filter(item => { let fs=this.state.filter; if (fs==="uncompleted") if (item.completed===true) return false else return true if (fs=== "completed") if (item.completed===true) return true else return false else return true }).map(item => <Todo onChage={this.handleChange.bind(this)} key={item.key} todo={item}/>)} {/*调用todo进行处理相关的函数问题,map后返回新的容器*/} </div> ); } } ReactDOM.render(<Root />,document.getElementById('root')); //NewRoot(props) // Test(Root)(props)
修改filter.js如下
import React from 'react';import { Select } from 'antd';const { Option } = Select;import 'antd/lib/select/style';export default props => ( <Select showSearch style={{ width: 200 }} defaultValue="uncompleted" onChange={event => props.onFilter(event)}> <Option value="uncompleted">未完成</Option> <Option value="completed">已完成</Option> <Option value="all">全部</Option> </Select>);
7 调整代码布局结果如下
调整代码布局,将显示层(view)代码调整到component目录中包括create.js,filter.js,Todo.js和TodoApp.js(此处是将index.js的数据悉数移动到形成的),将后面的service层的代码调整到service中,如下
index.js 和 TodoApp.js修改如下
TodoApp.js
import React from 'react';import Create from './create'import TodoService from '../service/service'import Todo from './Todo';import Filter from './filter'export default class Root extends React.Component { constructor (props) { super(props); this.service=new TodoService(); this.state={todos:this.service.todos} this.state={filter:"uncompleted"} } handleCreate (event) { this.service.create(event); this.setState({todos:this.service.todos}); } handleChange(checked,key) //此处主要是用于处理后端的completed的变化,因此需要传递key和对应的触发事件的值 { console.log(key,checked) //打印key和对应的值 this.service.todochaService(key,checked) } handleFliter(value){ this.setState({filter:value}) this.state.filter=value; //修改状态 console.log(this.state.filter) } render(){ return( <div> <Create onCreate={this.handleCreate.bind(this)} /> {/*自己定义一个属性,处理props事件的*/} {/*完成数据的显示*/} <Filter onFilter={this.handleFliter.bind(this)}/> {[...this.service.todos.values()].filter(item => { let fs=this.state.filter; if (fs==="uncompleted") if (item.completed===true) return false else return true if (fs=== "completed") if (item.completed===true) return true else return false else return true }).map(item => <Todo onChage={this.handleChange.bind(this)} key={item.key} todo={item}/>)} {/*调用todo进行处理相关的函数问题,map后返回新的容器*/} </div> ); } }
index.js 如下
import ReactDOM from 'react-dom';import React from 'react';import Root from './compoent/TodoApp';ReactDOM.render(<Root />,document.getElementById('root')); //NewRoot(props) // Test(Root)(props)
8 总结
渲染的事情归TodoApp负责,并管理所有的状态。
create负责显示文本框,接受用户输入的待办事宜。
TOdo,负责每一条数据的显示和check变化
filter,主要负责一个状态的filter的切换
三 服务改进1 状态监控改进service.js
todoservice 负责业务的处理,为了简单,把数据处理也放在此处
状态state的控制和修改有些麻烦,需要改进
程序修改
TodoApp观察TodoService中的变量的变化,如todos。可通过obserable 进行定义被检查对象,通过 observer 进行检测处理。
之前的TodoApp是同构service关联到TodoService实例的,现在修改成了通过JSX元素属性的方式传递,因此,需要修改index.js和TodoApp及后端。
service.js 修改如下
import store from 'store' import { observable } from "mobx";export default class TodoService{ static NAMESPACE="todo" //定义存储前缀 @observable todos= new Map(); //定义存储容器 // 创建todo constructor(){ this.load(); } load(){ store.each((value,key) => { if (key.startsWith(TodoService.NAMESPACE)) this.todos.set(key,value) } )} create(title) { //定义函数,用于处理创建和存储数据 const todo = { //定义value类型 key: TodoService.NAMESPACE+(new Date()).valueOf(), /*毫秒时间戳*/ title :title, //定义相关类型 completed: false //定义数据状态 } this.todos.set(todo.key,todo); //存储至容器中 //持久化处理 store.set(todo.key,todo); return todo } todochaService(key,checked){ let todo=this.todos.get(key) //获取对应的值 todo.completed=checked; //赋值 console.log(todo.completed,checked) this.todos.set(key,todo) //刷新map store.set(key,todo) //刷新store }}
index.js修改如下
import ReactDOM from 'react-dom';import React from 'react';import Root from './compoent/TodoApp';import TodoService from './service/service'const service=new TodoService()ReactDOM.render(<Root service={service} />,document.getElementById('root')); //通过外部传值的方式实现
TodoApp.js如下
import React from 'react';import Create from './create'import Todo from './Todo';import Filter from './filter'import {observer} from 'mobx-react';@observerexport default class Root extends React.Component { constructor (props) { super(props); this.state={filter:"uncompleted"} } handleCreate (event) { this.props.service.create(event); //此处通过index.js的方法进行传值 } handleChange(checked,key) //此处主要是用于处理后端的completed的变化,因此需要传递key和对应的触发事件的值 { console.log(key,checked) //打印key和对应的值 this.props.service.todochaService(key,checked) //此处也是 } handleFliter(value){ this.setState({filter:value}) this.state.filter=value; //修改状态 console.log(this.state.filter) } render(){ return( <div> <Create onCreate={this.handleCreate.bind(this)} /> {/*自己定义一个属性,处理props事件的*/} {/*完成数据的显示*/} <Filter onFilter={this.handleFliter.bind(this)}/> {[...this.props.service.todos.values()].filter(item => { let fs=this.state.filter; if (fs==="uncompleted") if (item.completed===true) return false else return true if (fs=== "completed") if (item.completed===true) return true else return false else return true }).map(item => <Todo onChage={this.handleChange.bind(this)} key={item.key} todo={item}/>)} {/*调用todo进行处理相关的函数问题,map后返回新的容器*/} </div> ); } }
2 复选框改变列表不刷新问题
复选框改变列表不刷新问题
运行一切为正常,就是有一点不方便,及checkbox点击后,其不会发生重绘操作。
checkbox变化导致了TodoService 的todochaService 函数调用,修改相关属性,但此处todos并未发生变化,只是修改其内部元素而已,解决方式是手动修改todos,使其发生重绘。
import store from 'store' import { observable } from "mobx";export default class TodoService{ static NAMESPACE="todo" //定义存储前缀 @observable todos= new Map(); //定义存储容器 // 创建todo constructor(){ this.load(); } load(){ store.each((value,key) => { if (key.startsWith(TodoService.NAMESPACE)) this.todos.set(key,value) } )} create(title) { //定义函数,用于处理创建和存储数据 const todo = { //定义value类型 key: TodoService.NAMESPACE+(new Date()).valueOf(), /*毫秒时间戳*/ title :title, //定义相关类型 completed: false //定义数据状态 } this.todos.set(todo.key,todo); //存储至容器中 //持久化处理 store.set(todo.key,todo); return todo } todochaService(key,checked){ let todo=this.todos.get(key) //获取对应的值 todo.completed=checked; //赋值 console.log(todo.completed,checked) this.todos.set(key,todo) //刷新map store.set(key,todo) //刷新store let temp=this.todos; this.todos = ()=>{}; this.todos=temp; }}
3 过滤数据方法调整结果如下
能够将过滤数据的filter函数后移动到TodoService中。
在TodoService中提供todos属性的getter,此处可直接将方法当成属性来调用
相关修改如下TodoApp.js修改如下
import React from 'react';import Create from './create'import Todo from './Todo';import Filter from './filter'import {observer} from 'mobx-react';@observerexport default class Root extends React.Component { constructor (props) { super(props); } handleCreate (event) { this.props.service.create(event); } handleChange(checked,key) //此处主要是用于处理后端的completed的变化,因此需要传递key和对应的触发事件的值 { console.log(key,checked) //打印key和对应的值 this.props.service.todochaService(key,checked) } handleFliter(value){ this.props.service.setFilterState(value) } render(){ return( <div> <Create onCreate={this.handleCreate.bind(this)} /> {/*自己定义一个属性,处理props事件的*/} {/*完成数据的显示*/} <Filter onFilter={this.handleFliter.bind(this)}/> {this.props.service.todos.map(item => <Todo onChage={this.handleChange.bind(this)} key={item.key} todo={item}/>)} </div> ); } }
修改代码如下
service.js修改如下
import store from 'store' import { observable,computed } from "mobx";export default class TodoService{ static NAMESPACE="todo" //定义存储前缀 @observable _todos= new Map(); //定义存储容器 @observable filter="uncompleted" //此处定义filter setFilterState(value){ this.filter = value; //需要修改此处 } @computed //此处会加快响应速率 get todos(){ return [...this._todos.values()] .filter(item => { let fs=this.filter; if (fs==="uncompleted") if (item.completed===true) return false else return true if (fs=== "completed") if (item.completed===true) return true else return false else return true }); } // 创建todo constructor(){ this.load(); } load(){ store.each((value,key) => { if (key.startsWith(TodoService.NAMESPACE)) this._todos.set(key,value) } )} create(title) { //定义函数,用于处理创建和存储数据 const todo = { //定义value类型 key: TodoService.NAMESPACE+(new Date()).valueOf(), /*毫秒时间戳*/ title :title, //定义相关类型 completed: false //定义数据状态 } this._todos.set(todo.key,todo); //存储至容器中 //持久化处理 store.set(todo.key,todo); return todo } todochaService(key,checked){ let todo=this._todos.get(key) //获取对应的值 todo.completed=checked; //赋值 console.log(todo.completed,checked) this._todos.set(key,todo) //刷新map store.set(key,todo) //刷新store let temp=this._todos; this._todos = ()=>{}; this._todos=temp; } }
4 处理输入待办事宜自动刷新问题
import store from 'store' import { observable,computed } from "mobx";export default class TodoService{ static NAMESPACE="todo" //定义存储前缀 @observable _todos= new Map(); //定义存储容器 @observable filter="uncompleted" //此处定义filter setFilterState(value){ this.filter = value; //需要修改此处 } @computed get todos(){ return [...this._todos.values()] .filter(item => { let fs=this.filter; if (fs==="uncompleted") if (item.completed===true) return false else return true if (fs=== "completed") if (item.completed===true) return true else return false else return true }); } flush (){ //强制刷新步骤 let temp=this._todos; this._todos = ()=>{}; this._todos=temp; } // 创建todo constructor(){ this.load(); } load(){ store.each((value,key) => { if (key.startsWith(TodoService.NAMESPACE)) this._todos.set(key,value) } )} create(title) { //定义函数,用于处理创建和存储数据 const todo = { //定义value类型 key: TodoService.NAMESPACE+(new Date()).valueOf(), /*毫秒时间戳*/ title :title, //定义相关类型 completed: false //定义数据状态 } this._todos.set(todo.key,todo); //存储至容器中 //持久化处理 store.set(todo.key,todo); this.flush(); return todo } todochaService(key,checked){ let todo=this._todos.get(key) //获取对应的值 todo.completed=checked; //赋值 console.log(todo.completed,checked) this._todos.set(key,todo) //刷新map store.set(key,todo) //刷新store this.flush() } }
四 部署相关事宜1 编写python端配置,及后端服务配置1 安装模块
pip install aiohttp
2 编写代码
#!/usr/bin/poython3.6#conding:utf-8from aiohttp import web,logimport loggingimport jsonasync def indexhandle(request:web.Request): return web.Response(text='welcom to pyserver',status=200)async def handle(request:web.Request): print (request.match_info) print (request.query_string) return web.Response(text=request.match_info.get('id','0000'),status=200)async def todopost(request:web.Request): print (request.method) print (request.match_info) print (request.query_string) js=await request.json() #协程是一个一个迭代,获取json字符串提交数据 print (js,type(js)) text=dict(await request.post()) #此处是一个可迭代对象,传统post提交//postman中使用此种方式进行提交处>理的 print (text,type(text)) js.update(text) #字典的合并 {}.update(**js,**text) res=json.dumps(js) #json化,将其转换成python的字符串 print (res) return web.Response(text=res,status=201)app=web.Application()app.router.add_get('/',indexhandle)app.router.add_get('/{id}',handle)app.router.add_post('/todo',todopost)app.logger.setLevel(level=logging.NOTSET) #最底级别web.run_app(app,host='0.0.0.0',port=8080)
3 启动如下
python test.py &
4 结果如下
2 修改webpack.config.dev.js 相关反响代理端配置如下3 重启访问如下本机服务器端IP地址为192.168.1.200,监听端口为8080
访问跟根
访问id
访问todo,上述只支持JSON格式,其他格式访问则不能正常访问
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。