Flux:Flux 是一种架构思想

https://facebook.github.io/flux/ 官网

资料:

http://www.ruanyifeng.com/blog/2016/01/flux.html


Redux:

Redux 由 Flux 演变而来,但受 Elm 的启发,避开了 Flux 的复杂性。 不管你有没有使用过它们,只需几分钟就能上手 Redux。

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 (如果你需要一个 WordPress 框架,请查看 Redux Framework。)

可以让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。不仅于此,它还提供 超爽的开发体验,比如有一个时间旅行调试器可以编辑后实时预览。

Redux 除了和 React 一起用外,还支持其它界面库。 它体小精悍(只有2kB,包括依赖)。

https://redux.js.org/ 官网

http://www.redux.org.cn/ 中文

资料:

https://segmentfault.com/a/1190000011474522


Vuex:

view <------> store

 								 ------------->actions
| disptach |
组件 | |
view --------->| |commit
| |
| commit ↓
-------------> mutations -----> state ----> View

Flux:

Flux 的最大特点,就是数据的"单向流动"。

用户访问 View

View 发出用户的 Action

Dispatcher 收到 Action,要求 Store 进行相应的更新

Store 更新后,发出一个"change"事件

View 收到"change"事件后,更新页面


Redux:

安装

npm install --save redux

基本概念:

vuex:store/state/commit/dispatch/getter/module

redux:Action 、Reducer 、Store

1、Store createStore

const store = createStore(reducer);

const {subscribe, dispatch, getState} = store;

getState:获取你所有的state(数据)

dispatch:分发--触发一个动作

subscribe:订阅

2、Reducer 用来做计算 ―― 产生一个新的状态 newState

state + action ==> newState

3、Action 描述 json

格式:

{
type:"动作"添加 删除 。。。 type是固定
payload:"数据"
}

Redux:使用步骤

1、先安装

npm i -S redux

2、引入
    import {createStore} from "redux";     ES6
const {createStore} require("redux"); ES5
3、写一个计算函数―― reducer
state+action => newState
function reducer(state,action){
switch(action.type){
case "xxx"
return newState;
default:
return state;
} }
4、创建store

const store = createStore(reducer);

5、操作store下的数据―― state

展现:{store.getState()}

修改:store.dispatch(action);

const {createStore,bindActionCreators,combineReducers} = require("redux");

bindActionCreators:

1、action

2、dispatch

使用格式:

const bindAction = bindActionCreators(fnAction,dispatch);

bindAction();

combineReducers:

//合并reducer 只能有一个reducer

const reducer = combineReducers({
reducer1,
reducer2,
......
});

Redux 应用只有一个单一的 store 只有一个单一reducer

exp1:

// import { createStore } from "redux";
const { createStore } = require("redux"); /**
* 这是一个 reducer,形式为 (state, action) => newState 的纯函数。
* 描述了 action 如何把 state 转变成下一个 state。
*
* state 的形式取决于你,可以是基本类型、数组、对象、
* 甚至是 Immutable.js 生成的数据结构。惟一的要点是
* 当 state 变化时需要返回全新的对象,而不是修改传入的参数。
*
* 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)
* 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。
*/
function reducer(state = 10, action = {}) {
switch (action.type) {
case "INCREMENT":
return state + 1;
case "DECREMENT":
return state - 1;
default:
return state;
}
} // 创建 Redux store 来存放应用的状态。
// API 是 { subscribe, dispatch, getState }。
let store = createStore(reducer); function log(){
console.log("state:",store.getState());
} // // 可以手动订阅更新,也可以事件绑定到视图层。
store.subscribe(log); // log();
store.dispatch({type:"INCREMENT"});
// log(); store.dispatch({type:"INCREMENT"}); // log(); // 改变内部 state 惟一方法是 dispatch 一个 action。
// action 可以被序列化,用日记记录和储存下来,后期还可以以回放的方式执行

res:

exp2:

