目录结构:
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './components/app';
import { BrowserRouter } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
//如果要给前端页面加路由的话,一定要把组件包含在BrowserRouter里面
<BrowserRouter>
<App />
</BrowserRouter>
);
app.jsx
import React, { Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django'
import Web from './web';
import WebContent from './webContent';
import NotFound from './notFound';
import {Routes,Route} from 'react-router-dom';
import { Navigate } from 'react-router-dom';
//写路由:根据当前的url去选择我们在下面显示哪一个组件
class App extends Component {
state = { }
render() {
return (
<React.Fragment>
<NavBar />
{/* 如果想写多个路由的话,一定要将所有路由包含在routes里面 */}
{/* container也是bootstrap里的一个类,他可以动态的调整填充区域的内容,响应式的调整填充区域的内容 */}
<div className='container'>
<Routes>
<Route path='/' element={<Home />}/>
{/* 嵌套路由 */}
<Route path='/linux' element={(<Linux />
// <div>
// hhh
// <a href="/">返回首页</a>
// </div>
)}>
<Route path='homework' element={<h4>homework的内容</h4>}></Route>
<Route path='terminal' element={<h4>terminal的内容</h4>}></Route>
<Route path='*' element={<h4>其他</h4>}></Route>
</Route>
{/* 给组件Django传一个参数,直接在组件里写就可以了 */}
<Route path='/django' element={<Django id='hhh' />}/>
<Route path='/web' element={<Web />}/>
{/* 将/web/conntent/1中1变成一个变量可以写成:chapter,这样1这个位置的内容就会被保存到名字是chapter这个变量里面 */}
{/* 如果有多个参数每一个参数用一个冒号 */}
{/* <Route path='web/content/:chapter/:section' element={<WebContent />}/> */}
{/* 用第二种方式来获取参数,路由匹配的时候,他只匹配到问号前面的部分,问号后面的部分它是不匹配的 */}
<Route path='/web/content' element={<WebContent />}/>
<Route path='/404' element={<NotFound />} />
{/* 重定向
如果打开一个新的页面之后,如果这个页面不存在的话,就把他重定向到404
通配符* path="*"表示它可以匹配所有的路径
Navigate的属性to表示我们需要跳到哪一个链接里面*/}
<Route path='*' element={<Navigate replace to="/404" />}/>
</Routes>
</div>
</React.Fragment>
);
}
}
export default App;
navbar,js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class NavBar extends Component {
state = { }
render() {
return (
<nav className="navbar navbar-expand-lg bg-body-tertiary">
<div className="container-fluid">
{/* 实现每次不重复加载页面,Link组件可以直接让当前页面假装跳到另外一个页面,但其实并没有向后端发请求
将所有的a标签都变成Link,
<a className="navbar-brand" href="/">讲义</a> */}
<Link className='navbar-brand' to='/'>讲义</Link>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNavAltMarkup">
<div className="navbar-nav">
{/* <a className="nav-link active" aria-current="page" href="/">Home</a>
<a className="nav-link" href="/linux">Linux</a>
<a className="nav-link" href="/django">Django</a>
<a className="nav-link" href="/web">Web</a> */}
{/* 前端渲染,每次点完一个按钮之后,他并没有真的打开这个链接 */}
{/* 如果想给后端发请求返回整个页面的话就用一般的Link(a标签),如果不想给后端发请求,只想假装改变页面的话就用link(Link标签) */}
<Link className="nav-link" aria-current="page" to="/">Home</Link>
<Link className="nav-link" to="/linux">Linux</Link>
<Link className="nav-link" to="/django">Django</Link>
<Link className="nav-link" to="/web">Web</Link>
</div>
</div>
</div>
</nav>
);
}
}
export default NavBar;
home.jsx
import React, { Component } from 'react';
class Home extends Component {
state = { }
render() {
return (
<h1>Home</h1>
);
}
}
export default Home;
linux.js
import React, { Component } from 'react';
import { Outlet } from 'react-router-dom';
// Outlet可以用来填充我们linux子组件里的路由的内容
class Linux extends Component {
state = { }
render() {
return (
<React.Fragment>
<h1>Linux</h1>
<hr />
{/* 在地址栏输入http://localhost:3000/linux/homework可以渲染出来Linux子组件homework的内容
在地址栏输入http://localhost:3000/linux/terminal可以渲染出来Linux子组件terminal的内容 */}
<Outlet />
</React.Fragment>
);
}
}
export default Linux;
django.jsx
import React, { Component } from 'react';
class Django extends Component {
state = { }
render() {
console.log(this.props.id);
return (
<h1>Django</h1>
);
}
}
export default Django;
web.jsx
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class Web extends Component {
state = {
webs:[
{id:1,title:"HTML"},
{id:2,title:"CSS"},
{id:3,title:"JavaScript"},
{id:4,title:"拳皇"},
{id:5,title:"React"},
]
}
render() {
//要渲染一个标题和一个内容所以要渲染两个东西,两个东西就需要先将他用React.Framement先括起来
return (
<React.Fragment>
<h1>Web</h1>
<hr />
<div>
{this.state.webs.map(web=>(
//循环里面每一个组件都有一个唯一的key,唯一的key可以搞成id
//给每一个元素加上一个链接,前端渲染加链接要放到Link里面
<div key={web.id}>
{/* <Link to={`/web/content/${web.id}`}>{web.id+"."+web.title}</Link> */}
{/* 2 */}
<Link to={`/web/content?chapter=${web.id}`}>{web.id+"."+web.title}</Link>
</div>
))}
</div>
</React.Fragment>
);
}
}
export default Web;
webContent.jsx
import React, { Component } from 'react';
// 1
import { useParams } from 'react-router-dom';
// 2
import { useSearchParams } from 'react-router-dom';
import { Link } from 'react-router-dom';
//传参数的方式
// 1.直接在url里面写
// http://localhost:3000/web/content/1/3
// 2.通过url里面传参数的话,可以在问好后面写,变量名等于什么值
// http://localhost:3000/web/content?chapter=1§ion=3
//如果是类组件的话,不能直接在类组件中访问useParams
//有两种修改方式,1.直接将类组件变成函数组件
//2.虽然在类里不能用但在调用这个类之前可以用,即在类外面用
class WebContent extends Component {
state = {
// useSearchParams是一个数组有两个值,第一个值是获取参数,第二个值是设置参数
//这个两个都是函数
searchParams:this.props.params[0],//获取某一个参数
setSearchParams:this.props.params[1],//将我们链接里面的参数设置成什么然后重新渲染当前页面
};
render() {
// 1
// console.log(this.props.params);
// 2
// console.log(this.state.searchParams.get('section'));
return (
<React.Fragment>
{/* 把那个数字取出来 */}
<h1>Web - {this.state.searchParams.get('chapter')}</h1>
<div>内容</div>
<hr />
<Link to='/web'>返回</Link>
</React.Fragment>
);
}
}
// export default WebContent;
//返回一个匿名函数,这个匿名函数会返回一个组件,这个匿名函数就是一个匿名组件,其实就是一个函数组件,外面本质上还是在函数组件里用的,但是外面相当于是在类组件外面套了一层函数组件
export default (props)=>(
<WebContent
{...props}//把函数组件里的属性展开
params={useSearchParams()}//再将它的值作为一个属性传进去就可以了
/>
);
//sfc函数组件
// const WebContent = () => {
// console.log(useParams());
// return (
// <h1>Web - 1</h1>
// );
// }
// export default WebContent;
notFound.jsx
//当找不到页面的时候返回404页面
import React, { Component } from 'react';
class NotFound extends Component {
state = { }
render() {
return (
<h1>NotFound</h1>
);
}
}
export default NotFound;