dva开发一个cnode网站(3)

完成详情页渲染,用到了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} />
&nbsp;&nbsp;&nbsp;
<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 }) {

}
},
};
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>
大功告成看看效果

欢迎关注我的公众号mike啥都想搞,学习更多内容。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理