React实战入门课程:dva开发一个cnode网站(3)

news/2024/7/10 22:56:04 标签: react, dva, node, js, es6

完成详情页渲染,用到了react-markdown来渲染
先看效果:
详情

js_4">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;
}

js_103">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 }) {

    }
},
};

js_138">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数据,truehtml数据

js_152">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);

使用了自己定义的HeaderDetail组件。在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组件

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


http://www.niftyadmin.cn/n/1366485.html

相关文章

React实战入门课程:dva开发一个cnode网站(4)

增加分类标签&#xff0c;效果如下&#xff1a; 1 修改ListData组件 完整代码&#xff1a; import React , { Component }from react; import { List, Avatar, Icon, Spin ,Tag } from antd; import PropTypes from prop-types; import { connect } from dva; import ./my.c…

圣诞节,中国开源世界炸锅了@阿里巴巴

今天和往常并没有什么区别&#xff0c;最为一名小程序员&#xff0c;我照常开始自己的工作&#xff0c;写着自己的代码。 npm start 启动自己的前端代码&#xff0c;接着码代码。随着浏览器跳转到页面&#xff0c;看着昨天完成的代码&#xff0c;还有点小激动。划拉两下鼠标&a…

免费开发实战资源,包含前后端以及app小程序

收集了一些开发视频教程&#xff0c;现在免费分享给需要的人 关注公众号回复指令领取React开发简书&#xff08;简书&#xff09;Python开发借书&#xff08;flask&#xff09;Vue开发去哪儿&#xff08;去哪儿&#xff09;SpringBoot深入学习&#xff08;SpringBoot&#xff0…

React框架Umi实战(1)简介与使用脚手架

之前写完了dva入门系列,它只是一个纯粹的数据流框架,拿来开发是没有问题的.但是还是有一些繁琐的步骤,每次要手动注册model,手写route路由.Umi的出现结合dva,使得开发更加的优雅与便捷. 1 特性 ? 开箱即用&#xff0c;内置 react、react-router 等 ? 类 next.js 且功能完备的…

React框架Umi实战(2)整合dva开发后台管理系统

umi官方推荐结合dva使用更配哦&#xff0c;其实他们都是同一位开发者开发的&#xff0c;属于阿里内部开源框架。 1 修改.umirc.js&#xff0c;开启dva支持 // ref: https://umijs.org/config/ export default {plugins: [// ref: https://umijs.org/plugin/umi-plugin-react.ht…

React框架Umi实战(3)路由进阶

前面的课程都是使用的约定路由&#xff0c;就是自动生成的&#xff0c;但是我们做项目大部分都是涉及权限控制的&#xff0c;这时就还是得用控制路由&#xff0c;仅今天就来改进一下 1 修改配置.umirc.js // ref: https://umijs.org/config/ export default {plugins: [// ref:…

netty搭建web聊天室(1)

之前一直在搞前端的东西&#xff0c;都快忘了自己是个java开发。其实还有好多java方面的东西没搞过&#xff0c;突然了解到netty&#xff0c;觉得有必要学一学。 介绍 Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具&#xff0c;用…

netty搭建web聊天室(2)群聊

上节课完成了netty的后端搭建&#xff0c;搞定了简单的http请求响应&#xff0c;今天来结合前端websocket来完成群聊功能。话不多说先上图&#xff1a; 前端构建 不使用复杂构建工具直接静态页面走起 使用了zui样式库 http://zui.sexy/?#/&#xff0c;非常不错&#xff0c;有…