初次入坑 React

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. 增大组件的复用性
    原文作者:Kam1995
    原文地址: https://segmentfault.com/a/1190000015275200
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