一 localstorage和基本组件介绍

1 localstorage介绍

localstorage 是浏览器端持久化方案之一,HTML5标准增加的技术
localstorage 是为了存储交互的数据,如json。
数据存储就是键值在不同域名下的存储
不同浏览器对单个域名下存储数据的长度支持不同,有的最多支持2MB

如下

react项目基本实践_第1张图片

其中sessionstorage是会话级别的存储,及就是临时存储。
localstorage 支持的浏览器最多而sessionstorage支持的浏览器却较少。
下面的indexedDB和web SQL 是和数据库存储有关,

indexedDB:
一个域一个datatable
key-value 检索方式
建立在关系型数据库上,具有索引表,游标,事务等概念。

2 store.js

store.js是一个兼容所有浏览器的localstorage包装器,不需要借助cookie或者flash,store.js会根据浏览器自动选择使用localstorage,globalstorage或者 userdata来实现本地存储功能。


安装

npm  i store  --save //此处是在部署包中添加 

react项目基本实践_第2张图片

介绍和相关说明

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)
})

结果如下

react项目基本实践

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();

输入框属性

addonAfter 带标签的 input,设置后置标签 string|ReactNode
addonBefore 带标签的 input,设置前置标签 string|ReactNode
placeholder="Basic usage" 占位词
size="smail" 小输入框,改为large就是大输入框

2 Card 组件

显示一个较为友好的界面

地址如下

https://ant.design/components/card-cn/

相关映射如下,最后面的style={{width:300}} 表示样式,其是指宽度

react项目基本实践_第3张图片

3 CheckBox多选框

相关处理可以使用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, 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 => (
    
        
            
            {props.todo.title}
         
       
);

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(
  ,

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)

结果如下

react项目基本实践

5 状态管理Mobx

Redux 和 Mobx

上述项目中基本功能都实现了。但state的控制显得有些麻烦。

社区提供了状态管理库,有Redux和Mobx

Redux 代码优秀,使用严格的函数式编程思想,学习曲线陡峭,小项目使用的优势不明显
Mobx,稳定,使用简单方便,适合中小型项目的使用,使用面向对象的方式学习,容易学习和接受,现在,使用也非常广泛。


Mobx 官网

https://mobx.js.org/

中文网

https://cn.mobx.js.org/

Mobx实现了观察者模式

观察者模式
观察者观察某个目标,目标对象(Obserable)发生了变化,就会通知自己内部注册的观察者Observer

react项目基本实践_第4张图片

观察者模式,及就是一对多的广播模式

首先,需要观察者和被观察者

目标对象,及被观察者,obserable 指的是数据的源头,被观察者可以有多个,同时观察这个变化。只要被观察的对象有变化,则便会导致观察者做出相应的操作,state和props变化是我们关心的,


@computed 的使用

mobx还提供了一个装饰器@computed,可以使用在任意类上属性的getter上使用,其所依赖的值发生了变化就会重新计算,否则直接返回到上次计算的结果。起到了缓存的作用,可直接用于filter的判断上,通过传入的值来进行相关匹配进而进行返回或计算。

6 异步处理和打包部署

异步处理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 需求分析

分层
视图层,负责显示数据,每一个react 组件一个js文件。

服务层,负责业务数据处理逻辑,命名为xxxService.js。

model层,负责数据,这里使用localstore。

注意:未特别说明,这些层的代码都在项目跟目录的src中

2 代码实现

1 服务层实现

此处仍使用上一节项目包,相关介绍如下

https://blog.51cto.com/11233559/2443713


项目包如下
链接:https://pan.baidu.com/s/1C-ZY9rWU-8ZugE4EwVveWw
提取码:744p

具体项目介绍。请查看上一节 react项目基础

构建TodoService类,文件名为service.js,此目前放置在src的目录下

react项目基本实践_第5张图片

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  => (
    
        
    

测试代码

)

开放接口层代码 index.js 相关代码如下

import React from 'react';   
import ReactDOM from 'react-dom';
import Create  from  './create'  //引入模块 

class  Root extends  React.Component  {
    render(){
        return  (
hello world
//引入显示
) } } ReactDOM.render(,document.getElementById('root'));

结果如下

react项目基本实践_第6张图片

输入框处理,为了能让用户提交信息,我们需要是哦有那个接受回车键的事件触发提交信息,键盘按下是一个事件,在Input中使用onPressEnter来收集键盘按下回车键的触发指令。

react项目基本实践

此处表明后面跟的是一个函数

修改如下
打印回车数据,其是通过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  => (
    
        {console.log(event.target.value)}}/>  {/*此处使用event表示触发的事件,其表示获取到用户数据*/}
    

测试代码

)

拿到用户数据,应该调用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  (
hello world
{/*通过此处的传递将oncrete属性传递到后端用于相关的处理*/}
) } } ReactDOM.render(,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  => (
    
         props.onCreate(event)}/>  {/*此处通过外部的index.js中的数据传递
        将handleCreate 传递过来进行相关的处理操作,其被作为props携带进入此处参与相关的处理和调度操作*/}
    

测试代码

)

