这是一篇纯写样式的代码,旨在让你再次熟悉 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 (
<img
onMouseEnter={() => {
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) => (
<FreeHeroItem
data={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 center
top;
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
)