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格式,其餘格式訪問則不能正常訪問