//1、引入
const {createStore,bindActionCreators} = require("redux"); //2、创建reducer //state数据初始化 const initState = {
count:0
}; const counterReducer = (state = initState,action = {})=>{
//加减 plus/minus 自定义数据 custom
switch(action.type){
case "PLUS_ONE":
return {count:state.count+1};
case "MINUS_ONE":
return {count:state.count-1};
case "CUSTOM_COUNT":
return {count:state.count+action.payload.count};
default:
return state;
}
}
//3 创建store
const store = createStore(counterReducer); store.subscribe(()=> console.log(store.getState())); //action
store.dispatch({type:"PLUS_ONE"});
store.dispatch({type:"MINUS_ONE"});
store.dispatch({type:"CUSTOM_COUNT",payload:{count:5}}); //action creaters function plusAction(){
return {type:"PLUS_ONE"};
}
function minusAction(){
return {type:"MINUS_ONE"};
}
function customCountAction(count){
return {type:"CUSTOM_COUNT",payload:{count}};
}
store.dispatch(plusAction());
store.dispatch(minusAction());
store.dispatch(customCountAction(5)); function plusActionWithDispatch(){
const action = {type:"PLUS_ONE"};
store.dispatch(action);
}
function minusActionWithDispatch(){
const action = {type:"MINUS_ONE"};
store.dispatch(action);
}
function customCountActionWithDispatch(count){
const action = {type:"CUSTOM_COUNT",payload:{count}};
store.dispatch(action);
}
plusActionWithDispatch();
minusActionWithDispatch();
customCountActionWithDispatch(5); const bindPlusAction = bindActionCreators(plusAction,store.dispatch); bindPlusAction();

res:



exp3:

<!DOCTYPE html>
<html>
<head>
<title>Redux basic example</title>
<script src="./node_modules/redux/dist/redux.js"></script>
</head>
<body>
<div>
<p>
Clicked: <span id="value">0</span> times
<button id="increment">+</button>
<button id="decrement">-</button>
<button id="incrementIfOdd">Increment if odd</button>
<button id="incrementAsync">Increment async</button>
</p>
</div>
<script>
function reducer(state = 10, action) { switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
var store = Redux.createStore(reducer) var valueEl = document.getElementById('value')
function render() {
valueEl.innerHTML = store.getState().toString()
}
render()
store.subscribe(render)
document.getElementById('increment')
.addEventListener('click', function () {
store.dispatch({ type: 'INCREMENT' })
})
document.getElementById('decrement')
.addEventListener('click', function () {
store.dispatch({ type: 'DECREMENT' })
})
document.getElementById('incrementIfOdd')
.addEventListener('click', function () {
if (store.getState() % 2 !== 0) {
store.dispatch({ type: 'INCREMENT' })
}
})
document.getElementById('incrementAsync')
.addEventListener('click', function () {
setTimeout(function () {
store.dispatch({ type: 'INCREMENT' })
}, 1000)
})
</script>
</body>
</html>

res:

exp4:


//1、引入
const {createStore,combineReducers} = require("redux"); //2、创建reducer //state数据初始化 const initState = {
count:0
}; const counterReducer = (state = initState,action = {})=>{
//加减 plus/minus 自定义数据 custom
switch(action.type){
case "PLUS_ONE":
return {count:state.count+1};
case "MINUS_ONE":
return {count:state.count-1};
case "CUSTOM_COUNT":
return {count:state.count+action.payload.count};
default:
return state;
}
}
const myReducer = (state = [],action={}) => state; //合并reducer 只能有一个reducer
const reducer = combineReducers({
counterReducer,
myReducer,
}); //3 创建store
//const store = createStore(counterReducer);
const store = createStore(reducer); console.log("state:",store.getState());

res:

Object.assign(target目标,数据源多个);

作用:

1、拷贝 ―― 浅拷贝

2、合并对象―― 后面的属性会覆盖前面的属性

3、继承

和jquery extend一样

