let objA = { name: 'zfpx' };
let objB = objA;
objB.name = '9';
console.log(objA.name);
内部实现了一套完整的 Persistent Data Structure,还有很多易用的数据类型。像 Collection
、List
、Map
、Set
、Record
、Seq
方法 | 作用 |
---|---|
isMap | 判断是否是Map |
clear | 清空值 |
set | 设置值 |
delete | 删除值 |
update | 更新值 |
merge | 合并值 |
setIn | 设置值 |
deleteIn | 删除值 |
updateIn | 更新值 |
mergeIn | 合并值 |
get | 获取值 |
getIn | 获取值 |
keys | key的数组 |
values | value的数组 |
entries | entry的数组 |
toJS | 转成普通JS对象 |
toObject | 转成普通对象 |
toJSON | 转成JSON对象 |
toArray | 转成数组 |
const immutable = require("immutable");
const assert = require("assert");
let obj1 = immutable.Map({ name: 'zfpx', age: 8 });
let obj2 = obj1.set('name', 'zfpx2');
let obj3 = obj2.update('age', x => x + 1);
let obj4 = obj3.merge({ home: '北京' });
console.log(obj1, obj2, obj3, obj4);
let obj6 = immutable.fromJS({ user: { name: 'zfpx', age: 8 }, 'k': 'v' });
let obj7 = obj6.setIn(['user', 'name'], 'zfpx2');
let obj8 = obj7.updateIn(['user', 'age'], x => x + 1);
let obj9 = obj8.mergeIn(["user"], { home: '北京' });
console.log(obj6, obj7, obj8, obj9);
console.log(obj6.get('user'));
console.log(obj6.getIn(['user', 'name']));
console.log(...obj6.keys());
console.log(...obj6.values());
console.log(...obj6.entries());
var map1 = immutable.Map({ name: 'zfpx', age: 9 });
var map2 = immutable.Map({ name: 'zfpx', age: 9 });
assert(map1 !== map2);
assert(Object.is(map1, map2) === false);
assert(immutable.is(map1, map2) === true);
方法 | 作用 | |
---|---|---|
isList | 判断是否是List | |
size | 统计个数 | |
push | 添加 | |
pop | 弹出最后一个 | |
update | 更新 | |
delete | 删除指定元素的数组 | delete(2) |
insert | 插入指定元素的数组 | insert(2) |
clear | 清空数组 | clear() |
concat | 合并 | |
map | 映射 | |
filter | 过滤 | |
get | 获取 | |
find | 查找 | |
includes | 判断包含 | |
last | 最后一个 | |
reduce | 计算总和 | |
count | 统计个数 |
let immutable = require('immutable');
let arr1 = immutable.fromJS([1, 2, 3]);
console.log(arr1.size);
let arr2 = arr1.push(4);
console.log(arr2);
let arr3 = arr2.pop();
console.log(arr3);
let arr4 = arr3.update(2, x => x + 1);
console.log(arr4);
let arr5 = arr4.concat([5, 6]);
console.log(arr5);
let arr6 = arr5.map(item => item * 2);
console.log(arr6);
let arr7 = arr6.filter(item => item >= 10);
console.log(arr7);
console.log(arr7.get(0));
console.log(arr7.includes(10));
console.log(arr7.last());
let val = arr7.reduce((val, item) => val + item, 0);
console.log(val);
console.log(arr7.count());
let obj1 = immutable.fromJS({ user: { name: 'zfpx', age: 8 }, 'k': 'v' });
let obj2 = obj1.setIn(['user', 'name'], 'zfpx2');
let Immutable=require('immutable');
let p1=Immutable.fromJS({
name: 'zfpx',
home:{name:'beijing'}
});
let p2 = p1.set('name','zfpx2');
console.log(p1.get('home')== p2.get('home'));
只要把每次的状态都放在一个数组中就可以很方便的实现撤销重做功能
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Counter extends Component {
state = {counter:{number:0}}
handleClick = () => {
let amount = this.amount.value ? Number(this.amount.value) : 0;
this.state.counter.number = this.state.counter.number + amount;
this.setState(this.state);
}
shouldComponentUpdate(nextProps, nextState) {
return true;
}
render() {
console.log('render');
return (
<div>
<p>{this.state.number}</p>
<input ref={input => this.amount = input} />
<button onClick={this.handleClick}>+</button>
</div>
)
}
}
ReactDOM.render(
<Caculator />,
document.getElementById('root')
)
+ import _ from 'lodash';
handleClick = () => {
let amount = this.amount.value ? Number(this.amount.value) : 0;
let state = _.cloneDeep(this.state);
state.counter.number = this.state.counter.number + amount;
this.setState(state);
}
shouldComponentUpdate(nextProps, nextState) {
for (const key in nextState) {
if (this.State[key] !== nextState[key]) {
return true;
}
}
return false;
}
shouldComponentUpdate(nextProps, prevState) {
return !_.isEqual(prevState, this.state);
}
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { is, Map } from 'immutable';
class Caculator extends Component {
state = {
counter: Map({ number: 0 })
}
handleClick = () => {
let amount = this.amount.value ? Number(this.amount.value) : 0;
let counter = this.state.counter.update('number', val => val + amount);
this.setState({counter});
}
shouldComponentUpdate(nextProps = {}, nextState = {}) {
if (Object.keys(this.state).length !== Object.keys(nextState).length) {
return true;
}
for (const key in nextState) {
if (!is(this.state[key], nextState[key])) {
return true;
}
}
return false;
}
render() {
return (
<div>
<p>{this.state.counter.get('number')}</p>
<input ref={input => this.amount = input} />
<button onClick={this.handleClick}>+</button>
</div>
)
}
}
ReactDOM.render(
<Caculator />,
document.getElementById('root')
)
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types'
import { createStore, combineReducers, applyMiddleware } from 'redux'
import { Provider, connect } from 'react-redux'
import immutable, { is, Map } from 'immutable';
import PureComponent from './PureComponent';
const ADD = 'ADD';
const initState = Map({ number: 0 });
function counter(state = initState, action) {
switch (action.type) {
case ADD:
return state.update('number', (value) => value + action.payload);
default:
return state
}
}
const store = createStore(counter);
class Caculator extends PureComponent {
render() {
return (
<div>
<p>{this.props.number}</p>
<input ref={input => this.amount = input} />
<button onClick={() => this.props.add(this.amount.value ? Number(this.amount.value) : 0)}>+</button>
</div>
)
}
}
let actions = {
add(payload) {
return { type: ADD, payload }
}
}
const ConnectedCaculator = connect(
state => ({ number: state.get('number') }),
actions
)(Caculator)
ReactDOM.render(
<Provider store={store}><ConnectedCaculator /></Provider>,
document.getElementById('root')
)
import { combineReducers } from 'redux-immutable';
function combineReducers(reducers) {
return function (state = Map(), action) {
let newState = Map();
for (let key in reducers) {
newState = newState.set(key, reducers[key](state.get(key), action));
}
return newState;
}
}
let reducers = combineReducers({
counter
});
const ConnectedCaculator = connect(
state => {
return ({ number: state.getIn(['counter', 'number']) })
},
actions
)(Caculator)
import React from "react";
import ReactDOM from "react-dom";
import { createStore, applyMiddleware } from "redux";
import { Provider } from "react-redux";
import { combineReducers } from 'redux-immutable';
import createHistory from "history/createBrowserHistory";
import { Route } from "react-router";
import { Map } from 'immutable';
import {
ConnectedRouter,
routerMiddleware,
push,
LOCATION_CHANGE
} from "react-router-redux";
const initialRouterState = Map({
location: null,
action: null
});
export function routerReducer(state = initialRouterState, { type, payload = {} } = {}) {
if (type === LOCATION_CHANGE) {
const location = payload.location || payload;
const action = payload.action;
return state
.set('location', location)
.set('action', action);
}
return state;
}
const history = createHistory();
const middleware = routerMiddleware(history);
const store = createStore(
combineReducers({
router: routerReducer
}),
applyMiddleware(middleware)
);
window.push = push;
window.store = store;
let Home = () => <div>Home</div>
let About = () => <div>About</div>
let Topics = () => <div>Topics</div>
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
</div>
</ConnectedRouter>
</Provider>,
document.getElementById("root")
);
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { createStore, combineReducers, applyMiddleware } from "redux";
import { Provider } from "react-redux";
import createHistory from "history/createBrowserHistory";
import { Router, Route } from "react-router";
import { Link } from "react-router-dom";
import PropTypes from 'prop-types';
// import {
// ConnectedRouter,
// routerReducer,
// routerMiddleware,
// push
// } from "react-router-redux";
const CALL_HISTORY_METHOD = '@@router/CALL_HISTORY_METHOD';
const LOCATION_CHANGE = 'LOCATION_CHANGE';
var initialRouteState = {
location: null
}
class ConnectedRouter extends Component {
static contextTypes = {
store: PropTypes.object
};
handleLocationChange = (location) => {
this.store.dispatch({
type: LOCATION_CHANGE,
payload: location
});
}
componentWillMount() {
this.store = this.context.store;
this.history = this.props.history;
history.listen(this.handleLocationChange);
}
render() {
return <Router {...this.props} />
};
}
function routerReducer(state = initialRouteState, action) {
let { type, payload } = action;
if (type === LOCATION_CHANGE) {
return { ...state, location: payload };
}
return state;
}
function routerMiddleware(history) {
return function () {
return function (next) {
return function (action) {
if (action.type !== CALL_HISTORY_METHOD) {
return next(action);
}
var _action$payload = action.payload,
method = _action$payload.method,
args = _action$payload.args;
history[method].apply(history, args);
};
};
};
}
//push
function push(...args) {
return {
type: CALL_HISTORY_METHOD,
payload: { method: 'push', args: args }
};
}
// Create a history of your choosing (we're using a browser history in this case)
const history = createHistory();
// Build the middleware for intercepting and dispatching navigation actions
const middleware = routerMiddleware(history);
// Add the reducer to your store on the `router` key
// Also apply our middleware for navigating
const store = createStore(
combineReducers({
router: routerReducer
}),
applyMiddleware(middleware)
);
window.push = push;
window.store = store;
// Now you can dispatch navigation actions from anywhere!
// store.dispatch(push('/foo'))
let Home = () => <div>Home</div>
let About = () => <div>About</div>
ReactDOM.render(
<Provider store={store}>
{/* ConnectedRouter will use the store from Provider automatically */}
<ConnectedRouter history={history}>
<div>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</div>
</ConnectedRouter>
</Provider>,
document.getElementById("root")
);