react配合antd元件實現的管理系統demo

兜兜裡有sugar發表於2018-04-23

前言:此文需要有一定react,redux基礎,具體學習資料請科學上網。

|-src  			//開發
|----assets  		//css,img資源
|----unit.js  		//公用方法
|----routers            //路由配置
|----containers         //業務邏輯頁面
|----component          //通用元件
複製程式碼

啟動

# install dependencies
npm install

# serve with hot reload at localhost:8080
npm start

# build for production with minification
npm run build
複製程式碼

使用create-react-app腳手架

具體基礎配置請參考

配合antd元件實現的管理系統demo, 線上地址

開發前反思

1. 按需載入

webpack的import動態載入的模組的函式,import(引數),引數為模組地址。

注意:import後會返回一個promise物件。

import('/components/chart').then(mud => {
    dosomething(mod)
});
複製程式碼

本demo構建了非同步載入元件Bundle,具體程式碼請見

class Bundle extends Component {
  constructor(props) {
      super(props);
      this.state = {
          mod: null
      };
  }
  unmount = false
  componentDidMount = () => {
    // 載入元件時,開啟全域性loading
    this.props.dispatch(loading(true))
    this.load(this.props)
  }
  componentWillUnmount = () => {
    this.unmount = true
  }
  
  componentWillReceiveProps(nextProps) {
      if (nextProps.load !== this.props.load) {
          this.load(nextProps)
      }
  }
  load(props) {
      if (this.state.mod) {
          return true
      }
      //注意這裡,使用Promise物件; mod.default匯出預設
      props.load().then((mod) => {
          if (this.unmount) {
              // 離開元件時,不非同步執行setState
              this.props.dispatch(loading(false))
              return false
          }
          this.setState({
              mod: mod.default ? mod.default : mod
          }, _ => {
            // 元件載入完畢,關閉loading
            this.props.dispatch(loading(false))
          });
      });
  }

  render() {
      return this.state.mod ? this.props.children(this.state.mod) : null;
  }
}
複製程式碼

具體使用

  <Bundle load={() => import('路徑')}>
    {Comp => {
      return Comp ? <Comp /> : <div>載入中...</div>
    }}
  </Bundle>
複製程式碼

2. 全域性loading

配合redux,dispatch => reducer更新 => mapstate更新,在根元件進行loading的渲染

詳細請見本demo地址 src/routers/router.js——render函式

3. 配置路由物件

專案佈局如下

react配合antd元件實現的管理系統demo
本demo使用的是router4,官方文件演示為單行Route(如vue種的router),未有統一配置物件。 管理系統基本圍繞著content進行業務開發,構建通用配置有助於開發 構建router.config.js

const routers = [
  {
    menuName: '主頁',
    menuIco: 'home',
    component: 'home/home.js', // 主頁
    path: '/admin/home' // 主頁
  },
  {
    menuName: '使用者',
    menuIco: 'user',
    children: [
      {
        menuName: '使用者列表',
        component: 'user/list.js', // 主頁
        path: '/admin/user/list' // 主頁
      }
    ]
  },
  {
    menuName: '多級選單',
    menuIco: 'setting',
    children: [
      {
        menuName: '多級選單2',
        children: [
          {
            menuName: '選單',
            component: 'user/list.js', // 主頁
            path: '/admin/user/list3' // 主頁
          }
        ]
      }
    ]
  },
  {
    menuName: '關於我',
    menuIco: 'smile-o',
    component: 'about/about.js', // 主頁
    path: '/admin/about' // 主頁
  }
]
複製程式碼

實現思路,最外層佈局為Admin,content被Admin包裹,那麼可以利用this.props.children,把內容打入content中。(利用bundle元件非同步載入後塞入元件進行渲染)

<Admin>
    <Content { ...this.props } breadcrumb={this.state.breadcrumb}>
        {this.props.children}
    </Content>
</Admin>
複製程式碼
// Content元件內部
render() {
    return (
        <div> 
            {this.props.children}
        </div>
    )
}
// 本demo實現,詳見src/routers/router.js
<Route
  path="/admin"
  render={item => (
    <Admin {...item} { ...this.props }>
      {initRouters.map(el => this.deepItem(el, { ...this.props, ...item}))}
    </Admin>
  )}
