localstorage 是浏览器端持久化方案之一,HTML5标准增长的技术
localstorage 是为了存储交互的数据,如json。
数据存储就是键值在不一样域名下的存储
不一样浏览器对单个域名下存储数据的长度支持不一样,有的最多支持2MB 前端以下python
其中sessionstorage是会话级别的存储,及就是临时存储。
localstorage 支持的浏览器最多而sessionstorage支持的浏览器却较少。
下面的indexedDB和web SQL 是和数据库存储有关,reactindexedDB:
一个域一个datatable
key-value 检索方式
创建在关系型数据库上,具备索引表,游标,事务等概念。webpack
store.js是一个兼容全部浏览器的localstorage包装器,不须要借助cookie或者flash,store.js会根据浏览器自动选择使用localstorage,globalstorage或者 userdata来实现本地存储功能。ios
安装 git
npm i store --save //此处是在部署包中添加
介绍和相关说明github
https://github.com/marcuswestin/store.js/web
测试代码以下 数据库
var store = require('store') //导入模块 store.set('user','test') //设置key,value值 console.log(store.get('user')) //获取key,value值 store.remove('user') //移除key,及其和对应的value console.log(store.get('user','aaaaa')) //查询不存在时使用默认 store.clearAll() //清除全部 store.set('test','test') // 设置 store.each(function (value,key) { //遍历key和value,注意,此处是value,key console.log(key,'====',value) })
结果以下npm
用户提交数据,须要表单控件,而这种用户提交的数据显示就是view层须要完成的功能,对于react来讲是一个空间,但这些控件须要用户看到,为了美观,引入了antd。
ant Design 蚂蚁金服开源的reactUI库
antd官网
https://ant.design/index-cn
官方文档
https://ant.design/docs/react/introduce-cn
使用一种较为简单的组件Input来完成输入功能
地址以下
https://ant.design/components/input-cn/
基础代码以下
import { Input } from 'antd'; ReactDOM.render(<Input placeholder="Basic usage" />);
输入框属性
addonAfter 带标签的 input,设置后置标签 string|ReactNode
addonBefore 带标签的 input,设置前置标签 string|ReactNode
placeholder="Basic usage" 占位词
size="smail" 小输入框,改成large就是大输入框
显示一个较为友好的界面
地址以下
https://ant.design/components/card-cn/
相关映射以下,最后面的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);
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> );
过滤是指,过滤什么状态的待办事宜
应该有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>,
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)
结果以下
Redux 和 Mobx
上述项目中基本功能都实现了。但state的控制显得有些麻烦。
社区提供了状态管理库,有Redux和Mobx
Redux 代码优秀,使用严格的函数式编程思想,学习曲线陡峭,小项目使用的优点不明显
Mobx,稳定,使用简单方便,适合中小型项目的使用,使用面向对象的方式学习,容易学习和接受,如今,使用也很是普遍。
Mobx 官网
https://mobx.js.org/
中文网
https://cn.mobx.js.org/
Mobx实现了观察者模式
观察者模式
观察者观察某个目标,目标对象(Obserable)发生了变化,就会通知本身内部注册的观察者Observer
观察者模式,及就是一对多的广播模式
首先,须要观察者和被观察者
目标对象,及被观察者,obserable 指的是数据的源头,被观察者能够有多个,同时观察这个变化。只要被观察的对象有变化,则便会致使观察者作出相应的操做,state和props变化是咱们关心的,
@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); });
分层
视图层,负责显示数据,每个react 组件一个js文件。服务层,负责业务数据处理逻辑,命名为xxxService.js。
model层,负责数据,这里使用localstore。
注意:未特别说明,这些层的代码都在项目跟目录的src中
此处仍使用上一节项目包,相关介绍以下
项目包以下
连接: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 } }
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> )
结果以下
添加数据完成后显示问题,须要建立用于列表显示结果,须要建立的包以下,其仍然再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)
结果以下
每添加一个元素,其会显示该元素。但其在网页刷新后其会不存在,但在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)
最终结果以下
不管如何刷新,其最终结果都将会彻底显示
后端 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)
结果以下
建立相关过滤模块,以下 仍然临时存储于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> );
结果以下
调整代码布局,将显示层(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)
渲染的事情归TodoApp负责,并管理全部的状态。
create负责显示文本框,接受用户输入的待办事宜。
TOdo,负责每一条数据的显示和check变化
filter,主要负责一个状态的filter的切换
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'; @observer export 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> ); } }
复选框改变列表不刷新问题
运行一切为正常,就是有一点不方便,及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; } }
结果以下
可以将过滤数据的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'; @observer export 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; } }
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() } }
pip install aiohttp
#!/usr/bin/poython3.6 #conding:utf-8 from aiohttp import web,log import logging import json async 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)
python test.py &
本机服务器端IP地址为192.168.1.200,监听端口为8080
访问跟根
访问id
访问todo,上述只支持JSON格式,其余格式访问则不能正常访问