dva——03——models异步处理

dva——03——models异步处理_第1张图片访问时根据路由动态决定加载哪些组件,如果组件加上connect,可以获得状态(model),组件dispatch一个action到模型中,如果是同步则到Reducer,状态发生改变,谁用了connect就得到这个状态
如果是异步到effect,需要写成生成器的写法,在effect中先进行异步处理,处理完了再通过同步给到Reducer,Reducer是负责数据更新的,再通过connect传给组件。Subscription做一些初始化设置,比如loadding框显示转圈,数据请求完后隐藏转圈

subscription的使用:history(路由地址) 进行各种初始化设置
dva——03——models异步处理_第2张图片dva——03——models异步处理_第3张图片

异步操作例子
需求是:Cinema组件做数据缓存,如果是第一次进入页面,走Ajax请求异步请求数据,后面再次进入该页面直接走缓存

先用connect高阶函数包裹Cinema组件,这样Cinema组件才能拿到状态,在Cinema组件中发起diapatch,model里的effects里的函数接收到
在model异步函数effects中请求数据,yield call一个函数,这个函数是service里的,service请求数据,model拿到之后再put给reducers,再传给页面
代码展示:
要打开入口文件index.js的model
dva——03——models异步处理_第4张图片Cinema.js

import { connect } from "dva";
import React, { Component } from "react";

class Cinema extends Component {
  componentDidMount() {
    if (this.props.list.length === 0) {
      // dispatch一个action,action解构赋值的结果是type和payload,这里只有type
      this.props.dispatch({
        type: "maizuo/getCinemaList",
      });
    } else {
      console.log("缓存",this.props.list);
    }
  }
  render() {
    return (
      <div>
        <ul>
          {this.props.list.map((item) => (
            <li key={item.cinemaId}>{item.name}</li>
          ))}
        </ul>
      </div>
    );
  }
}
// 可以将mapStateToProps函数写外面,也可以直接写在connect里面
const mapStateToProps = (state) => {
  // console.log(state,333355);
  // 将对象名为list数据传给Cinema组件,组件的props能接收到名为list的数据
  return { list: state.maizuo.list };
};
// 如果要简写省去return,不能要{}包裹,会被当成函数体而不是对象,所以要在外面用()包起来表示一个整体的东西
// 错误写法
// const mapStateToProps = (state) => 
//    { list: state.maizuo.list}
// 正确写法
//  const mapStateToProps = (state) => ({list: state.maizuo.list})
export default connect(mapStateToProps)(Cinema);

models/maizuo.js

import {getCinemaListService} from "../services/maizuo"
export default {
  namespace: "maizuo",
  state: {
    isShow: true,
    list: [],
  },
  subscriptions: {
    setup({ dispatch, history }) {
      console.log("初始化");
    },
  },
  reducers: {
    hide(prevState, action) {
      // 这里合并而不直接更改数据是因为prevState是不可变的,保证状态不可变
      // 所以我们要深复制一遍,再return出去(同名的直接覆盖)
      return { ...prevState, isShow: false };
    },
    show(prevState, action) {
      return { ...prevState, isShow: true };
    },
    changeCinemaList(prevState,{type,payload}){
      // 把payload数据放到命名为list的里去
         return{...prevState,list:payload}
    }
  },
  effects: {
    // 第一个参数是action可以解构赋值成type和payload
    *getCinemaList(action, { call, put }) {
      // call进行异步取数据,put发送新的action到reducers中
      var res = yield call(getCinemaListService);
      console.log(res);
      //  put参数也是action对象,解构赋值为type和payload
      yield put({
        type: "changeCinemaList",
        payload: res.data.data.cinemas,
      });
    },
  },
};

services/maizuo.js

import request from "../utils/request";
export function getCinemaListService() {
  return request(
    "https://m.maizuo.com/gateway?cityId=330100&ticketFlag=1&k=4103390",
    {
      headers: {
        "X-Client-Info":'{"a":"3000","ch":"1002","v":"5.2.0","e":"16460383564094280654127105","bc":"330100"}',
        "X-Host": "mall.film-ticket.cinema.list",
      },
    }
  );
}

如果请求的网站有跨域怎么办,比如我们之前请求的网站是卖座网无跨域限制,现在我们在center页面中请求猫眼网(有跨域)的数据,在.webpackrc文件(支持dev-server、反向代理)中配置反向代理,这个文件必须是json格式,所以changeOrigin得加双引号,将changeOrigin(改变源)设置为true,将这个文件改成json
dva——03——models异步处理_第5张图片dva——03——models异步处理_第6张图片在猫眼网控制台的网络找到请求网址
dva——03——models异步处理_第7张图片

dva——03——models异步处理_第8张图片将开头剪切到反向代理中
dva——03——models异步处理_第9张图片
dva——03——models异步处理_第10张图片一朝/ajax进行请求时,反向代理转发到target地址,由服务端发请求,它们无跨域限制

请求另一个地址例子:
在这里插入图片描述dva——03——models异步处理_第11张图片
dva——03——models异步处理_第12张图片
第二个例子的代码:
.webpackrc

{
  "proxy": {
    "/api": {
      "target": "https://i.maoyan.com",
      "changeOrigin": true
    }
  }
}

Center.js

import React, { Component } from "react";
import { withRouter } from "dva/router";
import request from "../utils/request"
export default class Center extends Component {
  componentDidMount(){
    request(
      "/api/mmdb/movie/v3/list/hot.json?ct=%E6%9D%AD%E5%B7%9E&ci=50&channelId=4"
    ).then((res) => {
      console.log(res.data);
    });
  }
  render() {
    return (
      <div>
        Center
        {/*  */}
        {/* 不传props的情况下可以使用withRouter */}
        <WithChild />
      </div>
    );
  }
}
class Child extends Component {
  render() {
    return (
      <div>
        <button
          onClick={() => {
            // console.log(this.props)
            localStorage.removeItem("token");
            this.props.history.push("/login");
          }}
        >
          退出登录
        </button>
      </div>
    );
  }
}
// 组件首字母要大写,注意
const WithChild = withRouter(Child);

你可能感兴趣的:(umi,dva,react.js,前端,node.js)