localstorage 是浏览器端持久化方案之一,HTML5标准增加的技术
localstorage 是为了存储交互的数据,如json。
数据存储就是键值在不同域名下的存储
不同浏览器对单个域名下存储数据的长度支持不同,有的最多支持2MB如下
其中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,及其和对应的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)
})
结果如下
用户提交数据,需要表单控件,而这种用户提交的数据显示就是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://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
}
}
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格式,其他格式访问则不能正常访问
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。