# react-travel **Repository Path**: bing-cola/react-travel ## Basic Information - **Project Name**: react-travel - **Description**: react17+ts 旅游网 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-10-14 - **Last Updated**: 2022-04-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # React ## 初始化项目 1. `npx create-react-app react-travel --template typescript` 2. `cd react-travel` 3. `npm run start` --- ## CSS 模块化 - CSS in JS ### typescript css 1. 安装插件:yarn add typescript-plugin-css-modules --save-dev 2. tsconfig.json中配置插件:`"compilerOptions":{ "plugins": [ { "name": "typescript-plugin-css-modules" } ] }` 3. vscode配置:创建`.vscode/settings.json` : ```json { "typescript.tsdk": "node_modules/typescript/lib", "typescript.enablePromptUseWorkspaceTsdk": true } ``` ### css需要作为模块被引入组件 1. 将App.css重命名为:App.module.css ```css /* App.module.css */ .center { text-align: center; } .list { line-height: 30px; font-size: 20px; } ``` 2. 定义声明文件custom.d.ts: 对css引用对象的支持,否则.tsx会报错 ```js // custom.d.ts declare module '*.css' { const css: { [key: string]: sting }; export default css; } ``` 3. 组件中使用: ```html // App.tsx import styles from './App.module.css'; function App() { return (
CSS in JS
); } export default App; ``` --- ## 使用 Ant Design 官网:https://ant.design/index-cn 1. 安装UI组件库:`yarn add antd` 2. 安装Icon图标:`yarn add @ant-design/icons --save` 3. 在`index.tsx`中引入css:`import 'antd/dist/antd.css';` 4. 组件中使用UI: ```html import { Input } from 'antd'; ``` 5. 组件中使用Icon: ```html import { MessageOutlined } from '@ant-design/icons'; ; ``` --- ## 路由 ### 安装路由 1. 安装:`yarn add react-router-dom --save-dev` 2. 会自动安装`react-router`核心框架 3. 安装typescript的声明文件:`npm install @types/react-router-dom --save-dev` ### 使用路由 1. BrowserRouter:路由导航与原生浏览器操作行为一致 2. Route:路由的路径解析原理与原生浏览器一致,可以自动识别url路径 3. Switch:路径的切换以页面为单位,不要页面堆叠 基础路由eg: ```js import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom' import { Home } from './pages' function App() { return (
{/* Switch 解决页面叠加问题,每次只渲染一个路由页面 */}

登录页面

)} />

