<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 1\. 可共享可變狀態是萬惡之源 ~~~ let objA = { name: 'zfpx' }; let objB = objA; objB.name = '9'; console.log(objA.name); ~~~ ## 2\. 什么是 Immutable * Immutable Data 就是一旦創建,就不能再被更改的數據。對 Immutable 對象的任何修改或添加刪除操作都會返回一個新的 Immutable 對象 * Immutable 實現的原理是 Persistent Data Structure(持久化數據結構),也就是使用舊數據創建新數據時,要保證舊數據同時可用且不變 同時為了避免 deepCopy 把所有節點都復制一遍帶來的性能損耗 * Immutable 使用了 Structural Sharing(結構共享),即如果對象樹中一個節點發生變化,只修改這個節點和受它影響的父節點,其它節點則進行共享 * [immutable-js](https://facebook.github.io/immutable-js/docs/#/) [immutablejs](http://img.zhufengpeixun.cn/immutablejs.gif) ## 3\. Immutable類庫 內部實現了一套完整的 Persistent Data Structure,還有很多易用的數據類型。像`Collection`、`List`、`Map`、`Set`、`Record`、`Seq` ### 3.1 Map | 方法 | 作用 | | --- | --- | | 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); ~~~ ### 3.2 List | 方法 | 作用 | | | --- | --- | --- | | 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()); ~~~ ## 4\. Immutable優勢 ### 4.1 降低復雜度 ~~~ let obj1 = immutable.fromJS({ user: { name: 'zfpx', age: 8 }, 'k': 'v' }); let obj2 = obj1.setIn(['user', 'name'], 'zfpx2'); ~~~ ### 4.2 節省內存 ~~~ 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')); ~~~ ### 4.3 方便回溯 只要把每次的狀態都放在一個數組中就可以很方便的實現撤銷重做功能 ## 5\. React性能優化 ### 5.1 計數器 * 每次調用setState的時候組件都會刷新 ~~~ 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') ) ~~~ ### 5.2 深度克隆+淺比較 * 可以通過淺比較判斷是否需要刷新組件 * 淺比較要求每次修改的時候都通過深度克隆每次都產生一個新對象 ~~~ + 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; } ~~~ ### 5.3 深比較 * 也可以通過深度比較的方式判斷兩個狀態的值是否相等 * 這樣做的話性能非常低 ~~~ shouldComponentUpdate(nextProps, prevState) { return !_.isEqual(prevState, this.state); } ~~~ ### 5.4 immutable ~~~ 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') ) ~~~ ## 6\. redux+immutable手工實現 ~~~ 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') ) ~~~ ## 7\. redux-immutable中間件 * [redux-immutable](https://github.com/gajus/redux-immutable#readme) ~~~ 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) ~~~ ## 8\. react-router-redux使用 ~~~ 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") ); ~~~ ## 9\. react-router-redux實現 ~~~ 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") ); ~~~ ![](https://img.kancloud.cn/aa/93/aa93ca37952f593f3afdd7efe82d36d9_998x435.png) ~~~ let {List,fromJS,is} = require('immutable'); let l1 = fromJS([1,2,3]); console.log(l1); console.log(l1.size); let l2 = l1.push(4); console.log(l2); let l3 = l2.pop(); let l4 = l3.update(2,x=>x*2); console.log(l4);//1,2,6 let l5 = l4.concat([5,6]); let l6 = l5.map(x=>x*2); let l7 = l6.filter(x=>x%2===0); let num = l7.get(0); let exist2 = l7.includes(2); ~~~ ~~~ let {Map,fromJS,is} = require('immutable'); let obj1 = fromJS({user:{name:'zhufeng'}}); let obj2 = obj1.set('age','10'); let obj3 = obj2.set('home','beijing'); console.log(obj1.get('user') === obj3.get('user')) ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看