仿携程旅游平台
※仿携程旅游平台※
需求分析
针对四个板块页面规划
分析:产品模块、用户模块、购物模块、订单模块
系统设计
界面设计(UI设计规范)、需求设计(需求设计规范SRS)
一切仿携程。
开发
将.vscode与tsconfig.json和custom.d.ts同步至该项目初始化。
使css模块化书写。
框架Ant-design
路由
由于原生react路由不支持ts,所以解决方法:
npm install @types/react-router-dom --save-dev
在App.tsx中引入路由框架,react-router-dom-----BrowserRouter
import { BrowserRouter, Route } from "react-router-dom";
import { HomePage } from "./pages";
function App() {
return (
<div className={styles.App}>
<BrowserRouter>
<Route path="/" component={HomePage} />//5版本的react-router才好用!!!
</BrowserRouter>
</div>
);
}
最初由于我的版本为最新的6.几版本,所以发生了错误:
于是我将react-router 的版本改为@5.2.1版本,还是v5用着习惯....就不会出现未知错误了。
继续测试,在"/"下,默认显示HomePage路由。成功显示App路由页面。
创建唯一匹配,创建404匹配
<BrowserRouter>
<Switch>
<Route path="/" component={HomePage} exact/>
<Route path="/signIn" render={()=><h1>登录</h1>} />
<Route render={()=><h1>404 not found</h1>} />
</Switch>
</BrowserRouter>
react路由中尝试用三件套BrowserRouter+Switch+Route三者结合。
路由也分为几种方式
第一种常见的使用 “?” 来引导参数(search)
第二种 分段路由,分段路由使用restful的思维方式,参数作为url片段的一部分,使用/12345
比如:http://localhost:3000/products/12345 这个参数资源id
如果想通过这种方式实现路由的话,即可使用params这个参数获得id。
props.match.params.touristRouteId //在该路由下可以获取到/1234下的1234
但同时要在路由出口处设置path路径,以便匹配该路由以及参数
<Route path="/detail/:touristRouteId" component={DetailPage}/>
另外也尽量不要使用any来约束这个id的类型,由于id为string类型,所以我们可以使用interface接口来约束id:string,总之,想成功实现匹配路由id还需几个步骤,具体如下:
- 引入路由中的RouteComponentProps,使该组件可以获取到props下的history、match、location。
- 约束该路由页面中id/params/search的类型。
import React from "react";
import {RouteComponentProps} from "react-router-dom"
interface MatchParams{
touristRouteId:string
}
export const DetailPage:React.FC<RouteComponentProps<MatchParams>>=(props)=>{
return (
<h1>旅游路线详情页ID:{props.match.params.touristRouteId}</h1>
)
}
跨组件的数据传递方式-------------路由跳转
- context
- HOC高阶组件
- hooks
例如当点击一个图片时,要跳转至相应的链接。
那么如何在Image这种组件中使用history这些属性?
方法一:使用高阶组件withRouter。
引入import { withRouter, RouteComponentProps } from "react-router-dom";
//原来的写法: 将export导出组件
export const ProductImage:React.FC<PropsType> = ({})=>{}
//更改后的写法: 被withRouter包裹的高阶组件:
const ProductImageComponent: React.FC<PropsType> = ({ history, location, match})
export const ProductImage = withRouter(ProductImageComponent);
就可以实现在被包裹的组件中使用history这种属性啦。
方法二:useHistory() useLocation() useParams() useRouteMatch()钩子函数也可以。
import {useHistory,useLocation,useParams,useRouteMatch} from "react-router-dom"
const history = useHistory();
const location = useLocation();
const params = useParams();
const match = useRouteMatch();
console.log(history,location,params,match);
方法三:Link超链接组件
<Link to={`detail/${id}`}>
//包裹Image组件
</Link>
实现当点击每一个Image组件时通过id进行跳转。
此处遇到bug,在严格模式下onclick事件触发路由跳转,但url地址变化并没有使组件更新。 解决方法:注释掉严格模式(原理暂时不懂)
react设计模式
react通过jsx生成动态dom渲染UI,没有太多的设计模式管理。只使用react无法开发大部分应用,网站通过组件树传递数据,在父组件传递到子组件可以实现,但同级/隔了很多级的组件要想共享数据的话整个网站代码可能无法维护,一不小心可能会出现无限循环,所以我们使用redux设计模式,一种架构方案。所有的数据存放在store仓库中,
控制全局语言切换,切换语言配置,(redux管理)
- npm install redux安装
创建store后,再创建reducer作为参数,即成功连接在一起:
在组件中可以使用store.getState()获取到reducer中的初始数据。
实现在UI中直接修改reducer中的数据,(通过action触发dispatch命令,创建action命令。。。。。。通过命令进入reducer仓库修改state数据.)
也可以直接在UI组件中通过 store.subscribe() 订阅reducer中的修改后的数据,实现实时展示最新的state。
转载自:https://juejin.cn/post/7174079328458637320