404 not found 页面

)} />
); } export default App; ``` ### 路由中参数传递 使用分段路由Segments:`http://localhost:3000/products/11121314` #### 1. `App.tsx`中添加详情页的路由 ```js import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom' import { Home, Detail } from './pages' function App() { return (
{/* 路由添加参数id */}
); } export default App; ``` #### 2. `Home.tsx`中跳转到详情页的路由 1. 使用高阶函数: ```js import React from "react"; import { withRouter } from "react-router-dom"; // 高阶函数 const HomeComponent: React.FC = ({ history, location, match }) => { console.log(history, location, match); return (
history.push(`detail/123456`)}> 跳转至详情页,并传递参数id
); } export const Home = withRouter(HomeComponent); // 使用高阶函数封装路由 ``` 2. 使用hook: ```js import React from 'react'; import { useHistory, useLocation, useParams, useRouteMatch } from 'react-router-dom'; // hook export const Home: React.FC = () => { // 使用hook const history = useHistory(); const location = useLocation(); const params = useParams(); const match = useRouteMatch(); return (
history.push(`detail/123456`)}> 跳转至详情页,并传递参数id
); }; ``` 3. 使用Link: ```js import React from "react"; import { Link } from "react-router-dom"; // link export const Home: React.FC = () => { return ( 跳转至详情页,并传递参数id ); } ``` #### 3. `Detail.tsx`详情页中获取参数 ```js import React from 'react'; export const Detail: React.FC = (props) => { console.log(props.match.params.id); } ``` --- ## 国际化(I18n) ### 安装 `npm install react-i18next i18next --save` 或 `yarn add react-i18next i18next --save` ### 配置 新建文件夹`i18n\config.ts`: ```js import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import translation_en from './en.json'; // 配置的英文json import translation_zh from './zh.json'; // 配置的中文json const resources = { en: { translation: translation_en, }, zh: { translation: translation_zh, }, }; i18n.use(initReactI18next).init({ resources, lng: 'zh', interpolation: { escapeValue: false, }, }); export default i18n; ``` ### 使用 1. `index.tsx`中引入:`import './i18n/config'` 2. 组件中`Home.tsx`: ```js import React from 'react'; import { useTranslation } from 'react-i18next' export const Home: React.FC = () => { const { t } = useTranslation() return (
{t('home.detail')}
); }; ``` 3. 点击按钮切换,`reducer.ts`中: ```js import i18n from 'i18next'; export interface languageState { language: 'zh' | 'en'; languageList: { name: string; code: string }[]; } const defaultState: languageState = { language: 'zh', languageList: [ { name: '中文', code: 'zh' }, { name: 'English', code: 'en' }, ], }; const reducer = (state = defaultState, action) => { switch (action.type) { case 'change_language': i18n.changeLanguage(action.value); return { ...state, language: action.value }; default: return state; } }; export default reducer; ``` React的核心思想就是组件化,组件化带来最大好处就是组件彼此独立,可以复用。 ## 什么是钩子(hooks) 1. 消息处理的一种方法,用来监视指定程序 2. 函数组件中需要处理副作用,可以用钩子把外部代码“钩”进来 3. 常用钩子:`useState`,`useEffect`,`useContext`,`useReducer` 4. hooks一律使用`use`前缀命名:`useXxx` ## 副作用 纯函数:给一个函数同样的参数,那么这个函数永远返回同样的值。 副作用与穿函数相反,指一个函数处理了与返回值无关的事情。 输入参数一样,而输出结果不确定的情况就是副作用。 纯函数中没有副作用,有副作用的不是纯函数。 React中的副作用有:state状态的改变、生命周期、构建函数... 函数式组件中使用`useEffect`处理副作用 1. 当`useEffect`的第二个参数为一个非空数组时,会在`count`值发生变化时调用(相当于vue中的`watch`) ```js useEffect(() => { document.title = `You clicked ${count} times`; // 监听count值变化 }, [count]) ``` 2. 当`useEffect`的第二个参数为一个空数组时,初始化调用一次之后不再执行(相当于`componentDidMount`) ```js useEffect(() => { console.log('hello world'); // 仅在初始化时调用一次 }, []) // 等价于 componentDidMount() { console.log('hello world'); } ``` 3. 当`useEffect`没有第二个参数时,组件的初始化和更新都会执行,(相当于`componentDidMount` + `componentDidUpdate`),容易死循环(夺命连环call) ```js useEffect(() => { document.title = `You clicked ${count} times`; }); // 等价于 componentDidMount() { document.title = `You clicked ${this.state.count} times`; } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; } ``` 4. 当`useEffect`返回一个函数时,这个函数会在组件卸载时执行(相当于`componentDidMount`+`componentWillUnmount`) ```js useEffect(() => { const id = setInterval(() => { setCount(c => c + 1); }, 1000); return () => clearInterval(id); // 相当于componentWillUnmount }, []); // 等价于 componentDidMount() { this.id = setInterval(() => { this.setState({count: this.state.count + 1}) }, 1000); } componentWillUnmount() { clearInterval(this.id); } ``` --- ## 高阶组件(HOC) 1. 高阶组件(HOC)就是一个返回了组件的函数 2. 通过组件嵌套的方法给子组件添加更多的功能 3. 接收一个组件作为参数并返回一个经过改造的新组件 简而言之,高阶组件是参数为组件,返回值为新组件的函数。 `const hoc = higherOrde(wrappedComponent)` 组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件。 ### 高阶组件优点 1. 抽取重复代码,实现组件复用 2. 条件渲染,控制组件的渲染逻辑(渲染劫持) 3. 捕获/劫持被处理组件的生命周期 ```js import React from 'react'; const withAddToCart = (ChildComponent)=>{ return (props) =>{ return } } ``` ## React-Redux https://react-redux.js.org/ ### 1.安装 npm install react-redux @types/react-redux yarn add react-redux @types/react-redux ### 2.引入Provider 在`index.tsx`中引入Provider: ```js import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import { Provider } from 'react-redux'; // 引入Provider import store from './redux/store'; // 引入store ReactDOM.render( {/* 使用Provider并加载数据仓库 */} , document.getElementById('root') ); ``` ### 3.connect() 组件中使用connect(). ```js import { connect } from 'react-redux'; // ... export const Xxx = connect(mapStateToProps, mapDispatchToProps)(XxxComponents); ```