初次入坑 React

Kam1995發表於2018-06-13

React

有關使用包

  1. 使用官方提供的react腳手架搭建的小型專案:create-react-app
  2. react中使用路由react-router-dom
  3. 單向資料流使用的是redux,通過redux-thunk中介軟體實現非同步操作
  4. 使用單向資料流與路由中,通過props逐級傳遞有點麻煩,效能不佳,使用中介軟體形式的react-redux構造裝飾器,可以訪問全域性資料流
  5. 在react專案中還是用了懶載入react-loadable

    import Loadable from `react-loadable`
    const Loading = ({      //自定義公用載入時頁面
        pastDelay,
        timedOut,
        error
    }) => {
        if(pastDelay) {
            return <div></div>;
        } else if(timedOut) {
            return <div>Taking a long time...</div>;
        } else if(error) {
            return <div>Error!</div>;
        }
        return null;
    }
    //路由中頁面  懶載入 view
    const MusicIndex = Loadable({
        loader: () =>
            import(`./component/MusicIndex/MusicIndex`),
        loading: Loading,
        timeout: 10000
    })

react中的生命週期

# react 的基本元件生命週期如下
1. constructor 元件的建構函式:接受父元件的引數,初始化state,繫結函式等等的操作
2. componentWillMount 元件渲染之前,每次元件渲染都會觸發一次
3. componentDidMount 元件渲染之後,每次元件渲染都會觸發一次,子元件都掛載好,可以使用refs,可以使用非同步方法,防止阻塞UI
4. componentWillReceiveProps 該函式接收到新的props才會被呼叫,render不會觸發該函式
5. shouldComponentUpdate 在元件接收到新的props或者state時被呼叫。在初始化時或者使用forceUpdate時不被呼叫。 
6. componentWillUpdate 該函式接收到新的props或者state與render之前才會被呼叫,初始化不會觸發該函式
7. componentDidUpdate 該函式在元件完成更新後立即呼叫。在初始化時不會被呼叫。
8. componentWillUnmount 該函式為元件被移除(解除安裝)時被呼叫
class App extends Component {
    constructor(props) {
        super(props)
    }
    componentWillMount(){}
    componentDidMount() {}
    componentWillReceiveProps(newProps) {}
    shouldComponentUpdate(newProps, newState) {
        return true;
    }
    componentWillUpdate(nextProps, nextState) {}
    componentDidUpdate(prevProps, prevState) {}
    componentWillUnmount() {}
    render() {
        return(
            <div className="App">展示APP頁面</div>
        );
    }
}

react中使用路由

import { HashRouter as Router, Route, Link } from "react-router-dom"
import { MusicIndex } from "./../MusicIndex.js"
import { MusicRanking } from "./../MusicRanking.js"
import { MusicCollection } from "./../MusicCollection.js"
import { MusicPersonal } from "./../MusicPersonal.js"

render() {
    return(
        <div className="App">
            <Router>
                <div className="app-box-view">
                    <Route exact path="/" component={ MusicIndex } />
                    <Route path="/ranking" component={ MusicRanking } />
                    <Route path="/collection" component={ MusicCollection } />
                    <Route path="/personal" component={ MusicPersonal } />
                </div>
            </Router>
            <div className="App-tabbar">
                <span onClick={ window.location.hash = `/`}>頁面一</span>
                <span onClick={ window.location.hash = `/ranking`}>頁面二</span>
                <span onClick={ window.location.hash = `/collection`}>頁面三</span>
                <span onClick={ window.location.hash = `/personal`}>頁面四</span>
            </div>
            <Audio></Audio>
        </div>
    );
}

react中使用單向資料流redux

redux
  • redux分為3各部分

    1. store :資料,store全域性僅有唯一的store
    2. action: 操作,通過觸發action改變store的狀態,stroe的狀態不能不能直接修改
    3. Reducers 執行,通過action反饋的操作去執行,直接修改store的狀態
  • redux 在大型專案中可與 vuex 一樣實現模組化管理。redux 通過自帶的函式 combineReducers 對自身切割分為多個模組。
redux例子
1. redux分割例子
import { combineReducers } from "redux"
import { albumItem } from `./reducers/MusicAlbumItem`
import { ranking } from `./reducers/MusicRanking`
import { user } from `./reducers/MusicUser`
import { collection } from `./reducers/MusicCollection`

export const rootReducer = combineReducers({
    player,
    ranking,
    user,
    collection
})

2. 單獨分割出來redux的例子
const R_CHANGE = "改變快取排行版"
const R_INIT = "重置排行版"
const R_LOADING = "排行版列表加在完畢"
//以下為store
let rankingStore = {
    rank:[],
    target:{
        id:0,
        playlist:{}
    },
    loading:true
}
//以下為reducers
export const ranking = (state = rankingStore, action) => {
    switch(action.type) {
        case R_INIT:
            state.rank = action.list
            return Object.assign({}, state)
        case R_CHANGE:
            state.target = action.list
            return Object.assign({}, state)
        case R_LOADING:
            state.loading = false
            return Object.assign({}, state)
        default:
            return state
    }
}
//以下為action
export function r_change(list) {
    return {
        type: R_CHANGE,
        list:list
    }
}
export function r_init(list) {
    return {
        type: R_INIT,
        list:list
    }
}
export function r_loading() {
    return {
        type: R_LOADING
    }
}
redux如何被不同路由下的元件使用與訪問
  1. 在react的入口檔案中注入store,使其可以被全域性路由訪問
  2. 在對應的元件中引入需用的actino,stroe是直接訪問全域性的,action是按需引入
  3. 以下為例子
import React from `react`;
import ReactDOM from `react-dom`
import { createStore, applyMiddleware, compose } from `redux`
import { BrowserRouter } from `react-router-dom`
import registerServiceWorker from `./registerServiceWorker`
import `./index.css`
import App from `./App`
import { rootReducer } from `./redux/index`
import thunk from `redux-thunk`
import { Provider } from `react-redux`

const store = createStore(rootReducer, compose(
    applyMiddleware(thunk),
    window.devToolsExtension ? window.devToolsExtension() : f => f
))
//通過路由注入store,使其可被全域性訪問stroe(前提是需訪問的元件引入對應的redux)
ReactDOM.render(
    (<Provider store={store}>
        <BrowserRouter>
            <App />
        </BrowserRouter>
    </Provider>),
    document.getElementById(`root`)
);
react可優化的各方面
  1. 在react 16 之前的版本可以通過簡單的遍歷元件中的props或者state資料的變化監聽資料是否被更新,來控制元件的渲染,一個正常的元件在父元件的狀態被改變的情況下,會觸發render,如果是列表之類的元件render多了就會效能差,可以通過 shouldComponentUpdate 鉤子函式來決定元件是否接受更新
  2. 在react 16後,官方提出類似Component的介面 PureComponent,react可以自動幫你決定元件是否接受更新
  3. 在元件的使用時,必須對其賦於 全域性唯一的KEY。在列表的渲染中不推薦使用迴圈的下標作為 key 在列表的渲染中,如果對列表某條資料刪除會改變其上下的元件的 key 改變
  4. 增大元件的複用性

相關文章