上一篇文章已经把Swiper卡片加入到我们的项目中了,今天这篇文章我们结合一下网易云音乐Api,来实现一个音乐卡片。先看一下实现的效果
接口地址 : /recommend/songs
说明: 这个接口需要先登录才能访问,并且拿到登录后返回的token和cookie值。
然后我们这里展示用到的值有
接口地址 : /login/cellphone
说明: 需要传两个参数:password 和 phone。这个账号密码需要是网易云的账号密码。
登录成功后返回值如下,我们需要cookie 和 token供/recommend/songs
使用。
如下返回的数据是一个有30项的数组。我想要把它拆分成这种结构: [[{},{}...],[{},{}],[{},{}],[{},{}]]
。渲染出如下图的四组卡片,每组下又有7张卡片
// 这是自己封装请求数据的hook
const [response] = useFetch(recommendSongs(), {});
const data = response?.data.dailySongs;
let cards = [];
// 进行了一个 七个一分组的处理
for (let i = 0; i < data?.length; i += 7) {
if (i < 28) {
cards.push(data?.slice(i, i + 7));
}
}
[[],[],[],[]]
的渲染,渲染出四个卡片组<Swiper>
,第二次渲染每个卡片组的卡片<SwiperSlide>
<IconDoubleChevronLeft />和<IconDoubleChevronRight />
是两个图标。用的是字节的图标库 字节图标可以复制为React代码 <div className={style.container}>
{cards?.map((item, index) => (
<Swiper
effect={'cards'}
grabCursor={true}
style={{ overflow: 'visible' }}
modules={[EffectCards]}
className={style.swiper}
>
{item.map((song: any, no: number) => (
<SwiperSlide
onClick={
() => setCurrentPlaying(() => ({ id: song?.privilege?.id }))
}
>
<div style={{ width: '100%', position: 'relative' }}>
<div style={{ position: 'absolute', left: 10, top: 5 }}>
{no + 1}.
</div>
<img src={song?.al?.picUrl} width="100%" height="100px" />
</div>
<div style={{ width: '100%', paddingLeft: '10px' }}>
<Title heading={6} style={{ margin: '8px 0' }}>
{song?.al?.name}
</Title>
</div>
<div style={{ width: '100%', paddingLeft: '10px' }}>
<p style={{ fontSize: '12px' }}>{song?.ar[0]?.name}</p>
</div>
<div
style={{
display: 'flex',
justifyContent: 'space-evenly',
position: 'absolute',
bottom: '10px',
width: '100%',
}}
>
<IconDoubleChevronLeft />
<IconDoubleChevronRight style={{ marginRight: '10px' }} />
</div>
</SwiperSlide>
))}
</Swiper>
))}
</div>
import { Avatar, Dropdown, Layout, Nav, Typography } from '@douyinfe/semi-ui';
import {
Route,
Routes,
NavLink,
BrowserRouter,
Link,
useNavigate,
} from 'react-router-dom';
import * as React from 'react';
import useFetch from '../../../../utils/useFetch';
import { recommendSongs } from '../../../apis/api';
import { Swiper, SwiperSlide } from 'swiper/react';
import { EffectCards } from 'swiper';
import style from './index.module.scss';
import 'swiper/css/effect-cards';
import 'swiper/css/bundle';
// Import Swiper styles
import 'swiper/css';
import {
IconDoubleChevronLeft,
IconDoubleChevronRight,
} from '@douyinfe/semi-icons';
import { useRecoilState } from 'recoil';
import { palying } from '../../../../store/atom';
const { useState } = React;
const { Title } = Typography;
const Songs: React.FC = () => {
const navigate = useNavigate();
const [currentPlaying, setCurrentPlaying] = useRecoilState(palying);
// const [data, setDtata] = useState();
const [response] = useFetch(recommendSongs(), {});
console.log(response?.data.dailySongs, '🐷');
const data = response?.data.dailySongs;
let cards = [];
for (let i = 0; i < data?.length; i += 7) {
if (i < 28) {
cards.push(data?.slice(i, i + 7));
}
}
console.log(cards, 'sss');
return (
<div className={style.container}>
{cards?.map((item, index) => (
<Swiper
effect={'cards'}
grabCursor={true}
style={{ overflow: 'visible' }}
modules={[EffectCards]}
className={style.swiper}
>
{item.map((song: any, no: number) => (
<SwiperSlide
onClick={
() => setCurrentPlaying(() => ({ id: song?.privilege?.id }))
}
>
<div style={{ width: '100%', position: 'relative' }}>
<div style={{ position: 'absolute', left: 10, top: 5 }}>
{no + 1}.
</div>
<img src={song?.al?.picUrl} width="100%" height="100px" />
</div>
<div style={{ width: '100%', paddingLeft: '10px' }}>
<Title heading={6} style={{ margin: '8px 0' }}>
{song?.al?.name}
</Title>
</div>
<div style={{ width: '100%', paddingLeft: '10px' }}>
<p style={{ fontSize: '12px' }}>{song?.ar[0]?.name}</p>
</div>
<div
style={{
display: 'flex',
justifyContent: 'space-evenly',
position: 'absolute',
bottom: '10px',
width: '100%',
}}
>
<IconDoubleChevronLeft />
<IconDoubleChevronRight style={{ marginRight: '10px' }} />
</div>
</SwiperSlide>
))}
</Swiper>
))}
</div>
);
};
export default Songs;