您好,登錄后才能下訂單哦!
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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。