完成详情页渲染,用到了react-markdown
来渲染
先看效果:
1 在components下新建Detail.js
import 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><Cardtype="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><Cardtype="inner"title={this.props.data.reply_count+'个回复'}><ListclassName="comment-list"itemLayout="horizontal"dataSource={this.props.data.replies}renderItem={item => (<Commentauthor={item.author.loginname}avatar={item.author.avatar_url}content={<ReactMarkdown source={item.content} />}datetime={item.create_at}/>)}/></Card></Card>) : ''}</Spin>)}componentWillMount () {const { par } = this.propsthis.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.js
import * 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.dataconst {id} = datareturn {...state,id,data:r}}},subscriptions : {setup({ dispatch, history }) {}
},
};
3 在service中添加获取详情的api list.js
import 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.js
import React from 'react';
import { connect } from 'dva';
import Header from '../components/Header';
import Detail from '../components/Detail';function DetailPage(props) {const {params} = props.matchreturn (<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. Initialize
const app = dva();// 2. Pluginsapp.use(createLoading());// 3. Model
app.model(require('./models/listdata').default);
app.model(require('./models/detail').default);// 4. Router
app.router(require('./router').default);// 5. Start
app.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啥都想搞
,学习更多内容。