Bootstrap

umi-dva集成

1.umi和dva集成

在这里插入图片描述

2.非父子组件进行通信----同步

需求:city组件中点击城市名,能传到cinema组件,它们不是父子组件,如何通信呢
先创建models文件夹,创建cityModel.ts
在这里插入图片描述在city组件发起dispatch
在这里插入图片描述Cinema组件中可以拿到状态,并修改城市名

代码:
cityModel.ts

export default {
  namespace: 'city', //命名空间,不写的话默认是cityModel
  state: {
    //初始默认值
    cityName: '北京',
    cityId: 110100,
  },
  reducers: {
    changeCity(prevState: any, action: any) {
      // debugger;
      console.log(action);
      // reducers必须有返回值
      return {
        ...prevState,
        cityName: action.payload.cityName,
        cityId: action.payload.cityId,
      };
    },
  },
};

City.tsx

import React, { useEffect, useState } from 'react';
import {connect} from 'dva'
import { IndexBar, List } from 'antd-mobile';
import { useHistory } from 'umi';
 function City(props) {
  const [list, setList] = useState([]);
  const history = useHistory();
  function filterCity(cities: any) {
    // console.log(cities);
    // 26个字母
    const letterArr: Array<string> = []; //字符串类型
    //  二维数组
    const newList: any = [];
    for (var i = 65; i < 91; i++) {
      letterArr.push(String.fromCharCode(i));
    }
    // console.log(letterArr);
    for (var j in letterArr) {
      // console.log(cities.filter((item:any)=>item.pinyin.substring(0, 1).toUpperCase()==="A"));
      var cityitems: any = cities.filter(
        (item: any) =>
          item.pinyin.substring(0, 1).toUpperCase() === letterArr[j],
      );
      // 比如字母O无对应城市,cityitems为空数组 长度为0为假,就不放进newList数组
      cityitems.length &&
        newList.push({
          title: letterArr[j],
          items: cityitems,
        });
    }
    // console.log(newList);
    return newList;
  }
  useEffect(() => {
    fetch('https://m.maizuo.com/gateway?k=2777578', {
      headers: {
        'X-Client-Info':
          '{"a":"3000","ch":"1002","v":"5.2.0","e":"16460383564094280654127105","bc":"330100"}',
        'X-Host': ' mall.film-ticket.city.list',
      },
    })
      .then((res) => res.json())
      .then((res) => {
        // console.log(res.data.cities);
        setList(filterCity(res.data.cities));
      });
  }, []);
  function changeCity(item: any) {
    console.log(item.name, item.cityId);
    // 修改store state中的状态
    props.dispatch({
      type:'city/changeCity',//city是model命名空间,changeCity是reducers里的
      payload:{
        cityName:item.name,
        cityId:item.cityId
      }
    })
    history.push('./cinema');
  }
  return (
    <div>
      <div style={{ height: window.innerHeight }}>
        <IndexBar style={{ height: '100%' }}>
          {list.map((group: any) => {
            const { title, items } = group;
            return (
              <IndexBar.Panel index={title} title={title} key={title}>
                <List>
                  {items.map((item: any, index: number) => (
                    <List.Item
                      key={index}
                      onClick={() => {
                        changeCity(item);
                      }}
                    >
                      {item.name}
                    </List.Item>
                  ))}
                </List>
              </IndexBar.Panel>
            );
          })}
        </IndexBar>
      </div>
    </div>
  );
}
// 加了一个小括号()代表返回的是一个空对象,如果只有{}会被认为是无返回值的函数
// 被connect包装后才有dispatch
export default connect(()=>({}))(City)

Cinema.tsx

import React from 'react';
import { connect } from 'dva';
import { NavBar } from 'antd-mobile';
import { SearchOutline } from 'antd-mobile-icons';
function Cinema(props: any) {
  // console.log(props);
  return (
    <div>
      <NavBar
        onBack={() => {
          // console.log('click');
          props.history.push('/city');
        }}
        backArrow={false}
        back={props.cityName}
        right={<SearchOutline />}
      >
        标题
      </NavBar>
    </div>
  );
}
// 本质是city修改状态之后,Cinema的父组件connect监听到,再以父传子传给Cinema组件
// connect组件必须返回值,Cinema组件才能拿到值
export default connect((state:any) => {
  console.log(state, 26);
  return {
    cityName: state.city.cityName,
    cityId: state.city.cityId,
  };
})(Cinema);

3.异步

需求:将影院组件的数据进行缓存,如果是第一次进入该页面就走异步请求数据,再次进就走缓存
可以看到第二次进入cinema页面,控制台的Network里也没有发起Ajax请求,一直是这三个
在这里插入图片描述
1.之前id都写死了,每次返回的都是北京的数据,修改好了
在这里插入图片描述
并且要写成模板字符串,才能写cityId
在这里插入图片描述

2.切换城市不走缓存 清空list

代码
Cinema.ts

import React, { useEffect } from 'react';
import { connect } from 'dva';
import { NavBar } from 'antd-mobile';
import { SearchOutline } from 'antd-mobile-icons';
function Cinema(props: any) {
  // console.log(props);
  useEffect(()=>{
    // 判断是否有数据,没有数据发起请求
    if(props.list.length===0){
      props.dispatch({
        type:"cinema/getList",
        payload:{
          cityId:props.cityId
        }
      })
    }else{
      // 有数据走缓存
      console.log('缓存');
      
    }
  },[])
  return (
    <div>
      <NavBar
      //每次切换城市时不走缓存 清空cinema的list
        onBack={() => {
          // console.log('click');
          props.dispatch({
            type:"cinema/clearList"
          })
          props.history.push('/city');
        }}
        backArrow={false}
        back={props.cityName}
        right={<SearchOutline />}
      >
        标题
      </NavBar>
      <ul>
        {
        props.list.map((item:any)=><li key={item.cinemaId}>{item.name}</li>)
        }
      </ul>
    </div>
  );
}
{/* 本质是city修改状态之后,Cinema的父组件connect监听到,再以父传子传给Cinema组件
 connect组件必须返回值,Cinema组件才能拿到值 */}
export default connect((state:any) => {
  console.log(state, 26);
  return {
    cityName: state.city.cityName,
    cityId: state.city.cityId,
    list:state.cinema.list
  };
})(Cinema);

cinemaModel.ts

export default {
  state:{
    list:[]
  },
  namespace: 'cinema',
  reducers: {
    changeList(prevState:any,action:any){
      return{...prevState,list:action.payload}
    },
    clearList(prevState:any,action:any){
      return{...prevState,list:[]}
    }
  },
  effects: {
    *getList(action: any, obj: any): any {
      const { call, put } = obj;
      // call(promise对象)
      var res = yield call(getListCinema,action.payload.cityId);
      // console.log(res,'getlist--res');
      
      yield put({
        type: 'changeList',
        payload: res,
      });
    },
  },
};
async function getListCinema(cityId:any) {
  // console.log(cityId);
  
  var res = await fetch(
    `https://m.maizuo.com/gateway?cityId=${cityId}&ticketFlag=1&k=7703443`,
    {
      headers: {
        'X-Client-Info':
          ' {"a":"3000","ch":"1002","v":"5.2.0","e":"16460383564094280654127105","bc":"110100"}',
        'X-Host': 'mall.film-ticket.cinema.list',
      },
    },
  ).then((res) => res.json());
  // console.log(res,'res');
  return res.data.cinemas;
}

;