前言
上次初学用 react 写了个后台管理 http://dzblog.cn/article/5aa7ef0e4f85ad06d2346688 , 这次便寻思写个移动端的项目. 便有了这次的这个项目.
这个项目以前写了个 vue 的版本. 有兴趣的可以 点击进入 http://dzblog.cn/article/5a78609ec153997e3417a6d4
模拟数据用的是 Easy Mock https://easy-mock.com/
用的是我以前写 vue-toutiao http://dzblog.cn/article/5a78609ec153997e3417a6d4 用到的数据
账号: vue-toutiao
密码: 123456
技术栈
react + react-redux + react-router + webpack
结构:
build: webpack 配置
config: 项目配置参数
src
actions: 存放 action 方法
assets: 静态资源文件, 存放图片啥的
components: 常用组件
reducers: 存放 reducer
router: 路由管理
store: 状态管理 redux
styles: 样式文件
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}/>
- })
路由动画
通过
react-router-transition
https://www.npmjs.com/package/react-router-transition 做的切换动画.
然后通过 history.slideStatus 来判断如何动画
react-router-transition 具体 API https://maisano.github.io/react-router-transition/animated-switch
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()
还有一些零零散散的知识点, 就不介绍了, 具体可以到 https://github.com/cd-dongzi/react-toutiao 上查看.
https://github.com/cd-dongzi/react-toutiao
个人博客 http://dzblog.cn/article/5aca31ccd0597d4709f5337a
在线观看地址 http://dzblog.cn/cases/react-toutiao/index.html
来源: https://juejin.im/post/5aca3be56fb9a028e46eeb69