既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
subHeaderName
是一个纯字符串,这个也是最简单的。midConent
最终的决定是由一个由 对象 组成的数组:
[
{ title: '热门', url: '/#' },
{ title: '初级', url: '/#' },
{ title: '中级', url: '/#' },
{ title: '高级', url: '/#' },
];
checkMore
则是单独的一个对象:
{
title: '查看全部',
url: '/#',
};
其实为了省事儿单独的写 <a href='/#> 一些标题 </a>
也不是不可以,嫌麻烦的也可以直接这么写。
这种就属于每个人都会不太一样的编码风格和习惯问题,对于我来说将这些常量提取出去,一旦要修改或是清理数据都会方便很多。毕竟真实的项目中,如果后台数据没有准备好的话,大多数情况下是要自己准备 伪数据,而不是等后台开发完毕之后再使用后台传来的数据进行开发。
‼️ 所以,一定要和你的后台提前沟通好传来的数据结构是什么样子的,有文档最好,没有文档 一定 要留下邮件或是微信聊天记录作为证据,以防 被甩锅。
修改实现方法,重新渲染 sub header
中间的内容区依旧会使用 ul > li > a
的经典结构,并且使用 arr.map()
去进行遍历。
import React from 'react';
const SubHeader = (props) => {
const { subHeaderName, midConent, checkMore } = props;
const getMidContent = () => {
return (
<ul className="flex">
{midConent.map((val) => (
<li key={val.title}>
<a href={val.url}>{val.title}</a>
</li>
))}
</ul>
);
};
return (
<div className="sub-header flex space-between flex-center">
<h3>{subHeaderName}</h3>
{getMidContent()}
<div>
<a href={checkMore.url}>{checkMore.title}</a>
</div>
</div>
);
};
到这一步,距离 sub header 实现完毕还差最后一步——选中高亮的实现。
以下为静态的实现效果:
使用 useState 去实现选中高亮
选中高亮的逻辑实现起来其实并不复杂,具体步骤如下:
- 需要一个变量保存当前选中的选项,默认为
热门
- 在点击事件发生时,需要替换被选中的选项
这个部分的实现就需要借助 React 自带的一个钩子函数:setState
,setState
的存在是为了替换 类组件(class-based component) 中的 状态(state) 属性。
语法为:
建议使用 ES6 中的 const
const [property, propertyHandler] = useState(defaultValue);
其中
property
为该属性的变量名propertyHandler
为事件发生时用来更新状态的函数
这个函数只是一个标识符,它不负责处理其他的逻辑,只负责更新传进去的值
useState
中传进去的为默认值- 在需要更新状态的事件函数中调用
propertyHandler
即可。
以本业务场景为例,初始值的代码如下;
const [activeTitle, setTitle] = useState(midConent[0].title);
// 点击事件
function clickHandler(e, val) {
// 防止新页面打开 and/or 重定向的发生
e.preventDefault();
// 更新状态
setTitle(val);
}
activeTitle
定义的是当前被选中,需要被设为高亮的选项setTitle
为 点击标签时设置当前高亮选项 的函数
它会接受一个值,并且直接替换 activeTitle
useState
设置的是默认值,在这个情况下也就是热门——第一个选项的标题
点击事件 clickHandler
会还给每一个 a 标签,在 a 标签被鼠标点击后就会触发这个状态,更新当前显示高亮的标签。
实现后的动态效果:
到这一步,标题的实现就完成了。
完整 JSX 代码如下:
- SubHeader
import React, { useState } from 'react';
import PropTypes from 'prop-types';
const SubHeader = (props) => {
// =================新增部分===================
const [activeTitle, setTitle] = useState(midConent[0].title);
function clickHandler(e, val) {
e.preventDefault();
setTitle(val);
}
// =================新增部分===================
const getMidContent = () => {
return (
<ul className="flex">
{midConent.map((val) => {
const { title } = val;
return (
<li key={title}>
<a
href={val.url}
onClick={(e) => clickHandler(e, title)}
className={activeTitle === title ? 'selected' : null}
>
{title}
</a>
</li>
);
})}
</ul>
);
};
};
export default SubHeader;
- Home
const Home = () => {
return (
<div className="homepage relative">
<HomeBanner />
<div className="container">
<FieldSuggestion />
<div className="homepage-main">
<SubHeader
subHeaderName="编程入门"
midConent={subHeaderOl}
checkMore={checkMore}
/>
</div>
</div>
</div>
);
};
精品推荐和课程推荐 的实现
标题已经实现了,剩下的内容就是一排排的课程:
很明显,每一个课程的结构都是一样的:
- 课程图片
- 课程标题
- 课程描述
- 新款课程(右上角的小标题)
- 爆款课程(右上角的小标题)
那么,第一步可以先将单独的 课程 封装起来,随后再循环遍历所有的课程列表,就能够获得一排排的课表了。
封装课程组件
这就是之前在 common 里就设计好的 CourseItem 组件。
根据上面列出的课程结构,所以课程组件会需要获取以下这些属性:
- id,上文没显示的内容,这里是作为一个标识符而存在的
- title, 标题,也就是课程名称
- img, 课程图片
- peopleStudying,多少人在学习,属于课程描述的内容
- courseLevel,初级中级高级,也属于课程描述的内容
- isNew 或 isHot,用或是因为 PSD 的设计中只显示了一个,不过具体的检查我偷懒了,也没做
课程主体
暂时不考虑 isNew 或 isHot,先将主体结构实现:
import React from 'react';
const CourseItem = (props) => {
const { peopleStudying, courseLevel, id, title, img, isNew, isHot } = props;
return (
<div className="course-item">
<img src={img} />
<h4>{title}</h4>
<p className="course-info">
<span className="course-level">{courseLevel}</span>· {peopleStudying}
人正在学习
</p>
</div>
);
};
export default CourseItem;
随后放入假数据:
import php from '../asset/img/courses/php.png';
class Course {
// 偷一下懒,学习人数和等级写死了
// 也可以传到构造函数中去,但是PSD上都一样,我就……
peopleStudying = 1125;
courseLevel = '高级';
constructor(id, title, img, isNew = false, isHot = false) {
this.id = id;
this.title = title;
this.img = img;
this.isNew = isNew;
this.isHot = isHot;
}
}
const coursePhp = new Course(1, 'test', php, false, true);
// course list for home page
export const courseSuggestion1 = [coursePhp];
和 CSS:
.course-item {
width: 228px;
height: 270px;
background-color: #fff;
margin: 0 15px 15px 0;
}
.course-img {
width: 100%;
}
.course-item h4 {
margin: 20px;
font-size: 14px;
color: #050505;
font-weight: 400;
}
.course-info {
margin: 0 20px;
font-size: 12px;
color: #999;
}
.course-level {
color: #ff2c2d;
}
这样一来,效果就已经有了:
完整实现课程
引入之前拉下来的两个图片,这里偷懒了没有检查排他性——即只能存在 isNew
或 isHot
,而不能二者同时存在。
正式开发中如果有需求的话,这个检查时一定要做的。
然后利用三元表达是去检查 isNew
和 isHot
是否为 true
,如果是的话就渲染对应的组件,如果不是的话就渲染 null。
又因为两个图标的效果是完全一致的,我这里继续抽了一个函数出来去实现 icon:
import React from 'react';
import './courseItem.css';
import hotLabel from '../../asset/img/courses/hot.png';
import newLabel from '../../asset/img/courses/new.png';
const getLabelImg = (img, label) => {
return <img src={img} alt={label} class={label} />;
};
const CourseItem = (props) => {
const { peopleStudying, courseLevel, id, title, img, isNew, isHot } = props;
const isNewCourse = isNew
? getLabelImg(newLabel, 'new-course absolute')
: null;
const isHotCourse = isHot
? getLabelImg(hotLabel, 'hot-course absolute')
: null;
return (
<div className="course-item relative">
<img src={img} alt={title} className="course-img" />
<h4>{title}</h4>
<p className="course-info">
<span className="course-level">{courseLevel}</span>· {peopleStudying}
人正在学习
</p>
{isNewCourse}
{isHotCourse}
</div>
);
};
export default CourseItem;
实现效果:
有点这个意思了。
添加课程列表的数据
一个个手动复制黏贴就是非常浪费时间的事情了,所以下一步就是封装伪数据。
这里主要就是创建一个课程的类,这样可以快速的实例化课程,以及创造几个假数据:
import php from '../asset/img/courses/php.png';
import andriod from '../asset/img/courses/andriod.png';
import angular from '../asset/img/courses/angular.png';
import androidHybrid from '../asset/img/courses/andriod-hybrid.png';
class Course {
// 偷一下懒,学习人数和等级写死了
// 也可以传到构造函数中去,但是PSD上都一样,我就……
peopleStudying = 1125;
courseLevel = '高级';
constructor(id, title, img, isNew = false, isHot = false) {
this.id = id;
this.title = title;
this.img = img;
this.isNew = isNew;
this.isHot = isHot;
}
}
const coursePhp = new Course(
1,
'Think PHP 5.0 博客系统实战项目演练',
php,
false,
true
);
const courseAndriod = new Course(
2,
'Android 网络图片加载框架详解',
andriod,
true
);
const courseAngular = new Course(
3,
'Angular 2 最新框架+主流技术+项目实战',
angular
);
const courseAndroidHybrid = new Course(
4,
'Android Hybrid APP开发实战 H5+原生!',
androidHybrid
);
const courseAndroidHybrid2 = new Course(
5,
'Android Hybrid APP开发实战 H5+原生!',
androidHybrid
);
// course list for home page
export const courseSuggestion1 = [
coursePhp,
courseAndriod,
courseAngular,
courseAndroidHybrid,
courseAndroidHybrid2,
];
第一组伪数据就实现好了,接下来在 CourseSuggestion 组建中引入这个列表中,进行循环遍历出所有的课程:
import React from 'react';
import SubHeader from '../subHeader';
import { subHeaderOl, checkMore } from '../../../constants/home';
import { courseSuggestion1 } from '../../../constants/courseList';
import CourseItem from '../../../common/courseItem';
// 渲染课程列表,不含其他的内容模块
const CourseSuggestion = (props) => {
return (
<div>
<SubHeader
subHeaderName="编程入门"
midConent={subHeaderOl}
checkMore={checkMore}
/>
<div className="flex">
{courseSuggestion1.map((course) => (
<CourseItem {...course} key={course.id} />
))}
</div>
</div>
);
};
export default CourseSuggestion;
实现效果如下:
除了差点 CSS 之外,这个味儿对了。
useHistory是react-router-dom提供的一个钩子函数,可以用来通过它实例化一个history对象,用来实现页面的重定向。
使用方法如下:
// 引用钩子函数
import { useHistory } from 'react-router-dom';
// 实例化一个history对象
const history = useHistory();
// 通过将 url 推入 history 完成重定向的操作
history.push(url);
所以,最后在每个课程列表上加入 history.push(url/courseId)
完成重定向。这样,当用户点击单独的课程列表后,就会被重定向到对应的课程页面去:
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
st history = useHistory();
// 通过将 url 推入 history 完成重定向的操作
history.push(url);
所以,最后在每个课程列表上加入 `history.push(url/courseId)` 完成重定向。这样,当用户点击单独的课程列表后,就会被重定向到对应的课程页面去:
![](https://i-blog.csdnimg.cn/blog_migrate/cb1f26b5afc1e034a212cb933b05c5de.gif)
[外链图片转存中...(img-Nk5MZZnL-1715749565068)]
[外链图片转存中...(img-dXlQeRn7-1715749565069)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**