1. 高亮字段 & classNames
需求:
点击哪个tab项,哪个做高亮处理
核心思路:
点击谁就把谁的type(独一无二的标识)记录下来,然后和遍历是的每一项的type做匹配,谁匹配到就设置负责高亮的类名
javascript
// npm install classnames
import classNames from "classnames";
<li className="nav-sort">
{/**高亮类名 active */}
{
tabs.map(item=>
<span
key={item.type}
// 用useState记录点击的type
// 因为要传参,所以onClick里面写箭头函数
onClick={()=>handleTabChange(item.type)}
className={`nav-item ${type === item.type && 'active'}`}
// 下面是采用 classnames工具 写法
className={classNames('nav-item', {active:type === item.type})}
className={classNames('nav-item', type === item.type && 'active')}
>
{item.text}
</span>
)
}
</li>
2. 删除评论功能
需求:
1.只有自己的评论才显示删除按钮
2.点击删除按钮,删除当前评论,列表中不再显示
核心思路:
1.删除显示-条件渲染
2.删除功能-拿到当前项id,以id为条件对评论列表做filter过滤
javascript
{/* 条件:user.id === item.user.id */}
{user.uid === item.user.uid && (
// onClick 写成箭头函数,因为要传参
<span className="delete-btn" onClick={() => handleDel(item.rpid)}>
删除
</span>
)}
javascript
// 渲染评论列表
// 1. 使用 useState 维护 list
const [commentList, setCommentList] = useState(list);
// 删除功能
const handleDel = (id) => {
console.log(id);
// 对 commentList 做过滤处理
// filter不会改变原数组
setCommentList(commentList.filter((item) => item.rpid !== id));
};
3. uuid dayjs
4. 清空内容&聚焦实现
javascript
// npm install uuid
import { v4 as uuidV4 } from "uuid";
// npm install dayjs
import dayjs from "dayjs";
javascript
// 发表评论
const [content, setContent] = useState('')
const inputRef = useRef(null)
const handlePublish = () => {
setCommentList([
...commentList,
{
rpid: uuidV4(), // 随机id
user: {
uid: "007",
Avatar,
uname: "黑马前端",
},
content: content,
ctime: dayjs(new Date()).format("MM-DD HH:mm"), // 格式化 月-日 时:分
like: 60,
},
]);
// 1.清空输入框的内容
setContent('')
// 2. 重新聚焦
inputRef.current.focus()
};
html
<div>
<textarea
className="reply-box-textarea"
placeholder="发一条友善的评论"
ref={inputRef}
value={content}
onChange={(e) => setContent(e.target.value)}
/>
{/* 发布按钮 */}
<div className="send-text" onClick={handlePublish}>
发布
</div>
</div>
5. json-server
html
npm install json-server
Create a db.json
or db.json5
file
javascript
{
"posts": [
{ "id": "1", "title": "a title", "views": 100 },
{ "id": "2", "title": "another title", "views": 200 }
],
"comments": [
{ "id": "1", "text": "a comment about post 1", "postId": "1" },
{ "id": "2", "text": "another comment about post 1", "postId": "1" }
],
"profile": {
"name": "typicode"
}
}
package.json
javascript
"scripts":{
"serve": "json-server db.json --port:3004"
}
javascript
npm run serve
保持窗口不关闭
javascript
const [commentList, setCommentList] = useState([]);
useEffect(() => {
async function getList() {
const res = await axios.get("http://localhost:3004/list");
setCommentList(res.data);
}
getList();
}, []);
6. 自定义 Hook 函数封装数据请求
一般思路:
(1)编写一个use打头的函数
(2)函数内部编写封装的逻辑
(3)return 出去组件中用到的状态和方法
(4)组件中调用函数解构赋值使用
javascript
// 封装请求数据的 hook
function useGetList() {
const [commentList, setCommentList] = useState([]);
useEffect(() => {
async function getList() {
const res = await axios.get("http://localhost:3004/list");
setCommentList(res.data);
}
getList();
}, []);
return {
commentList,
setCommentList,
};
}
调用
javascript
const { commentList, setCommentList } = useGetList();
7. 数据格式清洗
javascript
const menus = foodList.map((item) => ({ tag: item.tag, name: item.name }));
从 foodList
数组中提取每个元素的 tag
和 name
字段,组成一个新的数组 menus
,其中每一项是一个只包含 tag
和 name
的对象。
javascript
const foodList = [
{ tag: "fruit", name: "Apple", price: 10 },
{ tag: "drink", name: "Cola", price: 5 },
{ tag: "dessert", name: "Cake", price: 15 }
];
// 得到的新数组 menus 是:
[
{ tag: "fruit", name: "Apple" },
{ tag: "drink", name: "Cola" },
{ tag: "dessert", name: "Cake" }
]
8. 外卖商品列表切换显示
条件渲染:控制对应项显示
activeIndex === index && 视图 (没有滑动效果,只有点击跳转)
javascript
{/* 外卖商品列表 */}
{foodsList.map((item, index) => {
return (
activeIndex === index && (
<FoodsCategory
key={item.tag}
// 列表标题
name={item.name}
// 列表商品
foods={item.foods}
/>
)
);
})}
9. 购物车商品 总价计算
javascript
const totalprice = cartList.reduce((a, c) => a + c.price * c.quantity, 0);
保留两位小数
javascript
{totalPrice.toFixed(2)}