目录
一、脚手架基础语法(16~17)
1.1、hello react
1.2、组件样式隔离(样式模块化)
已知:vue2通过scoped来防止组件样式冲突
react解决方法:样式模块化(CSS Modules)
使用方法:
1、将 CSS 文件命名为 [name].module.css。
2、在组件中导入样式模块,并使用对象属性访问样式类名。
import "./hello.css";//直接引入
import styles from "./hello.module.css";//样式模块化
<h2 className={styles.title}>hello react!</h2>
补充:Styled Components、Emotion、Shadow DOM 和 CSS 命名空间等方案也可以。
1.3、react插件
VScode插件搜索react:ES7+ React/Redux/React-Native snippets
输入rcc:类组件 rfc:函数组件回车即可
二、React Router v5
1、SPA:单页面应用
(1)、点击页面中的链接不会刷新页面,只做页面的局部刷新
(2)、数据都通过ajax请求获取,并在前端异步展现
2、路由:一个路由就是一个映射关系(key:value)
key为路径,value可能是function【后端路由】或component【前端路由】
前端:当浏览器的path变为/XX时,当前路由组件就会变为XX组件,依赖浏览器的
hash
或history
API来管理 URL 状态。
2.1、react-router-dom相关API
下载:npm i react-router-dom@5
路由组件和一般组件接收的props不同,前者会接收到三个history、location、match固定属性。
2.1.1、内置组件
import { BrowserRouter as Router, Route, Switch, Redirect,Link } from 'react-router-dom'
export default class App extends Component {
render() {
return (
<div>
<Router>
{/* Switch虽然在v5版本不是必须的,但是基本都会用到,只让页面匹配上一个,不能匹配上多个 */}
<Switch>
<Route path='/' exact render={() => <Redirect to='/index'></Redirect>}></Route>
<Route path='/index' render={(props) => {
//想要进入到主页,如果此时还未登录就重定向到登录页,如果已经登陆了就进入首页
if (isLogin()) {
// Home组件并不是路由组件,render的函数式组件才是真正的路由组件,需要把props的内容传到Home组件中。
return <Home {...props}></Home>
} else {
return <Redirect to='/login'></Redirect>
}
}}></Route>
<Route path='/login' render={(props) => {
if (isLogin()) {
return <Redirect to='/index/home'></Redirect>
} else {
return <Login {...props}></Login>
}
}}></Route>
</Switch>
<div className="left-side">
<Link to="/about">About</Link>
<Link to="/home">Home</Link>
</div>
<div className="right-content">
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
</div>
</Router>
</div>
)
}
}
2.1.1.1、BrowserRouter
使用 HTML5 history API 来保持URL 路径不带 #,适合现代 Web 应用
2.1.1.2、HashRouter
使用 # 来管理 URL,适合不支持HTML5 history API的老版本浏览器,刷新后会导致路由参数丢失
2.1.1.3、Route
<Route>
:用于定义路径和对应组件的基本单元
<Route path="/home" component={<Home />} />
2.1.1.4、Redirect
重定向:<Redirect to='/index'></Redirect>
2.1.1.5、Link
它是React Router提供的用于页面跳转的组件,类似于HTML的<a>
标签,但不会引起页面刷新
2.1.1.6、NavLink
特殊的<Link>,
添加了活动样式(activeClassName),通过this.props.children获取标签体内容
<NavLink to="/home" activeClassName="active">Go to Home</NavLink>
2.1.1.7、Switch
只让页面匹配上一个,不能匹配上多个,提高路由匹配效率
拓展:
路由默认使用模糊匹配,如果开启严格匹配【exact={true}】的话,有时会导致无法继续匹配二级路由,不要随便开启。
2.1.2、其它
2.1.2.1、history对象
管理浏览器的会话历史。例如推送新的路径、替换当前路径和返回上一页等处理导航的方法。
const history = useHistory();
const handleNavigation = () => {
history.push('/new-path'); // 导航到新的路径
};
2.1.2.2、match对象
包含了与当前路由匹配的信息,它通常在路由组件中作为 props 传递。
const User = ({ match }) => {
return <div>User ID: {match.params.userId}</div>;
};
const App = () => (
<Route path="/users/:userId" component={User} />
);
2.1.2.3、withRouter对象
高阶组件,用于将history、location 和match对象作为props传递给包装的组件,将一般组件加工,让其具备路由组件所特有的API。
const MyComponent = ({ history, location, match }) => {
const handleNavigation = () => {
history.push('/new-path'); // 导航到新的路径
};
return (
<div>
<h1>Current Path: {location.pathname}</h1>
<button onClick={handleNavigation}>Go to New Path</button>
</div>
);
};
export default withRouter(MyComponent);
类组件应用路由跳转:
import React from 'react';
import { withRouter } from 'react-router-dom';
class MyComponent extends React.Component {
handleNavigate = () => {
const { history } = this.props;
history.push('/new-route');
};
render() {
return (
<div>
<button onClick={this.handleNavigate}>Go to New Route</button>
</div>
);
}
}
export default withRouter(MyComponent);
2.2、向路由组件传参
2.2.1、传递params参数
类组件 :
函数组件:
const User = ({ match }) => {
const { userId } = match.params;
return <div>User ID: {userId}</div>;
};
2.2.2、传递search参数
类组件 :
函数组件:
import { useLocation } from 'react-router-dom';
const User = () => {
const location = useLocation();
const searchParams = new URLSearchParams(location.search);
const name = searchParams.get('name');
const age = searchParams.get('age');
return (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
</div>
);
};
2.2.3、传递state参数
类组件:
函数组件:
import { useLocation } from 'react-router-dom';
const User = () => {
const location = useLocation();
const { id,title } = location.state || {};
return (
<div>
<p>From Dashboard: {id}---{title}</p>
</div>
);
};
总结:
1、params:通过路由路径传递参数,使用match.params接收。
2、search:通过查询字符串传递参数,使用location.search和qs.parse【基于类组件】、location.search和URLSearchParams【基于函数组件】接收。
3、state:通过history.push或Link的to属性传递任意对象,使用location.state接收。补充:useHistory、useLocation、useParams等Hook在React 16.8之后才可用,并通过withRouterHOC进行路由的高阶组件包装。
2.3、编程式路由导航跳转
函数组件:
import React from 'react';
import { useHistory } from 'react-router-dom';
const MyComponent = () => {
const history = useHistory(); // 获取 history 对象
const handleNavigate = () => {
history.push('/new-route');
};
return (
<div>
<button onClick={handleNavigate}>Go to New Route</button>
</div>
);
};
export default MyComponent;
类组件:
<button onClick={() => this.pushShow(item.id, item.title)}>push查看</button>
<button onClick={() => this.replaceShow(item.id, item.title)}>replace查看</button>
replaceShow = (id, title) => {
this.props.history.replace(`/homes/message/detail/${id}/${title}`);
this.props.history.replace(`/homes/message/detail/?id=${id}/title=${title}`);
this.props.history.replace(`/homes/message/detail`,{id,title});
};
pushShow = (id, title) => {
this.props.history.push(`/homes/message/detail/${id}/${title}`);
this.props.history.push(`/homes/message/detail/?id=${id}/title=${title}`);
this.props.history.push(`/homes/message/detail`,{id,title});
};
三、React Router v6
下载:npm i react-router-dom@6
3.1、一级路由
Routes:
它用来包裹所有的<Route>,
并且确保只渲染匹配的第一个 <Route>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
3.2、重定向
<Route path="/" element={<Navigate to="/about" />}></Route>
3.3、NavLink高亮
function computedClassName({ isActive }) {
return isActive ? "list-item active" : "list-item";
}
<NavLink className={computedClassName} to="/about">About</NavLink>
<NavLink className={computedClassName} to="/homes">Home</NavLink>
3.4、useRoutes
3.5、嵌套路由
<Outlet />是一个占位符组件,用来渲染匹配的子路由的内容,父路由通常会渲染一个包含
<Outlet />
的组件,这样它就可以根据当前的 URL 渲染子路由对应的组件。
3.6、路由传参
3.6.1、params
<Route path="/user/:id" element={<UserProfile />} />
// UserProfile 组件中接收 params 参数
import { useParams } from 'react-router-dom';
const UserProfile = () => {
const { id } = useParams();
return <div>User ID: {id}</div>;
};
3.6.2、search
const [searchParams] = useSearchParams();
const q = searchParams.get("q"); // 获取查询参数 'q'
const page = searchParams.get("page"); // 获取查询参数 'page'
return (
<div>
<h1>搜索结果</h1>
<p>查询关键词:{q}</p>
<p>当前页码:{page}</p>
</div>
);
<Link to="/search?keyword=react">搜索React</Link>
// 在组件中接收查询参数
import { useLocation } from 'react-router-dom';
const Search = () => {
const location = useLocation();
const query = new URLSearchParams(location.search);
const keyword = query.get("keyword");
return <div>搜索关键词:{keyword}</div>;
};
3.6.3、state
<Link to={{ pathname: '/detail', state: { id: 1, name: 'React' } }}>详情</Link>
// 在目标组件中接收 state 参数
import { useLocation } from 'react-router-dom';
const Detail = () => {
const location = useLocation();
const { id, name } = location.state || {};
return (
<div>
<p>ID:{id}----------名称:{name}</p>
</div>
);
};
总结:
1、params:通过路由路径传递参数,使用useParams钩子接收。
2、search:通过查询字符串传递参数,使用useSearchParams或者useLocation和URLSearchParams解析。
3、state:通过Link或useNavigate传递状态参数,使用useLocation.state 来接收。
3.7、编程式路由导航
const navigate = useNavigate();
const handleClick = () => {
// 导航到 "/about" 页面,state参数写在对象里,params与search参数之间写url里
navigate('/about', { state: { fromDashboard: true } });
};
3.8、use拓展
useInRouterContext:检查组件是否在路由上下文中。
useNavigationType:获取当前导航类型(POP、PUSH、REPLACE)。
useOutlet:在父路由中渲染子路由的元素。
useResolvedPath:解析路径并返回路径对象
四、V6 pk V5
V6相比V5,进行了以下改动:
1、Routes代替了Switch、Navigate代替了Redirect;
2、useNavigate代替了useHistory,新增useParams、useLocation等,官方推荐函数组件。
3、路由匹配变得更精确,支持嵌套路由和动态路由的定义。
4、Route 组件的 API 也发生了改变,不再需要 component 或 render 属性,使用element 属性来传递渲染的组件。若项目使用的是React 16.3 ~16.7,只能使用React Router v5。
若项目使用的是 React 16.8 或更高版本,可以选择React Router v5或React Router v6,但建议使用v6,因为它包含了最新的功能和更简洁的 API。