React實戰篇(React仿今日頭條)
阿新 • • 發佈:2018-12-16
前言
上次初學用 react
寫了個後臺管理,這次便尋思寫個移動端的專案。便有了這次的這個專案。
這個專案以前寫了個 vue
的版本。有興趣的可以 點選進入
賬號: vue-toutiao
密碼: 123456
技術棧
react
+ react-redux
+ react-router
+ webpack
結構:
- build: webpack配置
- config: 專案配置引數
- src
actions
: 存放 action 方法assets
: 靜態資原始檔,存放圖片啥的components
: 常用元件reducers
: 存放 reducerrouter
store
: 狀態管理 reduxstyles
: 樣式檔案utils
: 常用封裝views
: 檢視頁面
- static: 靜態檔案: 存放 favicon.ico 等等
效果演示
知識點
按需載入
通過 import()
方法載入元件, 在通過高階元件處理 import
返回的 Promise
結果。
// asyncComponent.js import React from 'react' export default loadComponent => ( class AsyncComponent extends React.Component { state = { Component: null, } async componentDidMount() { if (this.state.Component !== null) return try { const {default: Component} = await loadComponent() this.setState({ Component }) }catch (err) { console.error(`Cannot load component in <AsyncComponent />`); throw err } } render() { const { Component } = this.state return (Component) ? <Component {...this.props} /> : null } } ) 複製程式碼
如下使用
import asyncComponent from './asyncComponent'
const Demo = asyncComponent(() => import(`views/demo.js`))
<Route path="/demo" component={Demo}/>
複製程式碼
路由設定
統一配置路由,及路由狀態
import asyncComponent from './asyncComponent' const _import_views = file => asyncComponent(() => import(`views/${file}`)) export const loyoutRouterMap = [ { path: '/', name: '首頁', exact: true, component: _import_views('Home') }, { path: '/video', name: '視訊', component: _import_views('Video') }, { path: '/headline', name: '微頭條', component: _import_views('Headline') }, { path: '/system', name: '系統設定', auth: true, component: _import_views('System') } ] 複製程式碼
登入攔截
通過路由配置中 auth
屬性來判斷是否需要登入 如以下配置
{
path: '/system',
name: '系統設定',
auth: true,
component: _import_views('System')
}
複製程式碼
登陸配置及判斷
// authRoute.js
import React from 'react'
import store from '../store'
import { Route, Redirect } from 'react-router-dom'
export default class extends React.Component {
render () {
let {component: Component, ...rest} = this.props
// 是否登入
if (!store.getState().user.user.name) {
return <Redirect to='/login' />
}
return <Route {...rest} component={Component}/>
}
}
// 生成route
const renderRouteComponent = routes => routes.map( (route, index) => {
if (route.auth) { // 需要許可權登入
return <AuthRoute key={index} {...route}/>
}
return <Route key={index} {...route}/>
})
複製程式碼
路由動畫
然後通過 history.slideStatus 來判斷如何動畫
redux-thunk處理action非同步
用 redux-actions
來書寫 action 跟 reducer
// action.js
import { createAction } from 'redux-actions'
import axios from 'utils/axios'
export const getHeadlineList = (params) => dispatch => {
return new Promise( (resolve, reject) => {
axios.get('headline/list', params)
.then( res => {
const list = res.data.list
dispatch(createAction('GET_HEADLINE_LIST')(list))
resolve(list)
}).catch( err => {
reject(err)
})
})
}
// reducer.js
import { handleActions } from 'redux-actions'
import { combineReducers } from 'redux'
const state = {
headlineList: []
}
const headline = handleActions({
GET_HEADLINE_LIST: (state, action) => {
let list = action.payload
state.headlineList = state.headlineList.concat(list)
return {...state}
}
}, state)
export default combineReducers({
headline
})
// store.js
// redux-thunk配置
import { createStore, compose, applyMiddleware } from 'redux'
import reducer from '../reducers'
import thunk from 'redux-thunk'
const configureStore => createStore(
reducer,
compose(
applyMiddleware(thunk)
)
)
export default configureStore()
複製程式碼
還有一些零零散散的知識點,就不介紹了,具體可以到 github 上檢視。
作者:cd-dongzi 連結:https://juejin.im/post/5aca3be56fb9a028e46eeb69 來源:掘金 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。