完成详情页渲染,用到了react-markdown来渲染先看效果:1 在components下新建Detail.jsimport React , { Component }from ‘react’;import { Card, Avatar, Spin, Icon,Comment, Tooltip, List} from ‘antd’;import PropTypes from ‘prop-types’;import { connect } from ‘dva’;import ReactMarkdown from ‘react-markdown’;import ‘./my.css’;class Detail extends Component{ render() { const { Meta } = Card; return ( <Spin spinning={this.props.loading.global} size=‘large’ tip=“数据正在加载中”> {typeof(this.props.data.author)==‘object’ ? ( <Card> <Card type=“inner” title={<div><Avatar src={this.props.data.author.avatar_url} /> <span style={{fontSize :26}}>{this.props.data.title}</span> </div>} extra={ <div> 发布于{this.props.data.create_at} 作者{this.props.data.author.loginname} {this.props.data.visit_count}次浏览 *来自 分享 </div> } > <ReactMarkdown source={this.props.data.content} /> </Card> <Card type=“inner” title={this.props.data.reply_count+‘个回复’}> <List className=“comment-list” itemLayout=“horizontal” dataSource={this.props.data.replies} renderItem={item => ( <Comment author={item.author.loginname} avatar={item.author.avatar_url} content={<ReactMarkdown source={item.content} />} datetime={item.create_at} /> )} /> </Card> </Card> ) : ‘’} </Spin> ) } componentWillMount () { const { par } = this.props this.props.dispatch({ type: ‘detail/find’, payload: { id:par} }) }}Detail.propTypes = { id: PropTypes.string.isRequired,};function mapStateToProps(state) { const {id,data} = state.detail; return { id, data, loading:state.loading };}// export default ListData;export default connect(mapStateToProps)(Detail);用到了antd中的一些组件,可以自己去官网参考下怎么用。 my.css里面定义了一些样式,主要解决markdown渲染后里面的图片太宽,重新设置宽度。a{ text-decoration:none; color:#333;}img{ max-width: 1300px;}2 在models下创建对应的model detail.jsimport * as listService from ‘../services/list’;export default { namespace: ‘detail’, state:{ id:’’, data:{} }, effects: { *find({ payload: { id } }, { call, put }) { const result = yield call(listService.find, { id }) yield put({ type: ‘updateData’, payload: { result, id } }) } }, reducers: { ‘updateData’(state, { payload: data }) { let r = data.result.data const {id} = data return {…state,id,data:r} } }, subscriptions : { setup({ dispatch, history }) { }},};3 在service中添加获取详情的api list.jsimport request from ‘../utils/request’;export function query({ page,pageSize,type }) { return request(/api/v1/topics?page=${page}&limit=${pageSize}&tab=${type}
);}export function find({ id }) { return request(/v1/topic/${id}?mdrender=false
);}mdrender参数设置为false来获取markdown数据,true为html数据4 创建详情页routes/DetailPage.jsimport React from ‘react’;import { connect } from ‘dva’;import Header from ‘../components/Header’;import Detail from ‘../components/Detail’;function DetailPage(props) { const {params} = props.match return ( <div> <Header keys={[‘index’]}/> <div style={{paddingTop:20,paddingLeft:100,paddingRight:100,paddingBottom:50}}> <Detail par={params.id}/> </div> </div> );}DetailPage.propTypes = {};export default connect()(DetailPage);使用了自己定义的Header 和Detail组件。在router.js中邦定路由到页面:import React from ‘react’;import { Router, Route, Switch } from ‘dva/router’;import IndexPage from ‘./routes/IndexPage’;import DetailPage from ‘./routes/DetailPage’;function RouterConfig({ history }) { return ( <Router history={history}> <Switch> <Route path="/" exact component={IndexPage} /> <Route path="/detail/:id" exact component={DetailPage} /> </Switch> </Router> );}export default RouterConfig;使用了参数路由,在DetailPage.js中,从props.match.params中就可以取到id值传给Detail组件5 别忘了在index.js中注册model以及插件import dva from ‘dva’;import ‘./index.css’;import createLoading from ‘dva-loading’;// 1. Initializeconst app = dva();// 2. Plugins app.use(createLoading());// 3. Modelapp.model(require(’./models/listdata’).default);app.model(require(’./models/detail’).default);// 4. Routerapp.router(require(’./router’).default);// 5. Startapp.start(’#root’);前面两节课忘说dva-loading了,需要在这里使用,才能在组件中获取loading属性6 在ListData组件中加入路由跳转详情页import {Link} from ‘dva/router’;<Link to={’/detail/’+item.id}>{item.title}</Link>使用了Link来做跳转,顺带把我们的Header组件的跳转也给改了 <Menu.Item key=“index”> <Link to="/"><Icon type=“appstore” />首页</Link> </Menu.Item> <Menu.Item key=“into”> <Link to="/into"><Icon type=“appstore” />新手入门</Link> </Menu.Item> <Menu.Item key=“api”> <Link to="/api"><Icon type=“appstore” />API</Link> </Menu.Item> <Menu.Item key=“about”> <Link to="/about"><Icon type=“appstore” />关于</Link> </Menu.Item> <Menu.Item key=“reg”> <Link to="/reg"><Icon type=“appstore” />注册</Link> </Menu.Item> <Menu.Item key=“login”> <Link to="/login"><Icon type=“appstore” />登陆</Link> </Menu.Item>大功告成看看效果欢迎关注我的公众号mike啥都想搞,学习更多内容。