实战详情页实现

158 阅读2分钟

image.png

我们这里只做标题和内容的布局。

这里的基本流程和之前基本一致,我就以代码来示范

image.png

1. 详情页布局

import styled from 'styled-components';

export const DetailWrapper = styled.div`
    overflow: hidden;
    width: 620px;
    margin: 0 auto;
    padding-bottom: 100px;
`;

export const Header = styled.div`
    margin: 50px 0 20px 0;
    line-height: 44px;
    font-size: 34px;
    color: #333;
    font-weight: bold;
`;

export const Content = styled.div`
    color: #2f2f2f;
    img {
        width: 100%;
    }
    p {
        margin: 25px 0;
        font-size: 16px;
        line-height: 30px;
    }
`;

class Detail extends PureComponent {
  render() {
    return (
      <DetailWrapper>
        <Header>{this.props.title}</Header>
        <Content dangerouslySetInnerHTML={{__html: this.props.content}}/>
      </DetailWrapper>
    );
  }

  componentDidMount() {
    this.props.getDetail();
  }
}
  1. 使用 axios 与 redux 管理数据并进行异步请求
import axios from "axios";
import { fromJS } from 'immutable';
import { constants } from "./index";

const defaultState = fromJS({
  title: '若是余生绵长,却只留她一人寂寥,那该有多残忍。',
  content: '<img\n' +
    '            src='http://upload-images.jianshu.io/upload_images/8202513-00d6c528c21e09be.png?imageMogr2/auto-orient/strip|imageView2/2/w/658/format/webp'/>\n' +
    '          <p>柳公子听了她的话,深情款款道:“可否换我来照顾你?”</p>\n' +
    '          <p>柳公子听了她的话,深情款款道:“可否换我来照顾你?”</p>\n' +
    '          <p>柳公子听了她的话,深情款款道:“可否换我来照顾你?”</p>\n' +
    '          <p>柳公子听了她的话,深情款款道:“可否换我来照顾你?”</p>'
});

export const changeDetail = (title, content) => ({
  type: constants.CHANGE_DETAIL,
  title,
  content
});

export const getDetail = () => {
  return (dispatch) => {
    axios.get('/api/detail.json').then((res) => {
      const result = res.data.data;
      dispatch(changeDetail(result.title, result.content));
    });
  }
};

export default (state = defaultState, action) => {
  switch (action.type) {
    case constants.CHANGE_DETAIL:
      return state.merge({
        title: action.title,
        content: action.content
      });
    default: {
      return state;
    }
  }
};

const mapDispatchToProps = (dispatch) => ({
  getDetail() {
    dispatch(actionCreators.getDetail);
  }
});

3. 设置点击不同列表页进入不同详情页

在实现点击列表页进入不同详情页时,需要通过路由传递参数来获取不同的详情页数据。下面介绍两种常用的方式:动态路由和使用路由参数。

3.1 动态路由

动态路由是指通过在路由路径中添加参数来传递数据。在这种方式下,需要修改跳转路由地址和详情页路由的匹配规则。

首先,在列表页中修改跳转路由地址,添加一个参数id,例如:

<Link key={index} to={'/detail/' + item.get('id')}>

接着,在路由配置中添加一个参数id,让详情页路由能够匹配这个id,例如:

<Route path='/detail/:id' exact component={Detail}></Route>

在详情页中,可以通过this.props.match.params.id来获取传递的id,例如:

this.props.getDetail(this.props.match.params.id);

3.2 使用路由参数

在使用路由参数时,需要在跳转路由地址中拼接一个参数,例如:

<Link key={index} to={'/detail?id=' + item.get('id')}>

在详情页路由中,需要修改路由匹配规则,例如:

<Route path='/detail' exact component={Detail}></Route>

最后,在详情页中可以通过this.props.location.search来获取传递的参数,例如:

const search = this.props.location.search;
const id = search.split('=')[1];
this.props.getDetail(id);

但是,这种方式需要自己去解析参数,相对比较麻烦。因此,推荐使用动态路由的方式传递参数。