结果如下

react项目基本实践_第7张图片

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 =>(
    
        
             }/>
            {props.todo.title}
        
    
)

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(
            
            {/*自己定义一个属性,处理props事件的*/}           {/*完成数据的显示*/}           {/* {this.service.todos.forEach}  虽然遍历,但不返回任何结果 */}           {this.service.todos.map(item=> )}  {/*调用todo进行处理相关的函数问题,map后返回新的容器*/}         
    );   } } ReactDOM.render(,document.getElementById('root'));  //NewRoot(props)  

结果如下

react项目基本实践_第8张图片

每添加一个元素,其会显示该元素。但其在网页刷新后其会不存在,但在localstorage中存储所有的数据,因此需要处理装载数据的函数。

4 数据持久化操作

修改代码如下

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(
            
            {/*自己定义一个属性,处理props事件的*/}           {/*完成数据的显示*/}           {[...this.service.todos.values()].map( item=> )}  {/*调用todo进行处理相关的函数问题,map后返回新的容器*/}         
    );   } } ReactDOM.render(,document.getElementById('root'));  //NewRoot(props)   // Test(Root)(props)

最终结果如下

react项目基本实践_第9张图片

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 => (
    
        
            props.onChage(event.target.checked,props.todo.key)}/>
            {props.todo.title}
         
       
);

后端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(
            
            {/*自己定义一个属性,处理props事件的*/}           {/*完成数据的显示*/}           {[...this.service.todos.values()].map( item=> )}  {/*调用todo进行处理相关的函数问题,map后返回新的容器*/}         
    );   } } ReactDOM.render(,document.getElementById('root'));  //NewRoot(props)   // Test(Root)(props)

结果如下

react项目基本实践_第10张图片

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  => (
  
);

其中 defaultValue 用于显示默认设置
onChange={(event) =>console.log(event)} 用于查看选择引起的调度
中中间的未完成用于显示,而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(
            
            {/*自己定义一个属性,处理props事件的*/}           {/*完成数据的显示*/}           {[...this.service.todos.values()].map( item=> )}  {/*调用todo进行处理相关的函数问题,map后返回新的容器*/}         
    );   } } ReactDOM.render(,document.getElementById('root'));  //NewRoot(props)   // Test(Root)(props)

结果如下

react项目基本实践_第11张图片

选择不同的选项会导致不同的触发结果,此处便可作为其条件进行相关操作

配置触发改变和相关显示

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(
            
            {/*自己定义一个属性,处理props事件的*/}           {/*完成数据的显示*/}           {[...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进行处理相关的函数问题,map后返回新的容器*/}         
    );   } } ReactDOM.render(,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  => (
  
);

结果如下

react项目基本实践_第12张图片

react项目基本实践_第13张图片

7 调整代码布局

调整代码布局,将显示层(view)代码调整到component目录中包括create.js,filter.js,Todo.js和TodoApp.js(此处是将index.js的数据悉数移动到形成的),将后面的service层的代码调整到service中,如下

react项目基本实践_第14张图片

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(
            
            {/*自己定义一个属性,处理props事件的*/}           {/*完成数据的显示*/}           {[...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进行处理相关的函数问题,map后返回新的容器*/}         
    );   } }

index.js 如下

import ReactDOM from 'react-dom';
import React from 'react';
import  Root  from  './compoent/TodoApp';
ReactDOM.render(,document.getElementById('root'));  //NewRoot(props)  
    // Test(Root)(props)

8 总结

渲染的事情归TodoApp负责,并管理所有的状态。
create负责显示文本框,接受用户输入的待办事宜。
TOdo,负责每一条数据的显示和check变化
filter,主要负责一个状态的filter的切换


service.js

todoservice 负责业务的处理,为了简单,把数据处理也放在此处

状态state的控制和修改有些麻烦,需要改进

三 服务改进

1 状态监控改进

程序修改

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(,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(
            
            {/*自己定义一个属性,处理props事件的*/}           {/*完成数据的显示*/}           {[...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进行处理相关的函数问题,map后返回新的容器*/}         
    );   } }

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;
    }

}

结果如下

react项目基本实践_第15张图片

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';
@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(
            
            {/*自己定义一个属性,处理props事件的*/}           {/*完成数据的显示*/}           {this.props.service.todos.map(item => )}         
    );   } }

修改代码如下

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-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)

3 启动如下

python  test.py   &

4 结果如下

react项目基本实践_第16张图片

2 前端

1 查看后端IP地址和相关监听端口

本机服务器端IP地址为192.168.1.200,监听端口为8080

react项目基本实践_第17张图片

2 修改webpack.config.dev.js 相关反响代理端配置如下

react项目基本实践_第18张图片

3 重启访问如下

访问跟根

react项目基本实践_第19张图片

访问id

react项目基本实践_第20张图片

访问todo,上述只支持JSON格式,其他格式访问则不能正常访问

react项目基本实践_第21张图片