React Hooks 与 Immutable 数据流实战 note05

搭建项目基本骨架【磨刀不误砍柴工】
对应分支 chapter2
![原始仓]https://github.com/sanyuan0704/react-cloud-music/tree/chapter2

基本搭建三步走

  1. 路由配置和应用部分
  2. 公共组件开发
  3. redux的store创建和引入

一、路由创建

路由文件编写

应用结构从路由文件入手,整理思路
应用骨架 顶部固定内容及tab,下面对应不同功能组件

  1. 安装依赖
npm install react-router react-router-dom react-router-config --save
  1. 编写路由
//routes/index.js
import React from 'react';
import { Redirect } from "react-router-dom";
import Home from '../application/Home';
import Recommend from '../application/Recommend';
import Singers from '../application/Singers';
import Rank from '../application/Rank';

export default [
  {
    path: "/",
    component: Home,
    routes: [
      {
        path: "/",
        exact: true,
        render: () => (
          <Redirect to={"/recommend"}/>
        )
      },
      {
        path: "/recommend",
        component: Recommend
      },
      {
        path: "/singers",
        component: Singers
      },
      {
        path: "/rank",
        component: Rank
      }
    ]
  }
]

路由生效,在App根组件中导入路由配置

import React from 'react';
import { GlobalStyle } from  './style';
import { renderRoutes } from 'react-router-config';//renderRoutes 读取路由配置转化为 Route 标签
import { IconStyle } from './assets/iconfont/iconfont';
import routes from './routes/index.js';
import { HashRouter } from 'react-router-dom';

function App () {
  return (
    <HashRouter>
      <GlobalStyle></GlobalStyle>
      <IconStyle></IconStyle>
      { renderRoutes (routes) }
    </HashRouter>
  )
}

export default App;

新建组件文件

//src/appliction/Home/index.js
import React from 'react';

function Home (props) {
  return (
    <div>Home</div>
  )
}

export default React.memo (Home);

然后类似的,创建 Recommend、Singers 和 Rank 组件。

启动项目,打开页面,你可以看到 "home" 已经显示到屏幕,但是这还不够,我们需要展示下面的功能组件,但是你在地址后面加上 /recommend,却并没有显示 Recommend 组件相应的内容,因为 renderRoutes 这个方法只渲染一层路由,之前 Home 处于数组第一层,后面的功能组件在第二层,当然不能正常渲染啦。其实要解决这个问题也非常简单,只需在 Home 中再次调用 renderRoutes 即可。

//src/appliction/Home/index.js
import React from 'react';
import { renderRoutes } from "react-router-config";

function Home (props) {
const { route } = props;

return (


Home

{ renderRoutes (route.routes) }

)
}

export default React.memo (Home);
好,现在你可以访问 /recommend 路由,应该可以看到 Recommend 中的内容。同理,现在也可以正常访问其它的路由啦。

二、公共组件开发

全局样式开发

assets/global-style.js
// 扩大可点击区域
const extendClick = () => {
return position: relative; &:before { content: ''; position: absolute; top: -10px; bottom: -10px; left: -10px; right: -10px; };
}
// 一行文字溢出部分用... 代替
const noWrap = () => {
return text-overflow: ellipsis; overflow: hidden; white-space: nowrap;
}

export default {
'theme-color': '#d44439',
'theme-color-shadow': 'rgba (212, 68, 57, .5)',
'font-color-light': '#f1f1f1',
'font-color-desc': '#2E3030',
'font-color-desc-v2': '#bba8a8',// 略淡
'font-size-ss': '10px',
'font-size-s': '12px',
'font-size-m': '14px',
'font-size-l': '16px',
'font-size-ll': '18px',
"border-color": '#e4e4e4',
'background-color': '#f2f3f4',
'background-color-shadow': 'rgba (0, 0, 0, 0.3)',
'highlight-background-color': '#fff',
extendClick,
noWrap
}

顶部栏开发

  1. home/目录下创建 style.js 创建样式
    import styled from'styled-components';
    import style from '../../assets/global-style';

export const Top = styled.divdisplay: flex; flex-direction: row; justify-content: space-between; padding: 5px 10px; background: ${style ["theme-color"]}; &>span { line-height: 40px; color: #f1f1f1; font-size: 20px; &.iconfont { font-size: 25px; } }
很简单的布局和样式,就不过多解释了。接下来在 Home 组件应用这些样式,

//src/appliction/Home/index.js
import React from 'react';
import { renderRoutes } from "react-router-config";
import { Top } from './style';

function Home (props) {
  const { route } = props;

  return (
    <div>
      <Top>
        <span className="iconfont menu">&#xe65c;</span>
        <span className="title">WebApp</span>
        <span className="iconfont search">&#xe62b;</span>
      </Top>
      { renderRoutes (route.routes) }
    </div>
  )
}

export default React.memo (Home);
接着来编写上面的 tab 栏,先定义样式:

export const Tab = styled.div`
  height: 44px;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  background: ${style ["theme-color"]};
  a {
    flex: 1;
    padding: 2px 0;
    font-size: 14px;
    color: #e4e4e4;
    &.selected {
      span {
        padding: 3px 0;
        font-weight: 700;
        color: #f1f1f1;
        border-bottom: 2px solid #f1f1f1;
      }
    }
  }
`
export const TabItem = styled.div`
  height: 100%;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;

在 Home 组件中使用:

import React from 'react';
import { renderRoutes } from "react-router-config";
import {
  Top,
  Tab,
  TabItem,
} from './style';
import { NavLink } from 'react-router-dom';// 利用 NavLink 组件进行路由跳转

function Home (props){
  const { route } = props;

  return (
    <div>
      <Top>
        <span className="iconfont menu">&#xe65c;</span>
        <span className="title">Web App</span>
        <span className="iconfont search">&#xe62b;</span>
      </Top>
      <Tab>
        <NavLink to="/recommend" activeClassName="selected"><TabItem><span > 推荐 </span></TabItem></NavLink>
        <NavLink to="/singers" activeClassName="selected"><TabItem><span > 歌手 </span></TabItem></NavLink>
        <NavLink to="/rank" activeClassName="selected"><TabItem><span > 排行榜 </span></TabItem></NavLink>
      </Tab>
      { renderRoutes (route.routes) }
    </div>
  );
}
 
export default React.memo (Home);

打开页面,现在一个像样的 WebApp 头部就出来了,并且点击不同的 tab

三、redux准备

成熟的状态管理库 实现单一数据源

依赖安装

npm install redux redux-thunk redux-immutable react-redux immutable --save

创建store

store文件夹下创建index.js reducer.js

项目注入store