您的当前位置:首页正文

Hash模式与History模式

2024-11-10 来源:个人技术集锦

13.1 Hash模式与History模式区别
前端路由中,不管是什么实现模式,都是客户端的一种实现方式,也就是当路径发生变化的时候,是不会向服务器发送请求的。

如果需要向服务器发送请求,需要用到ajax方式。

两种模式的区别

首先是表现形式的区别

Hash模式

当然这种模式相对来说比较丑,路径中带有与数据无关的符号,例如#与?

History模式

https://www.baidu.com/showlist/22256
1
History模式是一个正常的路径的模式,如果要想实现这种模式,还需要服务端的相应支持。

下面再来看一下两者原理上的区别。

Hash模式是基于锚点,以及onhashchange事件。

History模式是基于HTML5中的History API

也就是如下两个方法

history.pushState( ) IE10以后才支持

history.replaceState( )

因为浏览器在刷新页面时,它会向服务器发送 GET 请求,但此时服务器并没有配置相应的资源来匹配这个请求,因此返回 404 错误。

2、解决方案
为了解决这个问题,我们需要在服务器端进行相关配置,让所有的路由都指向同一个入口文件(比如 index.html),由前端路由来处理 URL 请求,返回对应的页面内容。

具体的配置方式取决于对应项目使用的服务器环境,常见的有 Apache、Nginx 等。

以 Nginx 为例,需要在服务器配置文件(通常是 nginx.conf.js )中添加以下配置,以将所有请求都代理到 Vue 应用程序的入口文件:

try_file $uri$uri/ index.html

同时需要注意在使用 History 模式时,需要保证所有路由的访问路径都指向 index.html,否则仍然会出现404错误。

这些配置将确保在 Vue 应用程序中使用 history 模式时,服务器能够正确地处理所有路由请求,并返回正确的页面。

13.2 History模式的使用

History模式需要服务器的支持,为什么呢?

所以说,在服务端应该除了静态资源外都返回单页应用的index.html

下面我们开始history模式来演示一下对应的问题。

首先添加一个针对404组件的处理

首先在菜单栏中添加一个链接:

      <div class="content left">
        <ul>
          <li><router-link to="/users"> 用户管理</router-link></li>
          <li><router-link to="/rights"> 权限管理</router-link></li>
          <li><router-link to="/goods"> 商品管理</router-link></li>
          <li><router-link to="/orders"> 订单管理</router-link></li>
          <li><router-link to="/settings"> 系统设置</router-link></li>
          <li><router-link to="/about"> 关于</router-link></li>
        </ul>
      </div>

这里我们添加了一个“关于”的链接,但是我们没有为其定义相应的组件,所以这里需要处理404的情况。

const NotFound = {
template: <div> 你访问的页面不存在!! </div>,
};

在程序中添加了一个针对404的组件。

const router = new VueRouter({
mode: “history”,
const router = new VueRouter({
mode: “history”,
routes: [
{ path: “/login”, component: Login },
{ path: “*”, component: NotFound },
{
path: “/”,
component: App,
redirect: “/users”,
children: [
{
path: “/users”,
component: Users,
meta: {
auth: true,
},
// beforeEnter(to, from, next) {
// if (window.isLogin) {
// next();
// } else {
// next(“/login?redirect=” + to.fullPath);
// }
// },
},
{ path: “/userinfo/:id”, component: UserInfo, props: true },
{ path: “/rights”, component: Rights },
{ path: “/goods”, component: Goods },
{ path: “/orders”, component: Orders },
{ path: “/settings”, component: Settings },
],
},
],
});

在上面的代码中,指定了处理404的路由规则,同时将路由的模式修改成了history模式。同时,启用这里启用了其它的组件的路由规则配置,也就是不在login方法中使用addRoutes方法来动态添加路由规则了。

login 方法修改成如下形式:

login() {
// window.isLogin = true;
window.sessionStorage.setItem(“isLogin”, true);
if (this.KaTeX parse error: Expected '}', got 'EOF' at end of input: … // this.router.addRoutes([
// {
// path: “/”,
// component: App,
// redirect: “/users”,
// children: [
// {
// path: “/users”,
// component: Users,
// meta: {
// auth: true,
// },
// // beforeEnter(to, from, next) {
// // if (window.isLogin) {
// // next();
// // } else {
// // next(“/login?redirect=” + to.fullPath);
// // }
// // },
// },
// { path: “/userinfo/:id”, component: UserInfo, props: true },
// { path: “/rights”, component: Rights },
// { path: “/goods”, component: Goods },
// { path: “/orders”, component: Orders },
// { path: “/settings”, component: Settings },
// ],
// },
// ]);
this. r o u t e r . p u s h ( t h i s . router.push(this. router.push(this.route.query.redirect);
} else {
this.$router.push(“/”);
}
}

现在已经将前端vue中的代码修改完毕了,下面我们要将页面的内容部署到node.js服务器中。

而且上面的代码中,我们使用了sessionStorage来保存登录用户的信息,不在使用window下的isLogin

对应的data内容下的代码也要修改:

const Login = {
data() {
return {
isLogin: window.sessionStorage.getItem(“isLogin”),
};
},

路由守卫中的代码进行如下修改:

jsrouter.beforeEach((to, from, next) => {
//to:去哪个页面,from来自哪个页面,next继续执行.
if (window.sessionStorage.getItem(“isLogin”)) {
//用户已经登录
if (to.path === “/login”) {
// 用户已经登录了,但是又访问登录页面,这里直接跳转到用户列表页面
next(“/”);
} else {
//用户已经登录,并且访问其它页面,则运行访问

        next();
      }
    } else {
      //用户没有登录,并且访问的就是登录页,则运行访问登录页
      if (to.path === "/login") {
        next();
      } else {
        //用户没有登录,访问其它页面,则跳转到登录页面。
        next("/login?redirect=" + to.fullPath);
      }
    }
  });

在上面的代码中,我们也是通过sessionStorage来获取登录信息。

index.html完整代码如下:

基于vue-router的案例

下面看一下具体的node代码的实现。

app.js文件中的代码如下:

connect-history-api-fallback模块的安装如下(注意在上面的代码中还没有使用该模块)

npm install --save connect-history-api-fallback
1
下面还需要安装express

npm install express
1
启动服务

并且当我们去单击左侧的菜单的时候,可以实现页面的切换,同时单击“关于”的时候,会出现NotFound组件中的内容。

经过测试发现好像没有什么问题,那这是什么原因呢?你想一下当我们单击左侧菜单的时候,路由是怎样工作的呢?

所以说现在整个操作都是在客户端完成的。

但是,当我刷新了浏览器以后,会出现怎样的情况呢?

以上就是如果vue-router开启了history模式后,出现的问题。

下面解决这个问题,在服务端启用connect-history-api-fallback模块就可以了,如下代码所示:

const path = require(“path”);
//导入处理history模式的模块
const history = require(“connect-history-api-fallback”);
const express = require(“express”);
const app = express();
//注册处理history模式的中间件
app.use(history());
//处理静态资源的中间件
app.use(express.static(path.join(__dirname, “…/web”)));
app.listen(3000, () => {
console.log(“服务器开启”);
});

服务端的代码做了修改以后,一定要服务端重新启动node app.js

然后经过测试以后发现没有问题了。

那么现在你考虑一下,具体的工作方式是什么?

当我们在服务端开启对history模式的支持以后,我们刷新浏览器,会想服务器发送请求,例如:http://localhost:3000/orders

显示全文