SPA俗称单页面应用。就类似于我们所看到的网站都集成于一个html文件,然后在网站交互的过程中始终保证在此页面上进行展示。页面标签不进行刷新,给用户一种未跳转的假象,但是也会面临着初次加载慢等。
单页应用程序是一种基于 Web 技术的应用程序架构模式,其中所有的页面加载、渲染和切换都在单个 HTML 页面中完成,而不需要每次切换页面时重新加载整个页面。相反,通过使用 JavaScript 和 AJAX 技术,SPA 在单个页面内动态地加载和更新内容。
在传统的多页应用程序中,每个页面对应一个独立的 HTML 文件,每次切换页面都需要从服务器重新加载整个页面。而在 SPA 中,初始加载时只需要下载一个 HTML 文件,之后的页面切换通过动态加载数据和更新页面的方式进行,大大提高了用户体验和页面加载速度。
SPA 的优点包括:
更快的用户体验:因为只需要加载一次初始页面,后续的页面切换只需要加载数据和更新部分内容,响应更迅速。
减少服务器负载:由于只需要返回数据而不是整个页面,减少了服务器端的压力和带宽消耗。
更流畅的页面切换:通过使用前端路由技术,可以实现无刷新的页面切换,提供更加流畅的用户界面。
更好的交互性:SPA 可以通过 JavaScript 操作 DOM 元素和响应用户事件,实现更丰富的交互效果。
可维护性和可扩展性:通过使用前端框架(如React、Angular、Vue等),可以将应用程序拆分为组件,提高代码的可维护性和可扩展性。
路由就类似于我们所使用的路由器,正是因为有路由的出现,才使用我们能够在单页面应用中实现不同页面的切换,因为路由中存在一组key和value的值。就无需刷新页面。
在react中我们需要引入第三方包来进行操作。这里引入的是react-router-dom@6的版本。然后我们可以根据其中提供的各种的API完成单页面的路由切换。我们也可以不在指定默认的版本,系统会自动帮我们npm对应的版本
下列分别引入的是路由的模式,路由的链接,以及自定义激活状态的路由连接。下面是在render中渲染的html标签。
import {BrowserRouter,Link,NavLink} from 'react-router-dom'
import React from 'react';
import {NavLink,Route,Routes} from 'react-router-dom'
import Header from './component/Header'
import About from './page/About';
import Home from './page/Home';
function App() {
return(
About
Home
{/* 注册路由,也就是写对应的关系 */}
{/* 路由可以匹配多个路径,因此可以展示多个组件,但是按道理应该只匹配一个即可,而且多个匹配会很耗费性能
Switch:就可以保证路由在匹配到第一个路径之后,就不和继续向下走。 */}
}/>
{/* exact={true}:开启严格匹配的模式,路径必须一致 */}
}/>
{/* Redirect:如果上面的都没有匹配到,就匹配到这个路径下面 */}
{/* */}
)
//通过 ...将状态中的全部赋值过去
}
export default App;
首先是路由模式。在react中如果我们要使用路由,那么要确保路由模式要完全包裹住link和route。这里为了方便我们可以将路由包裹在最外面的App标签中。这样无论我们在后面怎么添加路由信息。都会保证路由被包裹在路由模式中
ReactDOM.render(
,document.getElementById("root"))
然后就是Link和NavLink。其实这两种归根结底都是一样的。只是后面这种我们可以动态的修改其激活状态的样式。该函数我们需要传递to,也很好理解就是跳转到那个路由上。不过建议其跳转的path都采取小写的写法。而下面的我们可以自定义其对应的路由信息
Home
但在开发过程中我们可能所写的路由信息不止一个,可能会有很多个。因此可能对应的path可能会有重复。这时我们可以使用Switch、当然也需要从react-router-dom中引入。使用它的好处是我们可以避免匹配到合适的path时仍要往下匹配。节约了时间和效率。
然后在6版本中我们引入路由不再是使用component,而是使用element这种形式引入路由
}/>
}/>
然后在版本6中我们也不在使用Redirect来进行路由的重定向了,而是使用如下代码来进行路由的重定向。 并且如果我们在页面中需要等到何时的时机来进行路由重定向的时候,我们也可以使用Navigate来进行操作
在版本6中我们也不在使用手写路由的形式来进行,而是可以借助对应的对应的函数来进行声明路由表的相关操作。我们可以是用useRoutes来帮我们构建路由表,从而实现路由的对应跳转。
由于这里的Navigate作为的是一个标签,则对应的to直接跟在其后面就可以。然后我们在对应使用出直接进行调用即可
import About from '../page/About';
import Home from '../page/Home';
import { Navigate } from 'react-router-dom';
const staticRoute = [
{
path:'/about',
element:
},
{
path:'/home',
element:
},
{
path:'/',
element:
}
]
export default staticRoute
然后就相当于和vue中的route表一样,就会帮我们生成对应的路由信息。后续在其他文章中也会展示动态路由是如何操作的。
const element = useRoutes(staticRoute)
{/* 注册路由,也就是写对应的关系 */}
{/* 路由可以匹配多个路径,因此可以展示多个组件,但是按道理应该只匹配一个即可,而且多个匹配会很耗费性能
Switch:就可以保证路由在匹配到第一个路径之后,就不和继续向下走。 */}
{/* */}
{/* 使用Navigate作为标签是,对应的to直接跟在后面 */}
{element}
在版本6中的NavLink自定义动态的class也不再是5中用activeClassName这样来进行动态的绑定,而是需要我们给class绑定对应的函数。则实现形式如下。因为在函数中所传递的参数中我们只需要看对应的isActive是否为true,因此我们在这里就根据对应的函数返回值来给其动态的添加class类。
{return isActive ? 'bg-red' : 'list-group-item'}} to="/about">About
然后由于在router6中我们可以使用路由表的形式来进行路由的嵌套。因此我们的默认跳转也会写到路由表中。使用是Navigete 后面加上to的形式来进行路由的跳转切换。代码如下。这样就实现了我们路由默认跳转的情况。
import About from '../page/About';
import Home from '../page/Home';
import { Navigate } from 'react-router-dom';
const staticRoute = [
{
path:'/about',
element:
},
{
path:'/home',
element:
},
{
path:'/',
element:
}
]
export default staticRoute
5.路由传参
React中路由传参大概有三种,分别是search、params、state。下面将分别讲解其中的传参思路
5.1 params传递参数
第一种传递参数params参数,在Link中我们需要用/属性的形式传递
{item.message}
我们可以在对应的链接Link中进行传递参数的操作,当然是通过/属性的形式添加到对应的url后面。然后在路由Route那进行对应参数的接口使用的是/:属性的形式。然后传递到对应页面中的props中的metch中。
this.props.match.params
5.2 search传递参数
我们通过search传递参数时,对应的格式为?key=value&key=value的形式来进行传递。因此我们需要在Link中将需要传递的参数按照上述格式进行书写。因此代码如下
{item.message}
{
path:'message',
element: ,
children:[
{
// path:'detail/:id',
path:'detail',
element:
}
]
},
在路由页面由于我们不再是使用的类式组件,而是使用的是函数式组件,因此我们也需要引入hook中的useSearchParams来进行对应的获取search参数
const [search] = useSearchParams()
console.log(search.get('id'))
5.3 state 传递参数
我们可以在Link中不在只是写入单单的字符串,而是可以写入自定义的对象,这样就可以实现对state传递参数。
{item.message}
接受的话需要我们特别处理一下,因为state在location中默认值时underfined,因此我们在操作时就需要使用 || 来避免在underfined上 取属性。因此需要实现对应的引入hook函数,如useLocation
const {state:{id}} = useLocation()
5.4总结
上述三种路由传参都是比较常用的。但是如果我们不想让其他用户知道我们路径上传递的什么参数,则我们可以使用第三种方法。如果是携带参数的话我们可以使用第一或者第二种方法。
6.路由跳转
我们在版本5中我们可以是用路由组件中的props.history来获取对应的操作元素的API。如果该组件不是路由组件,我们也可以使用withRouter将非路由组件转化为对应的路由组件,从而拥有操作history的API。需要在暴露的时候进行使用。
export default withRouter(withRouterDemo)
但在函数式组件中不拥有对应的this,因此我们需要使用hooks来引入对应的操作路由的API。如useNavigate,该方法接收两个参数,第一个是跳转的路由,第二个事可以传入待传项的state参数。 如果只填数字,就类似于back和go一样的效果
navigate('detail',{})