21 项目实战:详情页面和登录功能开发(二)

异步获取数据

这一节,我们要把之前reducer写死的内容,放进模拟接口中,进行ajax请求。
1.先写一个模拟接口

//===>public/api/detail.js
{
    "success": true,
    "data": {
        "title": "【Android 音视频开发打怪升级:FFmpeg音视频编解码篇】五、Android FFmpeg+OpenGL ES播放视频",
        "content": "<img alt='' src='http://upload-images.jianshu.io/upload_images/2789400-a4bbe5dbbbe5418c?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp' /><p><b>特别说明一下</b>这里,OpenGL 线程渲染的过程中,不是直接调用绘制器去渲染,而是通过一个代理来间接调用,这样 OpenGL 线程就不需要关心有多少个绘制器需要调用,统统交给代理去管理就好了。</p><p><b>特别说明一下</b>这里,OpenGL 线程渲染的过程中,不是直接调用绘制器去渲染,而是通过一个代理来间接调用,这样 OpenGL 线程就不需要关心有多少个绘制器需要调用,统统交给代理去管理就好了。</p><p><b>特别说明一下</b>这里,OpenGL 线程渲染的过程中,不是直接调用绘制器去渲染,而是通过一个代理来间接调用,这样 OpenGL 线程就不需要关心有多少个绘制器需要调用,统统交给代理去管理就好了。</p><p><b>特别说明一下</b>这里,OpenGL 线程渲染的过程中,不是直接调用绘制器去渲染,而是通过一个代理来间接调用,这样 OpenGL 线程就不需要关心有多少个绘制器需要调用,统统交给代理去管理就好了。</p>"
    }
}

2.在constants文件中添加获取到详情数据的action常量

//===>src/pages/detail/store/constants/js
export const CHANGE_DETAIL = 'detail/CHANGE_DETAIL'

3.编写异步获取数据的actionCreators

//===>src/pages/detail/store/actionCreators.js
import axios from 'axios'
import * as constants from './constants'

const changeDetail = (title, content) => ({
    type: constants.CHANGE_DETAIL,
    title,
    content
})

export const getDetail = () => {
    return (dispatch) => {
        axios.get('/api/detali.json').then((res) => {
            const result = res.data.data
            dispatch(changeDetail(result.title, result.content))
        })
    }
}

4.数据获取到之后,要用reducer去修改store的数据

//===>src/pages/detail/store/reducer.js
import { fromJS } from 'immutable'
import * as constants from './constants'

const defaultState = fromJS({
    title: '',
    content: ''
})

export default (state = defaultState, action) => {
    switch (action.type) {
        case constants.CHANGE_DETAIL:
            return state.merge({
                title: action.title,
                content: action.content
            })
        default:
            return state
    }
}

5.最后,我们来编写Detail页面的代码,在生命周期钩子函数中进行ajax请求

//===>src/pages/detail/index.js
import React, { Component } from 'react'
import { DetailWrapper, Header, Content } from './style'
import { connect } from 'react-redux'
import { actionCreators } from './store'
class Detail extends Component {
    render() {
        return (
            <DetailWrapper>
                <Header>{this.props.title}</Header>
                <Content dangerouslySetInnerHTML={{ __html: this.props.content }} />
            </DetailWrapper>
        )
    }

    componentDidMount() {
        this.props.getDetail();
    }
}

const mapState = (state) => ({
    title: state.getIn(['detail', 'title']),
    content: state.getIn(['detail', 'content'])
})

const mapDispatch = (dispatch) => ({
    getDetail() {
        dispatch(actionCreators.getDetail())
    }
})

export default connect(mapState, mapDispatch)(Detail)
效果不变

页面路由参数的传递

1.我们在List组件的item点击事件添加参数

//===>src/pages/home/components/List.js
...
class List extends PureComponent {
    render() {
        const { list, page, getMoreList } = this.props
        return (
            <div>
                {
                    list.map((item, index) => {
                        return (
                            <Link key={index} to={'/detail/' + item.get('id')}>
                               ...
                            </Link>
                        )
                    })
                }
                <LoadMore onClick={() => getMoreList(page)}>更多文字</LoadMore>
            </div>
        )
    }
}
...

2.因为在App.js中,我们设置的是精准匹配,所以现在是不能访问/detail/id这个路径的,所以这里我们要改成动态路由的形式

//===>src/App.js
...
          <Route path='/detail/:id' exact component={Detail}></Route>
...

3.这样参数已经传到了detail页面了,我们来获取参数
我们通过this.props.match.params.id这种形式获取到了参数,在钩子函数中调用ajax请求的时候传参,这样actionCreators就可以接收到参数了。

//===>src/pages/detail/index.js
import React, { Component } from 'react'
import { DetailWrapper, Header, Content } from './style'
import { connect } from 'react-redux'
import { actionCreators } from './store'
class Detail extends Component {
    render() {
        return (
            <DetailWrapper>
                <Header>{this.props.title}</Header>
                <Content dangerouslySetInnerHTML={{ __html: this.props.content }} />
            </DetailWrapper>
        )
    }

    componentDidMount() {
        this.props.getDetail(this.props.match.params.id);
    }
}

const mapState = (state) => ({
    title: state.getIn(['detail', 'title']),
    content: state.getIn(['detail', 'content'])
})

const mapDispatch = (dispatch) => ({
    getDetail(id) {
        dispatch(actionCreators.getDetail(id))
    }
})
...

4.最后ajax发送请求并传参

//===>src/pages/detail/store/actionCreators.js
...
export const getDetail = (id) => {
    return (dispatch) => {
        axios.get('/api/detali.json?id=' + id).then((res) => {
            const result = res.data.data
            dispatch(changeDetail(result.title, result.content))
        })
    }
}
效果
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。