$.extend默认是浅拷贝 如果要实现深度拷贝

$.extend(true,target目标,数据源多个);

自己实现一个深度拷贝

JSON.parse/stringify

exp1:

复制,合并

<script>
//Object.assign $.extend var a = {a:"a"};
var b = {b:"b"} var x = Object.assign({},a,b); console.log(x==a,x,a,b); </script>

res:

exp2:

//属性重复 后面的属性会覆盖前面的属性

<script>
//Object.assign $.extend //属性重复 后面的属性会覆盖前面的属性
var a = {a:"a"};
var b = {a:"b",b:"b"};
var c = {a:"c",b:"c",c:"c"} var x = Object.assign({},a,b,c); console.log(x,a,b,c); </script>

res:



exp3:

//Object.assign是一个浅拷贝

浅拷贝指的是拷贝后的元素变化会影响的原来的元素; 只拷贝了地址

<script>
//Object.assign $.extend
//深拷贝 浅拷贝
//属性重复 后面的属性会覆盖前面的属性 //Object.assign是一个浅拷贝
var a = {a:1,b:2,arr:[1,2]};
var b = {}
Object.assign(b,a); b.arr[0] = "bbb"; console.log(a,b,a==b); </script>

res:

exp4:

深拷贝

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
//Object.assign === $.extend//浅拷贝 默认是浅拷贝
//深拷贝 浅拷贝
//属性重复 后面的属性会覆盖前面的属性 //true表示深拷贝
var a = {a:1,b:2,arr:[1,2]};
var b = {};
$.extend(true,b,a); b.arr[0] = "bbb"; console.log(a,b,a==b); </script>

res:

exp5:

<script>
//copy JSON.parse/stringify
var a = {a:1,b:2,arr:[1,2]};
var b = copy(a); b.arr[0] = "bbb"; function copy(obj){
//转成字符串,再转成json,地址变了,
return JSON.parse(JSON.stringify(obj));
} console.log(a,b,a==b); </script>

res:

exp6:

<script>

function Person(name,age){
this.name = name;
this.age = age;
} Person.prototype.getName = function(){
return this.name;
} function Worker(name,age,job){
//Person.call(this,name,age);
Object.assign(this,{name,age,job});
}
//Worker.prototype = new Person(); Object.assign(Worker,Person);
Worker.prototype.getJob = function(){
return this.job;
} console.log(Worker.prototype,Person.prototype); </script>

res:

exp7:

react状态

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="react.js"></script>
<script src="react-dom.js"></script>
<script src="babel.js"></script>
<script type="text/babel">
//状态
class Test extends React.Component{
constructor(...args){
super(...args);
this.state = {
a:1,b:2,
count:0
}
}
plus(){
let oldSate = this.state;
let obj = {
count:this.state.count+1
};
this.setState(obj); setTimeout(()=>{
console.log(1,this.state == obj,this.state,obj);
},0);
} render(){
return <div>
count:{this.state.count}
<input onClick={this.plus.bind(this)} type="button" value="按钮"/>
</div>
}
}
ReactDOM.render(
<Test/>,
document.getElementById("app")
);
</script>
<body>
<div id="app"></div>
</body>
</html>

res:



exp8:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="react.js"></script>
<script src="react-dom.js"></script>
<script src="babel.js"></script>
<script type="text/babel">
//状态
let state = {a:1,b:2,count:1,msg:""}; function setState(newState){
//复制,形同的取后面的
//state = Object.assign({},state,newState);
//结构去重
state = {...state,...newState};
renderApp();
} class Test extends React.Component{ plus(){
let oldState = state;
setState({
count:state.count+1
}); console.log(state == oldState,state);
} show(ev){
setState({
msg:ev.target.value
});
}
render(){
console.log("渲染了",state);
return <div>
count:{state.count}
<input onClick={this.plus.bind(this)} type="button" value="按钮"/> <br />
<input onChange={this.show.bind(this)} type="text" value={state.msg}/> {state.msg} </div>
}
}
renderApp();
//把渲染封装成函数
function renderApp(){
ReactDOM.render(
<Test/>,
document.getElementById("app")
);
} </script>
<body>
<div id="app"></div>
</body>
</html>

