
这是一篇纯写样式的代码,旨在让你再次熟悉 umi 的数据流,和页面渲染。如果你能够独立完成上面的效果,那你就不用继续阅读这篇文章了。
1. 添加mock数据
新建 ./mock/api.ts
import herolist from './herolist.json';export default {'POST /apimock/freeheros.json': (req, res) => {const { number } = req.body;function getRandomArrayElements(arr, count) {var shuffled = arr.slice(0),i = arr.length,min = i - count,temp,index;while (i-- > min) {index = Math.floor((i + 1) * Math.random());temp = shuffled[index];shuffled[index] = shuffled[i];shuffled[i] = temp;}return shuffled.slice(min);}const freeheros = getRandomArrayElements(herolist, number);res.send(freeheros);}}
这里我们增加了周免英雄的接口,从英雄池里面随机取出了几个对象,这个方法是我找来的,旨在做一个简单的演示,不要太在意,如果你有更好的方法,完全可以用你自己的。
修改代理,把匹配前缀改成 /api/,这样最终发出的请求如果是 /api/ 将会使用代理,如果是 /apimock/ 将会使用mock 数据,这是一种小手段。
proxy: {- "/api": {+ "/api/": {- "target": "https://pvp.qq.com",+ "target": "https://pvp.qq.com/","changeOrigin": true,"pathRewrite": { "^/api/": "" }}}
请求地址前缀是
/apimock这里是为了让代理和mock数据同时生效。因为我没有自己的服务器,代理的数据是来自腾讯游戏,mock数据在本地。
2. 在 model 中请求数据
./src/pages/hero/models/hero.ts
import { Effect, Reducer, Subscription, request } from 'umi';export default {state: {heros: [],+ freeheros: [],filterKey: 0,+ itemHover:0 //因为周免英雄列表里面有一个一直是详情图,所以这里给一个标记},subscriptions: {...},reducers: {...},effects: {*fetch({ type, payload }, { put, call, select }) {const herolist = yield call(queryHeroList);const herodetails = yield call(getHeroDetails, { ename: 110 });+ const freeheros = yield request('mock/freeheros.json', {+ method: 'POST',+ headers: {+ Accept: 'application/json',+ 'Content-Type': 'application/json; charset=utf-8',+ },+ body: JSON.stringify({+ number: 10,+ }),+ });yield put({type: 'save',payload: {heros: herolist,+ freeheros: freeheros},});},},};
4. 编写FreeHeroItem组件
./src/components/FreeHeroItem.tsx
import React, { FC } from 'react';import { HeroProps } from 'umi';interface FreeHeroItemProps {data: HeroProps;thisIndex: number;onItemHover: (thisIndex: number) => void;itemHover: number;}const FreeHeroItem: FC<FreeHeroItemProps> = ({ data, thisIndex, onItemHover, itemHover }) => {if (!data || !data.ename) return null;return (<imgonMouseEnter={() => {itemHover !== thisIndex && onItemHover(thisIndex);}} //步骤7 需要style={{borderRadius: '5px',height: '69px',margin: '5px',width: itemHover === thisIndex ? '224px' : '69px',}}src={`https://game.gtimg.cn/images/yxzj/img201606/heroimg/${data.ename}/${data.ename}${itemHover === thisIndex ? '-freehover.png' : '.jpg'}`}/>);}export default FreeHeroItem
因为这个组件的样式很少,所以我们把样式写在 style 中,这样可以减少一个 less 文件。
修改 src/models/hero.ts ,将 HeroProps 暴露出来,这样就可以从 umi 引入了。因为 plugin-dva 的功能, models 中导出的类型和方法,都会通过 umi 导出。
- interface HeroProps {+ export interface HeroProps {ename: number;cname: string;title: string;new_type: number;hero_type: number;skin_name: string;}
5. 在页面中渲染数据
./src/pages/hero.tsx
import FreeHeroItem from '@/components/FreeHeroItem';// 这里的 @ 标示 src目录,这是umi中自带的别名。... ...const { heros = [], filterKey = 0, freeheros = [] ,itemHover=0} = hero;... ...return (<div className={styles.normal}><div className={styles.info}><Row className={styles.freehero}><Col span={24}><p>周免英雄</p><div>{freeheros.map((data,index) => (<FreeHeroItemdata={data}itemHover={itemHover}onItemHover={onItemHover}thisIndex={index}key={index}/>)}</div></Col></Row></div>... ...</div>)
6. 为页面添加样式
./src/pages/hero.less
.normal {background: url(//game.gtimg.cn/images/yxzj/web201605/top_banner/bg_wrapper2.jpg) no-repeat centertop;padding-top: 500px;}.info {padding: 8px 20px 0;margin-bottom: 20px;.freehero {overflow: hidden;width: 100%;border-radius: 5px;height: 115px;padding: 0 15px;background-color: #123564;p {color: #a6afbc;margin: 5px;}}}
7. 为页面增加响应事件
./src/components/FreeHeroItem.tsx
// 详细代码见步骤4+ onMouseEnter={() => {+ itemHover !== thisIndex && onItemHover(thisIndex);+ }}
./src/pages/hero.tsx
const onChange = e => {...};+ const onItemHover=e=>{+ dispatch({+ type: 'hero/save',+ payload: {+ itemHover: e+ },+ });+ }return (//这里面的详细代码见步骤5)
