前言
继react +webpack5 + ts 框架搭建专栏学习后,很长时间没有来掘金更新了,今天起正式开始进行项目实践开发!!!
产品:仿网易云音乐demo
前置项
react:react18
打包工具:webpack5
路由:react-router-dom@6.x
UI:antd4.21.7
语言:typescript
node: node14
axios、eslint及prettier代码规范配置
1. 头部导航菜单
header引入logo图片时,报以上问题:
解决方法:global.d.ts中进行声明
头部导航效果如下:
引入antd-icon图标时一直报:缺少rev属性
解决:antd官网上也有好多人反馈该问题
官网大牛建议:升级@type/react @type/react-dom至最新版本
以上升级之后,又报错:
原因查找:说是由于
TS版本与@types/react版本不匹配导致
但是版本一致后仍存在该问题
最终解决: tsconfig.json中添加改配置
最终
header效果:
2.二级导航
前期准备,回顾下
screenX pageX clientX offsetX区别:
-
screenX、screenY鼠标点击的位置相对屏幕水平、垂直方向上的距离。 -
clientX、clientY:鼠标点击位置相对于用户端(当前屏幕/浏览器窗口) 能看到的可视区域 水平、垂直方向上的距离(不关心溢出的部分,只关注能看到的区域),从当前区域的左上角可视计算距离。无需考虑溢出的部分
-
pageX、pageY:页面未溢出不存在滚动的时候,pageX就相当于clientX,若页面发生滚动,则pageX即为滚动距离 scrollTop+clientX;pageY同理。未滚动时:
滚动时:
-
offsetX、offsetY:相对于绑定事件的元素 水平、垂直方向上的距离。
一级导航选中icon元素定位:
效果:
思路:动态设置该icon元素的left值 = menu-selected 元素的 offsetLeft + (offsetWidth - icon的width) / 2
动态计算left值
// 每次切换路由,获取当前最新的pathname,并赋给menu组件
useEffect(() => {
// 初始化路由重定向
if (location.pathname === '/') {
navigate('/home')
}
// 获取当前选中的menu item
getSelectedMenu()
}, [location.pathname])
// 动态计算icon定位元素的left数据
const getSelectedMenu = () => {
let iconLeft = 0
// 获取当前选中的menu item
const menuSelected = document.getElementsByClassName('ant-menu-item-selected')[0]
// 获取该元素到浏览器可视范围的距离
const rect = menuSelected.getBoundingClientRect()
// 动态计算icon的left值
iconLeft = rect.left + (rect.width - 14) / 2
props.menuChange(iconLeft) // 将数据传递到父组件
}
将计算的数据动态绑定到icon的style样式即可
state = {
iconLeft: 271,
}
// 接收子组件数据
menuChange = val => {
this.setState({ iconLeft: val })
}
<CaretUpOutlined className={header.cor} style={{ left: this.state.iconLeft }} />
添加二级导航内容,完善交互
<div className={home.nav}>
{btnList.map(btn => {
return (
<Button
type="text"
key={btn.value}
value={btn.value}
className={home.btn}
onClick={() => btnClick(btn.value)}
>
<span
style={{
backgroundColor: currentType === btn.value ? '#9B0909' : '',
}}
>
{btn.text}
</span>
</Button>
)
})}
</div>
最终效果:
业务模块页面
1. 发现音乐
1.1 推荐页
走马灯效果:
待续...
相关链接: github代码地址 dev分支