res:


不用react-redux:

页面渲染:

1.this.setState({})

此函数自动渲染页面.

2.给将render封装成函数,改变数据需要更新页面时调用,

3.index.js中的React.render(),封装成函数,添加store.subscribe(函数名)监听,适合页面较多的情况.

react-redux: 帮你渲染页面

cnpm i -S react-redux

import {Provider,Connect} from "react-redux";

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from "react-redux";
import store from "./react-redux/store";
import App from './react-redux/Counter';
import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(
//组件Provider,引入store.
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')); registerServiceWorker();

Counter.js:

高阶组件HOC

import React,{Component} from "react";

import {connect} from "react-redux";

class Counter extends Component{
constructor(...args){
super(...args);
console.log("counet props",this.props);
}
render(){
console.log("渲染了");
const {count,dispatch} = this.props;
return <div>
<input onClick={()=>dispatch({type:"MINUS_ONE"})} type ="button" value="-"/>
<span>{count}</span>
<input onClick={()=> dispatch({type:"PLUS_ONE"})} type="button" value="+"/>
</div>
}
} //高阶组件HOC
/* export default connect(function(state){
console.log(111,state);
return state;
})(Counter); */
//export default connect(state=>({count:state.count}))(Counter); /* function mapStateToPros(state){
return {
count:state.count
}
}
export default connect(mapStateToPros)(Counter); */
const mapStateToPros = state =>({count:state.count});
export default connect(mapStateToPros)(Counter);

高阶组件:只负责数据 不涉及UI

exp1:

<script type="text/babel">

class Clock extends React.Component{

    state = {time:new Date()};
timer = null;
componentDidMount(){
this.tick();
} componentWillUnmount(){
clearInterval(this.timer);
} tick(){
this.timer = setInterval(()=>{
this.setState({
time:new Date()
});
},1000);
} render(){
return <div>
<div> time:{this.state.time.toLocaleTimeString()} </div>
</div>
}
}
ReactDOM.render(
<Clock/>,
document.getElementById("app")
); </script>

res:

exp2:

<script type="text/babel">

/*
function connect(fn){
//fn...
return function(WrappedComponent){
return class extends React.Component {
render(){
return null;
}
}
} }
connect(fn)(WrappedComponent)
*/ //高阶组件 1是一个函数 2 返回一个新组件
function withTime(WrappedComponent) {
return class extends React.Component {
state = {time:new Date()};
timer = null;
componentDidMount(){
this.tick();
} componentWillUnmount(){
clearInterval(this.timer);
} tick(){
this.timer = setInterval(()=>{
this.setState({
time:new Date()
});
},1000);
}
render() {
return <WrappedComponent time={this.state.time} />;
}
};
} class Clock0 extends React.Component{
render(){
return <div>
<div> Clock1:{this.props.time.toString()} </div>
</div>
}
} class Clock1 extends React.Component{
render(){
return <div>
<div> Clock1:{this.props.time.toString()} </div>
</div>
}
} class Clock2 extends React.Component{
render(){
return <div>
<div> Clock2:{this.props.time.toLocaleString()} </div>
</div>
}
} Clock1 = withTime(Clock1);
Clock2 = withTime(Clock2); ReactDOM.render(
<div>
<Clock0 time={new Date()}/>
<Clock1/>
<Clock2/> </div>,
document.getElementById("app")
); </script>

res:

