1. 程式人生 > >React書城小案例

React書城小案例

步驟1:api介面設定

  • api下的index.js 處理axios的公共部分
import axios from 'axios';
import qs from 'qs';
axios.defaults.baseURL = "http://localhost:8000";
axios.defaults.withCredentials = true;
axios.interceptors.response.use(res=>res.data);
axios.defaults.transformRequest=data=>qs.stringify(data);
export default axios;

步驟2 通過axios 設定好獲取資料的方法

import axios from 'index.js';
const getBanner =()=>{
    return axios.get("/course/banner")
};
let initParams = {limit:10,page:1,type:"all"};
const getCourseList = (params=initParams)=>{
    return axios.get("/course/list",{params})
};
const getCourseInfo = (courseID)=>{
    return axios.get("/course/info",{params:{courseID}})
};
export {getBanner,getCourseList,getCourseInfo}

步驟3: 使用設定好的axios方法 處理action

import * as Types from "../action-types";
import {getBanner,getCourseList} from "../../api/course";
//定義actionCreator方法
let courseBanner = ()=>{
    return async (dispatch)=>{      
    //使用了redux-thunk中介軟體 async await是對非同步的同步呼叫的簡化
        let {data} = await getBanner();
        dispatch({type:Types.COURSE_BANNER,data})
    }
};
let courseList = (params={},replace=true)=>{
    params={
        limit:10,
        page:1,
        type:"all",
        ...params
    };
    return async (dispatch)=>{
        let result = await getCourseList(params);
        dispatch({type:Types.COURSE_LIST,result,courseType:params.type,replace});
    }
};
let courseLoading = ()=>{
    return {type:Types.COURSE_ISLOADING}
};
export {courseBanner,courseList,courseLoading};

步驟4: 通過redux-aciotn中的handleActions處理reducer

//例子:
let course = handleActions({
	[Types.COURSE_BANNER]:(state,action)=>{
        return {...state,bannerData:action.data}
    }
})
  • action中dispatch派發的物件就是reducer中的action
import * as Types from "../action-types";
import {handleActions} from "redux-actions";
let initState = {
    bannerData:[],
    courseData:[],
    courseType:"all",
    replace: true, //若為true表示篩選替換資料,若為false則表示追加資料
    isLoading: false
};
let course = handleActions({
    [Types.COURSE_BANNER]:(state,action)=>{
        return {...state,bannerData:action.data}
    },
    [Types.COURSE_LIST]:(state,action)=>{
        let {result,courseType,replace} = action;
        if(replace){
            return {...state,courseData:result.data,courseType,total:result.total,page:result.page};
        }else{
            let combineData = [].concat(state.courseData,result.data);//老的資料和新的資料合併在一起
            return {...state,courseData:combineData,courseType,total:result.total,page:result.page,isLoading:false};
        }

    },
    [Types.COURSE_ISLOADING]:(state,action)=>{
        return {...state,isLoading: true}
    }
},initState);
export default course;

步驟5:通過store下的index.js 匯出需要store

import {combineReducers} from 'redux';
import course from './course';
let reducer = combineReducers({
    course,
});
export default reducer;

步驟6:去到對應的元件進行操作

在這裡插入圖片描述

import React from "react";
import {connect} from "react-redux";
import {NavLink} from 'react-router-dom';
import { Carousel,Icon,Alert,Button } from 'antd';
import "./course.less";
import actions from "../../store/action";
class Course extends React.Component{
    componentWillMount(){
        if(this.props.bannerData.length<=0){
            this.props.courseBanner();   //派發指令拿到資料
        }
        if(this.props.courseData.length<=0){
            this.props.courseList();
        }
        //在元件渲染之前 獲取相應的資料 例:輪播圖資料和課程資料
    }
    render(){
        console.log(this.props);//打印出上圖中的資料 ,拿到資料後進行相應操作,後面的事就差不多了
        let {bannerData,courseData,courseType,total,page,courseList,isLoading,courseLoading} = this.props;
        return <div className="courseBox">
            {
                bannerData.length>0?<Carousel autoplay>
                    {
                        bannerData.map((item,index)=>{
                            return  <div key={index}>
                                <img src={item.pic} alt="" onClick={(e)=>{
                                    let type = item.type;
                                    this.props.courseList({type});}}
                                />
                            </div>
                        })
                    }
                </Carousel>:null
            }

            <div className="couBox">
                <h2><Icon type="menu-fold"/><span>
                {courseType==="all"?'全部課程':courseType==="react"?
                'REACT課程':courseType==="vue"?'VUE課程':"小程式課程"}
                </span></h2>
                <div className="courseList">
                    {
                        courseData.length>0?
                            courseData.map(function(item,index){
                                let {name,dec,pic,time,id}=item;
                                return  <div className="couItem" key={index}>
                                    <NavLink to={{
                                        pathname:'/course/info',
                                        search:`courseID=${id}`
                                    }}>
                                        <h3 className="title">{name}</h3>
                                        <div className="desc">
                                            <div className="imgBox">
                                                <img src={pic} alt=""/>
                                            </div>
                                            <p>{dec}</p>
                                            <span>時間:{time}</span>
                                        </div>
                                    </NavLink>
                                </div>}) :<Alert message="Warning Text" type="Warning" description="當前沒有資料"/>
                    }
                    {isLoading?<Button type="primary" loading className="loading">
                        載入中
                    </Button>:total<=page?null:
                        <a href="###" className="loadMore" onClick={(e)=>{
                            courseLoading();
                            courseList({
                                page:parseInt(page)+1,
                                type:courseType
                            },false)
                        }}><Button type="dashed">載入更多</Button></a>}
                </div>
            </div>

        </div>
    }
}
//執行actionCreator函式才表示派發指令
export  default  connect((state)=>{
    return {...state.course}
},actions.course)(Course);