Skip to content

Commit

Permalink
♿ perf(custom): 添加普通搜索以及页面优化
Browse files Browse the repository at this point in the history
目前距离1.0版本还需要对sider页面的tag选择修改、大屏下tag栏展示布局修改、添加次高级搜索等
  • Loading branch information
master1lan committed Feb 25, 2023
1 parent f3b31d1 commit c4f8e4e
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 50 deletions.
19 changes: 14 additions & 5 deletions src/routers/layout/routernav/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,20 @@ type DrawerHrefItemType = {
}[];
} & Pick<DraerNavContentType, "title">;

const DrawerNavItem: FC<Pick<DraerNavContentType, "title">> = ({ title }) => (
<DrawerNavContent title={title}>
<Header_Nav />
</DrawerNavContent>
);
const DrawerNavItem: FC<Pick<DraerNavContentType, "title">> = ({ title }) => {
const shouldShow = ["/", "/video", "/photo"].includes(
window.location.pathname
);
return (
<>
{shouldShow && (
<DrawerNavContent title={title}>
<Header_Nav />
</DrawerNavContent>
)}
</>
);
};

const DrawerHrefLink: FC<TabProps & Pick<DrawerHrefItemType, "onClose">> = (
props
Expand Down
37 changes: 4 additions & 33 deletions src/routers/layout/search/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import SearchSharpIcon from "@mui/icons-material/SearchSharp";
import { Form, useNavigate } from "react-router-dom";
import { Form, useLocation, useNavigate } from "react-router-dom";
import styles from "./search.module.less";
import { useSearchFocus } from "@components/proview/searchFocus";
import { Flipped } from "react-flip-toolkit";
import SearchIcon from "@mui/icons-material/Search";
import { useURLParams } from "@utils/hooks/url";
// todo 增加高级搜索以及手机端的搜索
export default function Search() {
const navigate = useNavigate();
const handlerSubmit = () => {
const value = (document.getElementById("q") as HTMLInputElement).value;
navigate(`/search?tag=${value}`);
};
const [tag] = useURLParams(["tag"]);
return (
<>
<div
Expand All @@ -21,6 +23,7 @@ export default function Search() {
placeholder='尝试搜索些啥?'
autoComplete='off'
id='q'
defaultValue={tag}
onKeyDown={(event) => {
if (event.key === "Enter") {
handlerSubmit();
Expand All @@ -39,35 +42,3 @@ export default function Search() {
</>
);
}

function Search_1() {
const { focused, bind } = useSearchFocus();
return (
<>
<Flipped flipId={"search-box"} spring={"veryGentle"}>
<div className={styles["search-box"]}>
<Form
role='search'
className={`${styles["search-form"]} ${
focused ? styles["form-active"] : ""
}`}
>
<div className={styles["search-content"]}>
<input
{...bind}
type='text'
autoComplete='off'
maxLength={50}
className={styles["search-input"]}
placeholder='尝试在这里搜索些什么'
/>
</div>
<div className={styles["search-btn"]}>
<SearchSharpIcon />
</div>
</Form>
</div>
</Flipped>
</>
);
}
66 changes: 55 additions & 11 deletions src/routers/search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ import {
fetchVideohandler,
PickVideoRouterImageCardType,
} from "@routers/video/tools";
import { useChangeLoading } from "@store/loading";
import { nanoid } from "nanoid";
import { useEffect, useState } from "react";
import { useLoaderData } from "react-router-dom";
import { useSearchShowState } from "./hooks";

import { VideoListType } from "../video/masonry";
import SelectNav from "./select";
import { videoOrderType } from "@utils/fetch/fetchtype";
import { OrderArr } from "./tool";
type LoaderType = {
request: {
url: string;
Expand All @@ -18,17 +23,56 @@ type LoaderReturnType = UnPromisify<ReturnType<typeof loader>>;
export async function loader({ request }: LoaderType) {
const url = new URL(request.url),
tag = url.searchParams.get("tag");
const data = await fetchVideohandler(1, { order: "score", q: `tag.${tag}` });
return { data };
let order = url.searchParams.get("order") as videoOrderType;
if (!OrderArr.includes(order)) {
order = "score";
}
return [tag, order] as const;
}

export default function SearchPage() {
const { data } = useLoaderData() as LoaderReturnType,
filterData = data.map((item) => ({
...PickVideoRouterImageCardType(item),
id: nanoid(4),
}));
const { loading, isEmpty } = useSearchShowState(filterData),
propsObj = { loading, isEmpty, data: filterData };
return <NormalVideoRes {...propsObj} />;
const loaderData = useLoaderData() as LoaderReturnType,
[tag, order] = loaderData;
const [lists, setLists] = useState<VideoListType>([]);
const { handerChangeLoading } = useChangeLoading("searchIsloading");
useEffect(() => {
setLists([]);
handerChangeLoading(true);
function handlerSetList(
datas: UnPromisify<ReturnType<typeof fetchVideohandler>>,
nextPage: number
) {
setLists((lists) => [
...lists,
...datas.map((item, index) => {
const itemRes = PickVideoRouterImageCardType(item);
if (index === datas.length - 5) {
return {
...itemRes,
id: nanoid(4),
observer: true,
callback: (inView: boolean) => fetchHandler(nextPage),
};
}
return { ...itemRes, id: nanoid(4) };
}),
]);
}
const fetchHandler = async (page: number = 1) => {
const data = await fetchVideohandler(page, {
order,
q: `tag.${tag}`,
});
handlerSetList(data, page + 1);
};
fetchHandler(1).then(() => handerChangeLoading(false));
}, loaderData);
const { loading, isEmpty } = useSearchShowState(lists),
propsObj = { loading, isEmpty, data: lists };
return (
<div>
<SelectNav />
<NormalVideoRes {...propsObj} />
</div>
);
}
72 changes: 72 additions & 0 deletions src/routers/search/select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { videoOrderType } from "@utils/fetch/fetchtype";
import { nanoid } from "nanoid";
import { FC } from "react";
import { useNavigate } from "react-router-dom";
import { OrderArr, returnReplacedParmasURl } from "./tool";
import { useURLParams } from "@utils/hooks/url";

export default function SelectNav() {
const navigate = useNavigate(),
handlerCilck = (queryString: videoOrderType) => {
const replacedUrl = returnReplacedParmasURl([
{ parmas: "order", replace: queryString },
]),
newQuerySrting = new URL(replacedUrl).search;
navigate(`/search${newQuerySrting}`);
};
return (
<div className='flex gap-4 my-6 pl-1 text-gray-500 text-sm max-sm:justify-evenly max-sm:gap-0 max-[400px]:my-3'>
{Search_Nav.map((item) => (
<SearchNavItem
onClick={handlerCilck.bind(null, item.queryString)}
{...item}
key={item.id}
/>
))}
</div>
);
}

const SearchNavItem: FC<{
onClick: () => void;
label: string;
queryString: videoOrderType;
}> = ({ label, onClick, queryString }) => {
const [order] = useURLParams(["order"]),
isCurOrder = OrderArr.includes(order as videoOrderType)
? order === queryString
: queryString === "score";
return (
<div
onClick={onClick}
className={`px-4 py-2 rounded-md cursor-pointer hover:text-sky-500 flex-shrink max-[400px]:px-2 max-[400px]:py-1 ${
isCurOrder ? `bg-sky-100 text-sky-500` : ""
}`}
>
{label}
</div>
);
};

type searchNavType = {
id: string;
label: "综合排序" | "最多播放" | "最新发表";
queryString: videoOrderType;
};
const Search_Nav: searchNavType[] = [
{
id: nanoid(4),
label: "综合排序",
queryString: "score",
},
{
id: nanoid(4),
label: "最多播放",
queryString: "view",
},
{
id: nanoid(4),
label: "最新发表",
queryString: "pubdate",
},
];
31 changes: 31 additions & 0 deletions src/routers/search/tool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { videoOrderType } from "@utils/fetch/fetchtype";

function ParseQueryString(queryString: string) {
const regExp = /([^&=]+)=([\w\W]*?)(&|$)/g;
let result = null,
ret: { [key: string]: string } = {};
while ((result = regExp.exec(queryString)) != null) {
ret[result[1]] = result[2];
}
return ret;
}
export const parseURL = (url = window.location.href) => {
const objUrl = new URL(url),
params = objUrl.search.slice(1);
return ParseQueryString(params);
};

export const returnReplacedParmasURl = (
input: { parmas: string; replace: string }[]
) => {
const originUrl = window.location.href,
paramsObj = parseURL(originUrl);
input.forEach(({ parmas, replace }) => (paramsObj[parmas] = replace));
return originUrl.replace(
window.location.search,
`?${Object.entries(paramsObj)
.map(([key, value]) => `${key}=${value}`)
.join("&")}`
);
};
export const OrderArr: videoOrderType[] = ["pubdate", "score", "view"];
3 changes: 2 additions & 1 deletion src/utils/fetch/fetchtype.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export type videoOrderType = "pubdate" | "view" | "score";
/**
*@description video接口的请求参数类型
*/
Expand All @@ -7,7 +8,7 @@ export interface IFetchVideoParams {
* pubdate为最新发布排序,view为最多播放排序,score为最高得分排序
* @example pubdate | view | score
*/
order: "pubdate" | "view" | "score";
order: videoOrderType;
/**
* @description 分页,每页返回20个;从1开始,自然数递增
* @example 1
Expand Down
5 changes: 5 additions & 0 deletions src/utils/hooks/url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const useURLParams = (searchList: string[]) => {
const originURl = window.location.href;
const url = new URL(originURl);
return searchList.map((item) => url.searchParams.get(item) || "");
};

0 comments on commit c4f8e4e

Please sign in to comment.