路由配置差异
- 服务端路由配置
- 主要用于在服务端生成初始的HTML页面。由于服务端没有浏览器环境,不需要考虑DOM操作等与浏览器强相关的功能。
- 服务端路由更侧重于根据请求的URL直接匹配对应的组件,并渲染出相应的HTML片段。例如在使用
vue - server - renderer
时,会依据路由规则找到匹配的组件,进行数据预取(如果需要)后渲染。
- 服务端路由需要考虑性能和资源消耗,避免在服务端执行过多复杂的、非必要的操作。
- 客户端路由配置
- 运行在浏览器环境中,除了基本的路由匹配功能外,还需要处理页面的过渡动画、前进后退等浏览器历史相关的操作。
- 客户端路由在切换路由时,一般通过
history.pushState
或hashchange
事件来更新URL,并动态地挂载和卸载组件,实现无刷新页面切换。例如使用vue - router
在客户端配置路由时,可以轻松实现页面间的平滑过渡效果。
确保路由状态一致性
- 使用相同的路由定义
- 在服务端和客户端都使用同一个路由配置文件(或共享路由配置逻辑)。例如定义一个
router.js
文件,在服务端和客户端引入并使用相同的路由规则,这样可以确保双方对于路由的定义是一致的。
- 如:
// router.js
import Vue from 'vue';
import Router from 'vue - router';
import Home from '@/components/Home';
import About from '@/components/About';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
});
- 数据预取与同步
- 在服务端渲染时,根据路由匹配进行数据预取。例如在服务端获取组件所需的数据后,将数据序列化并注入到HTML页面中。客户端在激活时,从HTML中提取数据,并将其作为初始数据使用,从而确保客户端和服务端渲染的数据一致性,进而保证路由状态一致。
- 以一个获取用户列表的页面为例,服务端在渲染该路由对应的组件时,获取用户列表数据并注入到HTML中:
// 服务端渲染逻辑
import { createRenderer } from 'vue - server - renderer';
import app from './app';
import router from './router';
import axios from 'axios';
const renderer = createRenderer();
router.onReady(() => {
const context = {};
const { path } = router.currentRoute;
if (path === '/userList') {
axios.get('/api/userList').then(response => {
context.userList = response.data;
renderer.renderToString(app, context, (err, html) => {
// 将html返回给客户端,同时userList数据已注入到context中并会包含在html里
});
});
}
});
// 客户端激活逻辑
import Vue from 'vue';
import app from './app';
import router from './router';
const clientApp = new Vue({
router,
render: h => h(app)
});
const context = window.__INITIAL_STATE__;
if (router.currentRoute.path === '/userList') {
clientApp.$data.userList = context.userList;
}
clientApp.$mount('#app');
- 路由模式统一
- 服务端和客户端都使用相同的路由模式,例如都使用
history
模式或都使用hash
模式。如果在服务端使用history
模式,需要在服务器端配置好相应的重写规则,确保所有请求都能正确匹配到应用程序的入口文件,以避免404错误。在客户端也使用history
模式时,vue - router
会使用history.pushState
来管理路由,这样双方路由的行为和表现更加一致。