完成详情页渲染,用到了
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>
<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.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.data
const {id} = data
return {...state,id,data:r}
}
},
subscriptions : {
setup({ dispatch, history }) {
}
},
};
欢迎关注我的公众号mike啥都想搞
,学习更多内容。
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.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. Initialize
const app = dva();
// 2. Plugins
app.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>