24.redux的更多相关文章

  1. 如何使用24行JavaScript代码实现Redux

    作者:Yazeed Bzadough 译者:小维FE 原文:freecodecamp 为了保证文章的可读性,本文采用意译而非直译. 90%的规约,10%的库. Redux是迄今为止创建的最重要的Jav ...

  2. react+redux教程(三)reduce()、filter()、map()、some()、every()、...展开属性

    reduce().filter().map().some().every()....展开属性   这些概念属于es5.es6中的语法,跟react+redux并没有什么联系,我们直接在https:// ...

  3. [React Testing] The Redux Store - Multiple Actions

    When using Redux, we can test that our application state changes are working by testing that dispatc ...

  4. Redux管理你的React应用

    使用Redux管理你的React应用   因为redux和react的版本更新的比较频繁,博客园这里用的redux版本是1.0.1,如果你关心最新版本的使用技巧,欢迎来我的Github查看(https ...

  5. redux 最简例子

    方便初学redux的同学学习,这里是最简单的redux例子 1 import React, {Component, PropTypes} from 'react' 2 import ReactDOM ...

  6. [React] react+redux+router+webpack+antd环境搭建一版

    好久之前搭建的一个react执行环境,受历史影响是webpack3.10.0和webpack-dev-server2.7.1的环境,新项目准备用webpack4重新弄弄了,旧的记录就合并发布了(在没有 ...

  7. 教你如何在React及Redux项目中进行服务端渲染

    服务端渲染(SSR: Server Side Rendering)在React项目中有着广泛的应用场景 基于React虚拟DOM的特性,在浏览器端和服务端我们可以实现同构(可以使用同一份代码来实现多端 ...

  8. 前端(十):使用redux管理数据

    react本身能够完成动态数据的监听和更新,如果不是必要可以不适用redux. 安装redux: cnpm install redux --save,或者yarn add redux. 一.react ...

  9. [翻译]Review——24 tips for React Native you probably want to know

    Post author: Albert Gao Post link: http://www.albertgao.xyz/2018/05/30/24-tips-for-react-native-you- ...

随机推荐

  1. Excel 驼峰表达式

    =LEFT(A1,1)&MID(SUBSTITUTE(PROPER(A1),"_",""),2,100)

  2. [Python设计模式] 第15章 如何兼容各种DB——抽象工厂模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目 如何让一个程序,可以灵活替换数据库? 基础版本 class User(): ...

  3. html5学习笔记3——高级特性

    一:Web存储 数据以 键/值 对存在, web网页的数据只允许该网页访问使用. web存储有两种: localStorage - 没有时间限制的数据存储,存于浏览器缓存 sessionStorage ...

  4. Community宣言

    Community宣言 一个幽灵,共产主义的幽灵,在欧洲游荡.为了对这个幽灵进行神圣的围剿,旧欧洲的一切势力,教皇和沙皇.梅特涅和基佐.法国的激进派和德国的警察,都联合起来了. 有哪一个反对党不被它的 ...

  5. python两个 list 获取交集,并集,差集的方法

    1. 获取两个list 的交集 #方法一: a=[2,3,4,5] b=[2,5,8] tmp = [val for val in a if val in b] print tmp #[2, 5] # ...

  6. jQuery.ajax 调用 服务(.aspx,.asmx)

    方法1:Post(json)+IIS下://aspx,适用本机 $.ajax({ url: "TpgConnect_Rain/postgreService.aspx/getRainInfo& ...

  7. How the heck does async/await work in Python 3.5

    https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/

  8. 解决远程连接mysql很慢的方法

    开发某应用系统连接公司的测试服务器的mysql数据库连接打开的很慢,但是连接本地的mysql数据库很快,刚开始认为可能是网络连接问题导致的,在进行 ping和route后发现网络通信都是正常的,而且在 ...

  9. [Unity]Unity常见API

    本文主要为了方便查阅 1. MonoBehaviour 生命周期 Awake 对象创建的时候调用,类似构造函数 Start 在Awake之后执行,区别在于,如果组件不可用(在Inspector没有勾选 ...

  10. MongoDB 查询总结

    1.含日期查询 从起始时间到结束时间 BasicDBObject queryObj = new BasicDBObject(); queryObj.put("date",new B ...