/>
複製程式碼

4. 配置通用reducer

多人配合開發,一些業務場景的元件需要狀提升(不理解狀態提升的同學,請科學上網)

import otherReducers from './otherReducers'
const App =  combineReducers({
    rootReducers,
    ...otherReducers // 其他需要增加的reducers
})
複製程式碼

5. 登陸驗證

利用withRouter函式,頁面進行路由跳轉時觸發該函式

const newWithRouter = withRouter(props => {
    // ....
})
複製程式碼

若未登入,則返回

return <Redirect  to="/login" />
複製程式碼

6. 路由攔截

同上,根據路由配置與許可權,返回相應的選單或遮蔽

return <Redirect  to={其他} />
複製程式碼

7 其他配置

7-1. 自定義樣式
// 修改webpack.config.dev.js 和 webpack.config-prod.js 配置檔案
{
    test: /\.(css|less)$/,
    // 匹配src的都自動載入css-module
    include: [/src/],
    exclude: [/theme/],
    use: [
        require.resolve('style-loader'), {
            loader: require.resolve('css-loader'),
            options: {
                importLoaders: 1,
                modules: true, // 新增對css modules的支援
                localIdentName: '[path]___[name]__[local]___[hash:base64:5]'
            }
        }, {
            loader: require.resolve('postcss-loader'),
            options: {
                // Necessary for external CSS imports to work
                // https://github.com/facebookincubator/create-react-app/issues/2677
                ident: 'postcss',
                plugins: () => [
                    require('postcss-flexbugs-fixes'),
                    autoprefixer({
                        browsers: [
                            '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway
                        ],
                        flexbox: 'no-2009'
                    })
                ]
            }
        }, {
            loader: require.resolve('less-loader') // compiles Less to CSS
        }
    ]
}, {
    // 不匹配node_modules,theme的都不能自動載入css-module
    test: /\.(css|less)$/,
    include: [/node_modules/,/theme/],
    use: [
        {
            loader: "style-loader"
        }, {
            loader: "css-loader",
            options: {
                importLoaders: 1
            }
        }, {
            loader: require.resolve('less-loader') // compiles Less to CSS
        }
    ]
},
複製程式碼

使用: 在App.js中直接匯入

import  './assets/theme/App.less'
複製程式碼
7-2. 熱更新

步驟一:

// 安裝react-hot-loader 
npm install --save-dev react-hot-loader  
複製程式碼

步驟二:

在webpack.config.js 的 entry 值里加上 react-hot-loader/patch

步驟三:

webpackDevServer.config.js中hot設定為true

步驟四: 在webpack.config.dev.js中在babel-loader中plugins加入react-hot-loader/babel

{
    test: /\.(js|jsx|mjs)$/,
    include: paths.appSrc,
    loader: require.resolve('babel-loader'),
    options: {
        // This is a feature of `babel-loader` for webpack (not Babel itself). It
        // enables caching results in ./node_modules/.cache/babel-loader/ directory for
        // faster rebuilds.
        cacheDirectory: true,
        plugins: [
            'react-hot-loader/babel'
        ]
    }
},
複製程式碼

步驟五:

重寫index.js,App掛載

import { AppContainer } from 'react-hot-loader'

const render = Component => {
    ReactDOM.render(
        <AppContainer>
            <Component></Component>
        </AppContainer>,
        document.getElementById('root')
    )
}

render(App)

if(module.hot) {
    module.hot.accept('./App',() => {
        render(App);
    });
}
複製程式碼
7-3. 本地瀏覽

直接在package.json中加入

homepage:'.'
複製程式碼

後記:使用react與vue的感悟

react是函數語言程式設計,程式碼難度、學習曲度、裝逼指數,社群生態多樣性相比vue更高一點。

vue提供了大量的指令降低了開發難度,詳細完善的文件,上手更快。

react提供較少的api,相比vue的指令,業務場景的功能需要自己實現,難度更高一點

vue適合中小型專案,單兵、少量人員配合快速開發

react適合大型專案,多人協作

github: https://github.com/treasureDouDou

相關文章