注意
- 涉及浮动时要将浮动元素的父元素设为BFC元素,防止浮动元素溢出。
- 被包裹在BFC中的浮动不会影响BFC外部其他元素的布局(也就是可以使用BFC来清除浮动)
<img>
标签必须设置alt
属性。- 从App.js中可知Provider提供给Home组件的store是总store,而src-reducer.js中我们知道总store由header的store和home的store组成,所以我们需要先使用
.get("home")
获取到home的store才能继续获取她下面的数据。
路由
- 路由指根据url的不同显示不同的内容
在React中使用路由功能
- 需要借助第三方模块
react-router-dom
安装react-router-dom
1 | yarn add react-router-dom |
使用react-router-dom
- **引入
react-router-dom
中的BrowserRouter
和Route
**。Route
组件:定义路由组件。path
属性:(字符串)定义路由路径render
属性:(函数)在该路径下渲染的内容component
属性:(组件)在该路径下渲染的组件exact
属性:(可省略属性值)准确匹配路径。如不使用该属性,则默认是模糊匹配path
BrowserRouter
组件:包含各个路由组件。
在App.js中:
1 | import React, { Component } from 'react'; |
可以看到访问/detail
时同时出现了/
和/detail
的内容:
加上exact
属性:
1 | <Route path="/" exact render={() => <div>home</div>}></Route> |
首页组件的拆分
- 在src下新建pages文件夹,表示项目有多少个页面。
- pages下新建detail文件夹和home文件夹,表示有home和detail两个页面
- 在这两个文件夹下分别新建index.js文件。在index.js中放置需要被渲染的组件。
- 在App.js中引入两个组件,分别渲染在两个
Route
组件中。
Home组件
src-pages-home-index.js:
1 | import React, { Component } from 'react' |
Detail组件
src-pages-detail-index.js:
1 | import React, { Component } from 'react' |
App中引入并显示在路由上
App.js中,引入Home、Home两个组件:
1 | import Home from "./pages/home"; |
使用component属性使路由分别显示对应的组件:
1 | <Route path="/" exact component={Home}></Route> |
完善Home组件
刚刚只是写了最简单的一个样子,现在来完善一下。
在src-pages-home下新建style.js文件:
1 | import styled from "styled-components"; |
在Home组件中引入并使用:
1 | import React, { Component } from 'react'; |
注意:涉及浮动时要将浮动元素的父元素设为BFC元素,防止浮动元素溢出。
Home组件再拆分
Home组件下还要拆分一些组件:
- home文件夹下新建components文件夹用于存放其他组件。
- Topic.js
- List.js
- Recommend.js
- Writer.js
- components下的组件都先简单设置以后放入Home组件来展示一下位置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30import React, { Component } from 'react';
import {
HomeWrapper,
HomeLeft,
HomeRight,
} from "./style";
import List from "./components/List";
import Recommend from "./components/Recommend";
import Topic from "./components/Topic";
import Writer from "./components/Writer";
class Home extends Component {
render() {
return (
<HomeWrapper>
<HomeLeft>
<img className="banner-img" src="https://upload.jianshu.io/admin_banners/web_images/4894/23ecc55accf5c6a6c9910be966c125853d1f04a5.png?imageMogr2/auto-orient/strip|imageView2/1/w/1250/h/540" alt="banner图片" />
<Topic></Topic>
<List></List>
</HomeLeft>
<HomeRight>
<Recommend></Recommend>
<Writer></Writer>
</HomeRight>
</HomeWrapper>
)
}
}
export default Home;
Topic区域布局
- 之前每个组件都放在一个文件夹中,样式就在style.js下。
- 但是为了防止过度开发,Home组件下的所有小的组件的样式我们统一放在Home组件的style.js去定义,包括Topic组件。
pages-home-style.js:
1 | export const TopicWrapper = styled.div` |
topic.js:
1 | import React, { Component } from 'react' |
Topic的reducer设计
- 我们现在只写了一个TopicItem组件,实际上应该从数据中读取生成多个TopicItem组件。数据是保存在redux的store中的,整个项目的reducer在src的store中,它是由各个小的reducer合并而成的。
- 所以我们在Home组件下也新建一个store文件夹,用于管理home以及其下组件的数据。
- 新建reducer.js:管理home页面的数据(可将header的reducer复制一个框架过来)。
- 新建index.js:管理store中所有文件的输出,他是整个store中所有文件的出口文件。
- 项目的总reducer中引入home的reducer并将其合并。
- Topic组件中循环读取state的数据、输出对应TopicItem组件。
- Topic组件在Home组件内部,Home组件又在Provider组件内部,所以Topic组件有使用store中数据的能力,只需借助connect方法即可使用数据。
新建store-reducer.js管理数据
home-store-reducer.js中,将header的reducer复制一个框架过来,放入一些模拟数据:
1 | import { fromJS } from "immutable"; |
新建store-index.js管理文件输出
home-store-index.js:管理store中所有文件的输出,他是整个store中所有文件的出口文件:
1 | import reducer from "./reducer"; |
合并入项目总reducer
src-store-reducer.js,项目的总reducer中引入home的reducer并将其合并:
1 | import { combineReducers } from "redux-immutable"; |
Topic中循环读取state中数据
- Topic组件中循环读取state的数据、输出对应TopicItem组件。
- 此时Topic组件在Home组件内部,Home组件又在Provider组件内部,所以Topic组件有使用store中数据的能力,只需借助connect方法即可使用数据。
- 由于我们只需要读取state中数据,不需要去改变数据,所以此时connect方法的参数2可以先使用null。
- 注意
- state中的TopicList是immutable数组,需要使用get()获取数据。
- 从App.js中可知Provider提供给Home组件的store是总store,而src-reducer.js中我们知道总store由header的store和home的store组成,所以我们需要先使用
.get("home")
获取到home的store才能继续获取她下面的数据。
home-components-Topic.js:
1 | import React, { Component } from 'react'; |