重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
惠民ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:028-86922220(备注:SSL证书合作)期待与您的合作!
目录
todolist项目:...1
阶段5,状态的控制和改变:...1
阶段6,getter、setter:...5
阶段7,过滤数据方法调整:...9
阶段8,@computed的使用:...13
阶段9,完成状态,Symbol类型:...14
阶段10,axios,整合前后端:...17
Redux和Mobx,社区提供的状态管理库;
Redux,代码优秀,使用严格的函数式编程思想,学习曲线陡峭,小项目使用的优势不明显;
Mobx,优秀稳定的库,简单方便(内部实现复杂),适合中小项目使用,使用面向对象的方式,易学习和接受,现使用非常广泛;
https://mobx.js.org/
http://cn.mobx.js.org/
mobx实现了观察者模式(订阅+广播模式),观察者观察某个目标,obserable目标对象发生了变化,会通知自己内部注册了的observer观察者;
./src/index.js
import React from 'react';
import ReactDom from 'react-dom';
import TodoApp from './component/TodoApp';
import TodoService from './service/service';
const service =new TodoService(); //service实例通过props属性传递到组件中
ReactDom.render(
./src/service/service.js
解决复选框改变,列表不刷新问题:
1、手动修改todos,如下例,相当于change过;
2、用一常量,如@observable changed=false(或changed=时间戳+随机数),但这个变量要在render()中用到,哪怕写{this.props.service.changed}都行反正要用到,否则不会刷新;
import store from 'store';
import {observable}from 'mobx';
export default class TodoService {
constructor() {
// super();
this.load();
}
load() {
store.each((value,key)=> {
if (key.startsWith(TodoService.NAMESPACE))
// this.todos.push(value);
this.todos.set(key,value);
});
console.log(this.todos);
}
static NAMESPACE ='todo::';
// todos = [];
@observable //观察目标
todos =new Map();
create(title) {
// console.log('service');
const todo = {
key: TodoService.NAMESPACE + (new Date()).valueOf(),
title: title,
completed: false
};
// this.todos.push(todo);
this.todos.set(todo.key,todo);
store.set(todo.key,todo);
return todo;
}
setTodoState(key,checked) {
let todo =this.todos.get(key);
if (todo) {
todo.completed =checked;
store.set(key,todo);
}
let temp =this.todos; //改变观察目标,解决Checkbox复选框改变列表不刷新问题
this.todos = {}; //同this.todos = () => {}
this.todos =temp;
}
}
./src/component/TodoApp.js
this.props.service.create(event.target.value),index.js已定义,此处用props属性访问;
之前的this.state=({todos: this.service.todos})注释,当前使用mobx控制状态;
import React from 'react';
import Create from './Create';
// import TodoService from '../service/service';
import Todo from './Todo';
import Filter from './Filter';
import {observer}from 'mobx-react'; //注意此处是mobx-react
@observer
export default class TodoApp extends React.Component {
constructor(props) {
super(props);
// this.service = new TodoService();
// this.state = ({todos: this.service.todos, filter: 'uncompleted'});
this.state = ({filter: 'uncompleted'});
}
// handleCreate(...args) {
// console.log('Root handlerCreate');
// console.log(this);
// console.log('args is ', args);
// }
handleCreate(event) {
// console.log('Root handleCreate');
// console.log(this);
// console.log('event is ', event, event.target, event.target.value);
this.props.service.create(event.target.value);
// this.setState({todos: this.service.todos});
}
handleCheckedChange(key,checked) { //handleCheckedChange(event),event.target.checked=false|true
console.log('handleCheckedChange',key,checked);
this.props.service.setTodoState(key,checked);
// this.setState({todos: this.service.todos});
}
handleFilterChange(value) {
// console.log('~~~~~~~', args);
// console.log(this);
console.log(value);
this.setState({filter: value});;
}
render() {
return (
{/* {this.service.todos.map(
item =>
} */}
{/* {
[...this.service.todos.values()].map(
item =>
)
} */}
{
[...this.props.service.todos.values()].filter(
item => {
let fs =this.state.filter;
if(fs ==='all') {
return true;
}else if(fs ==='completed') {
// if(item.completed === true)
// return true;
// else
// return false;
return item.completed ===true;
}else if(fs ==='uncompleted') {
// if(item.completed === false)
// return true;
// else
// return false;
return item.completed ===false;
}
}
).map(
item =>
)
}
);
}
}
./src/component/{Create.js,Todo.js,Filter.js}不动;
类似py的property装饰器;
./src/service/service.js
import store from 'store';
import {observable}from 'mobx';
export default class TodoService {
constructor() {
// super();
this.load();
}
load() {
store.each((value,key)=> {
if (key.startsWith(TodoService.NAMESPACE))
// this.todos.push(value);
this._todos.set(key,value);
});
// console.log(this.todos);
}
static NAMESPACE ='todo::';
// todos = [];
@observable
_todos =new Map();
get todos() { //getter
return this._todos;
}
create(title) {
// console.log('service');
const todo = {
key: TodoService.NAMESPACE + (new Date()).valueOf(),
title: title,
completed: false
};
// this.todos.push(todo);
this._todos.set(todo.key,todo);
store.set(todo.key,todo);
let temp =this._todos; //类似setter;这三句放到此处,解决新创建的待办事宜的刷新问题
this._todos = {};
this._todos =temp;
return todo;
}
setTodoState(key,checked) {
let todo =this._todos.get(key);
if (todo) {
todo.completed =checked;
store.set(key,todo);
}
let temp =this._todos; //setter
this._todos = {}; //this.todos = () => {}
this._todos =temp;
}
}
./src/component/TodoApp.js
import React from 'react';
import Create from './Create';
// import TodoService from '../service/service';
import Todo from './Todo';
import Filter from './Filter';
import {observer}from 'mobx-react';
@observer
export default class TodoApp extends React.Component {
constructor(props) {
super(props);
// this.service = new TodoService();
// this.state = ({todos: this.service.todos, filter: 'uncompleted'});
this.state = ({filter: 'uncompleted'});
}
// handleCreate(...args) {
// console.log('Root handlerCreate');
// console.log(this);
// console.log('args is ', args);
// }
handleCreate(event) {
// console.log('Root handleCreate');
// console.log(this);
// console.log('event is ', event, event.target, event.target.value);
this.props.service.create(event.target.value);
// this.setState({todos: this.service.todos});
}
handleCheckedChange(key,checked) { //handleCheckedChange(event),event.target.checked=false|true
// console.log('handleCheckedChange', key, checked);
this.props.service.setTodoState(key,checked);
// this.setState({todos: this.service.todos});
}
handleFilterChange(value) {
// console.log('~~~~~~~', args);
// console.log(this);
// console.log(value);
this.setState({filter: value});;
}
render() {
return (
{/* {this.service.todos.map(
item =>
} */}
{/* {
[...this.service.todos.values()].map(
item =>
)
} */}
{
[...this.props.service.todos.values()].filter(
item => {
let fs =this.state.filter;
if(fs ==='all') {
return true;
}else if(fs ==='completed') {
// if(item.completed === true)
// return true;
// else
// return false;
return item.completed ===true;
}else if(fs ==='uncompleted') {
// if(item.completed === false)
// return true;
// else
// return false;
return item.completed ===false;
}
}
)
.map(
item =>
)
}
);
}
}
将过滤数据的filter,移到service.js中;
./src/service/service.js
import store from 'store';
import {observable}from 'mobx';
export default class TodoService {
constructor() {
// super();
this.load();
}
load() {
store.each((value,key)=> {
if (key.startsWith(TodoService.NAMESPACE))
// this.todos.push(value);
this._todos.set(key,value);
});
// console.log(this.todos);
}
static NAMESPACE ='todo::';
// todos = [];
@observable
_todos =new Map();
@observable //添加观察目标对象
filter ='uncompleted';
get todos() { //getter,_todos变量
// return this._todos;
return [...this._todos.values()].filter(
item => {
let fs =this.filter;
if(fs ==='all') {
return true;
}else if(fs ==='completed') {
// if(item.completed === true)
// return true;
// else
// return false;
return item.completed ===true;
}else if(fs ==='uncompleted') {
// if(item.completed === false)
// return true;
// else
// return false;
return item.completed ===false;
}
}
);
}
create(title) {
// console.log('service');
const todo = {
key: TodoService.NAMESPACE + (new Date()).valueOf(),
title: title,
completed: false
};
// this.todos.push(todo);
this._todos.set(todo.key,todo);
store.set(todo.key,todo);
let temp =this._todos;
this._todos = {};
this._todos =temp;
return todo;
}
setTodoState(key,checked) {
let todo =this._todos.get(key);
if (todo) {
todo.completed =checked;
store.set(key,todo);
}
let temp =this._todos;
this._todos = {}; //this.todos = () => {}
this._todos =temp;
}
setTodoFilter(value) {
this.filter =value;
}
}
./src/component/TodoApp.js
import React from 'react';
import Create from './Create';
// import TodoService from '../service/service';
import Todo from './Todo';
import Filter from './Filter';
import {observer}from 'mobx-react';
@observer
export default class TodoApp extends React.Component {
constructor(props) {
super(props);
// this.service = new TodoService();
// this.state = ({todos: this.service.todos, filter: 'uncompleted'});
// this.state = ({filter: 'uncompleted'}); //filter使用mobx管理
}
// handleCreate(...args) {
// console.log('Root handlerCreate');
// console.log(this);
// console.log('args is ', args);
// }
handleCreate(event) {
// console.log('Root handleCreate');
// console.log(this);
// console.log('event is ', event, event.target, event.target.value);
this.props.service.create(event.target.value);
// this.setState({todos: this.service.todos});
}
handleCheckedChange(key,checked) { //handleCheckedChange(event),event.target.checked=false|true
// console.log('handleCheckedChange', key, checked);
this.props.service.setTodoState(key,checked);
// this.setState({todos: this.service.todos});
}
handleFilterChange(value) {
// console.log('~~~~~~~', args);
// console.log(this);
// console.log(value);
// this.setState({filter: value});;
this.props.service.setTodoFilter(value);
}
render() {
return (
{/* {this.service.todos.map(
item =>
} */}
{/* {
[...this.service.todos.values()].map(
item =>
)
} */}
{
this.props.service.todos.map(
item =>
)
}
);
}
}
mobx提供了@computed装饰器,可用在任意类的属性的getter上,它所依赖的值发生了变化就重新计算,否则直接返回上次计算的结果;
使用@computed装饰get todos();
./src/service/service.js
import {observable,computed}from 'mobx';
export default class TodoService {
……
@computed //程序员感知不到变化,观察对象_todos和filter任意一个变化都会重新计算
get todos() {
// return this._todos;
return [...this._todos.values()].filter(
item => {
let fs =this.filter;
if(fs ==='all') {
return true;
}else if(fs ==='completed') {
// if(item.completed === true)
// return true;
// else
// return false;
return item.completed ===true;
}else if(fs ==='uncompleted') {
// if(item.completed === false)
// return true;
// else
// return false;
return item.completed ===false;
}
}
);
}
……
}
Symbol类型,是JS中的基本类型;
是ES6新增的主数据类型,是一种特殊的、不可变的数据类型;
Symbol([description]),description是可选的字符串;
不可使用new关键字,生成的不是对象,直接用函数调用方式使用;
Symbol每次返回一个独一无二的值,即便2次的描述一样,描述只是为了使人阅读方便,便于区分不同的Symbol值;
例:
let sym0 =Symbol();
let sym1 =Symbol();
let sym2 =Symbol('symbol2');
let sym3 =Symbol('symbol2');
console.log(sym0 ===sym1);
console.log(sym1 ===sym2);
输出:
false
false
./src/service/service.js
import store from 'store';
import {observable,computed}from 'mobx';
const ALL =Symbol('all');
const COMPLETED =Symbol('completed');
const UNCOMPLETED =Symbol('uncompleted');
export default class TodoService {
constructor() {
// super();
this.load();
}
load() {
store.each((value,key)=> {
if (key.startsWith(TodoService.NAMESPACE))
// this.todos.push(value);
this._todos.set(key,value);
});
// console.log(this.todos);
}
static NAMESPACE ='todo::';
static TODOSTATES = {
// all: 'all',
all: ALL,
// completed: 'completed',
completed: COMPLETED,
// uncompleted: 'uncompleted'
uncompleted: UNCOMPLETED
}
// todos = [];
@observable
_todos =new Map();
@observable
// filter = 'uncompleted';
filter =TodoService.TODOSTATES.uncompleted;
@computed
get todos() {
// return this._todos;
return [...this._todos.values()].filter(
item => {
let fs =this.filter;
// if(fs === 'all') {
if(fs ===TodoService.TODOSTATES.all) { //只能用类.属性这种方式,不可以fs === Symbol('all'),这样相当于重新调用Symbol()是个新值;===常用,严格相等;==要做隐式转换,不用
return true;
// } else if(fs === 'completed') {
}else if(fs ===TodoService.TODOSTATES.completed) {
// if(item.completed === true)
// return true;
// else
// return false;
return item.completed ===true;
// } else if(fs === 'uncompleted') {
}else if(fs ===TodoService.TODOSTATES.uncompleted) {
// if(item.completed === false)
// return true;
// else
// return false;
return item.completed ===false;
}
}
);
}
create(title) {
// console.log('service');
const todo = {
key: TodoService.NAMESPACE + (new Date()).valueOf(),
title: title,
completed: false
};
// this.todos.push(todo);
this._todos.set(todo.key,todo);
store.set(todo.key,todo);
let temp =this._todos;
this._todos = {};
this._todos =temp;
return todo;
}
setTodoState(key,checked) {
let todo =this._todos.get(key);
if (todo) {
todo.completed =checked;