React
有关使用包
- 使用官方提供的react脚手架搭建的小型项目:create-react-app
- react中使用路由react-router-dom
- 单向数据流使用的是redux,通过redux-thunk中间件实现异步操作
- 使用单向数据流与路由中,通过props逐级传递有点麻烦,性能不佳,使用中间件形式的react-redux构造装饰器,可以访问全局数据流
在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各部分
- store :数据,store全局仅有唯一的store
- action: 操作,通过触发action改变store的状态,stroe的状态不能不能直接修改
- 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如何被不同路由下的组件使用与访问
- 在react的入口文件中注入store,使其可以被全局路由访问
- 在对应的组件中引入需用的actino,stroe是直接访问全局的,action是按需引入
- 以下为例子
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可优化的各方面
- 在react 16 之前的版本可以通过简单的遍历组件中的props或者state数据的变化监听数据是否被更新,来控制组件的渲染,一个正常的组件在父组件的状态被改变的情况下,会触发render,如果是列表之类的组件render多了就会性能差,可以通过 shouldComponentUpdate 钩子函数来决定组件是否接受更新
- 在react 16后,官方提出类似Component的接口 PureComponent,react可以自动帮你决定组件是否接受更新
- 在组件的使用时,必须对其赋于 全局唯一的KEY。在列表的渲染中不推荐使用循环的下标作为 key 在列表的渲染中,如果对列表某条数据删除会改变其上下的组件的 key 改变
- 增大组件的复用性