乐趣区

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 啥都想搞,学习更多内容。

退出移动版