1. ES6重命名导入语法
import { BrowserRouter as Router } from "react-router-dom";
BrowserRouter是JavaScript中ES6的“重命名导入”语法,从react-router-dom这个包里导入BrowserRouter组件,
并且在当前文件里把它叫做Router。我们就可以直接在代码里用<Router>了。
详细请参考: MDN: import - JavaScript | MDN
2. 对象解构赋值
export const GlobalProvider = ({ children }) => {
const [state, dispatch] = useReducer(repoReducer, initalState);
};
这里的{children}与通常函数传值的参数children含义是不一样,这里是对象解构赋值,{children}是从props中解构取出来的children属性,而如果直接children,此时children就是props。这样写就是为了代码更简洁,不用每次都写props.children。其实const [state, dispatch] = useReducer(repoReducer, initalState);也是解构赋值。
官方文档和主流社区都推荐如下写法:
function MyComponent({ children }) {
return <div>{children}</div>;
}
详细请参考: Passing Props to a Component - React 官方文档
3.路径别名(Path Alias)
import { Reducer } from "@/reducers/Reducer";
在import { repoReducer } from "@/reducers/repoReducer";中@不是JavaScript或React语法,而是路径别名,用来简化导入路径。一般来说,@代表项目的src目录,所以说@/reducers/Reducer等价于src/reducers/Reducer。
如何在项目中配置 @ ?
不同构建工具配置方式不同。常见如下:
1.Vite项目中
import { defineConfig } from 'vite';
import path from 'path';
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
});
2.webpack项目中
const path = require('path');
module.exports = {
// ...其他配置
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
};
3.在TypeScript项目中
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
4. React组件的JSX写法
如下路由伪代码,会疑惑也许会疑惑为什么fallback/element的=后面是{< />}而不是{ }或者" "?
import Loading from "./components/Loading";
return (
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/users/:id/repos" element={<RepoList />} />
<Route path="/users/:id/repos/:repoId" element={<RepoDetail />}></Route>
<Route path="*" element={<NotFound />} />
</Routes>
</Suspense>
);
<Loading />是React组件的JSX写法,<Loading />表示渲染一个Loading组件,它会显示Loading组件里定义的内容(比如一个加载动画),= {<Loading />}的意思是把一个React元素(组件实例)作为fallback/element的值传递给Suspense/Route。
为什么不写成= " "或= { }?
前置知识: Loading是组件类型,本质上是一个函数(或类),<Loading />是组件实例。形象理解就是,Loading就像是“模具”或“蓝图”,而<Loading/>是这个摸具生产出来的成品
= "Loading"只是一个字符串,React会直接渲染字符串“loading”,这样页面上只会显示文字loading,而不是自定义组件中的样式或动画。
= {Loading}传递的是组件本身(即函数或类),而不是组建的实例,React需要的是一个元素(即<Loading />),而不是组件类型,如果写fallback={Loading},React不会自动渲染它,页面不会显示你要的内容。
5.import{ xxx }还是import xxx ? export还是export default ?
工具函数/常量/模块(非组件)
推荐:
import { xx } from "..." 大括号的写法,叫做命名导入(named input),只能导入模块中通过export命名导出的内容。语法:export const xxx = ...或export function xxx(){}。
因为一个工具文件可能会导出多个函数或变量。
例如自定义hook有多个函数:
import axios from "axios";
const BASE_URL = "https://api.github.com"; // 基础地址
export const getRepos = (username) => {
return axios.get(`${BASE_URL}/users/${username}/repos`);
};
export const getRepoDetail = async (username, repoName) => {
return await axios.get(`${BASE_URL}/repos/${username}/${repoName}`);
};
组件(React组件)
推荐:
import from "..."无大括号的写法,叫做默认导入(default import),只能导入模块中通过export default导出的内容,语法:export default xxx。
因为一个文件通常只导出一个主要组件,这样导入时更简洁。
例如Loading组件:
function Loading() {
return <div>Loading...</div>;
}
export default Loading;
6.路由参数(: id)
<Route path="/users/:id/repos" element={<RepoList />} />
<Route path="/users/:id/repos/:repoId" element={<RepoDetail />}></Route>
如上路由代码,:id其实是路由参数的语法,在React Router(以及很多前端路由库中),/users/:id/repos里的:id表示这是一个动态参数,不是固定的字符串,:id里的冒号:表示这是一个变量。
如何获取:id的值?
import { useParams } from "react-router-dom";
function RepoList() {
const { id } = useParams();
// id 就是 URL 里的动态部分,比如 123
}
在对应的组件中,可以用React Router的hook来获取参数,这样,当URL为/users/123/repos或/users/abc/repos时,React Router会自动把id=123/abc这个参数“注入”到响应使用useParam的组件内部。
注意: 路由参数不是通过props传递!
详细请参考资料:React Router - useParams