• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

vue编写hash和history路由

武飞扬头像
哎_佳佳
帮助38

hash路由实现

一、hash路由原理
  1. hash是url中可读可写的字符串,改变hash不会导致页面重新加载
  2. 通过监听hashchange事件,可以获得hash改变之后的回调
  3. 根据不同的hash值,将对应内容插到元素上即可
二、创建router类
class newHashRouter {
  constructor(routes = []) {
    this.routes = routes; // 存储路由集合
    this.currentHash = ""; // 存储当前hash值
    this.matchRouter = this.matchRouter.bind(this); // 创建设置路由方法
    // 页面加载完之后,需要匹配一次路由内容(相当于初始化)
    window.addEventListener("load", this.matchRouter, false);
    // 页面触发hashchange的时候,匹配路由
    window.addEventListener("hashchange", this.matchRouter, false);
  }

  // 路由匹配方法,匹配路由,将路由的内容设置到页面上
  matchRouter(event) {
    let hash = "";
    if (event.newURL) {
      // hashchange才有这个newURL参数,针对hashchange事件获取hash值
      hash = this.getUrlPath(event.newURL);
    } else {
      // 针对load事件获取hash值
      hash = this.getUrlPath(location.hash);
    }
    // 设置路由
    this.setRouter(hash);
  }

  // 设置路由
  setRouter(hash) {
    this.currentHash = hash;
    // 查找当前匹配到的路由
    let curRoute = this.routes.find(
      (route) => route.path === this.currentHash
    );
    // 如果找不到,默认返回首页路由
    if (!curRoute) {
      curRoute = this.routes.find((route) => route.path === "/index");
    }
    let { component } = curRoute; // 解构出路由的component字段
    // 将结构出来的component挂载在页面
    document.getElementById("main").innerHTML = component;
  }

  // 获取url上的hash值
  getUrlPath(url) {
    // 获取hash
    return url.indexOf("#") >= 0 ? url.slice(url.indexOf("#")   1) : "/";
  }
}
三、实例化路由对象
 const router = new newHashRouter([
    {
      path: "/",
      name: "home",
      component: "<div>首页内容</div>"
    },
    {
      path: "/shop",
      name: "shop",
      component: "<div>商城内容</div>"
    },
    {
      path: "/shopping-cart",
      name: "shopping-cart",
      component: "<div>购物车内容</div>"
    },
    {
      path: "/mine",
      name: "mine",
      component: "<div>我的内容</div>"
    }
  ]);
四、路由实现
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"
      name="viewport"
    />
    <title>实现简单的hash路由</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      html,
      body {
        height: 100%;
      }
      #main {
        height: calc(100vh - 50px);
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 3em;
      }
      #nav {
        height: 50px;
        position: fixed;
        left: 0;
        bottom: 0;
        width: 100%;
        display: flex;
      }
      #nav a {
        width: 25%;
        display: flex;
        justify-content: center;
        align-items: center;
        border: 1px solid black;
      }
      #nav a:not(:last-of-type) {
        border-right: none;
      }
    </style>
  </head>
  <body>
    <main id="main"></main>
    <nav id="nav">
      <a href="#/">首页</a>
      <a href="#/shop">商城</a>
      <a href="#/shopping-cart">购物车</a>
      <a href="#/mine">我的</a>
    </nav>
  </body>
  <script>
    class xsHashRouter {
      constructor(routes = []) {
        this.routes = routes; // 存储路由集合
        this.currentHash = ""; // 存储当前hash值
        this.matchRouter = this.matchRouter.bind(this); // 创建设置路由方法
        // 页面加载完之后,需要匹配一次路由内容(相当于初始化)
        window.addEventListener("load", this.matchRouter, false);
        // 页面触发hashchange的时候,匹配路由
        window.addEventListener("hashchange", this.matchRouter, false);
      }

      // 路由匹配方法,匹配路由,将路由的内容设置到页面上
      matchRouter(event) {
        let hash = "";
        if (event.newURL) {
          // hashchange才有这个newURL参数,针对hashchange事件获取hash值
          hash = this.getUrlPath(event.newURL);
        } else {
          // 针对load事件获取hash值
          hash = this.getUrlPath(location.hash);
        }
        this.setRouter(hash);
      }

      // 设置路由
      setRouter(hash) {
        this.currentHash = hash;
        // 查找当前匹配到的路由
        let curRoute = this.routes.find(
          (route) => route.path === this.currentHash
        );
        // 如果找不到,默认返回首页路由
        if (!curRoute) {
          curRoute = this.routes.find((route) => route.path === "/index");
        }
        let { component } = curRoute; // 解构出路由的component字段
        // 将结构出来的component挂载在页面
        document.getElementById("main").innerHTML = component;
      }

      // 获取url上的hash值
      getUrlPath(url) {
        // 获取hash
        return url.indexOf("#") >= 0 ? url.slice(url.indexOf("#")   1) : "/";
      }
    }

    const router = new xsHashRouter([
      {
        path: "/",
        name: "home",
        component: "<div>首页内容</div>"
      },
      {
        path: "/shop",
        name: "shop",
        component: "<div>商城内容</div>"
      },
      {
        path: "/shopping-cart",
        name: "shopping-cart",
        component: "<div>购物车内容</div>"
      },
      {
        path: "/mine",
        name: "mine",
        component: "<div>我的内容</div>"
      }
    ]);
  </script>
</html>
五、实际效果

history路由实现

一、history原理

history方法:

  1. window.history.go 可以跳转到浏览器会话历史中的指定的某一个记录页
  2. window.history.forward 指向浏览器会话历史中的下一页,跟浏览器的前进按钮相同
  3. window.history.back 返回浏览器会话历史中的上一页,跟浏览器的回退按钮功能相同
  4. window.history.pushState 可以将给定的数据压入到浏览器会话历史栈中
  5. window.history.replaceState 将当前的会话页面的url替换成指定的数据

popstate方法:

  1. history.pushState和history.replaceState方法是不会触发popstate事件的
  2. 但是浏览器的某些行为会导致popstate,比如go、back、forward
  3. popstate事件对象中的state属性,可以理解是我们在通过history.pushState或history.replaceState方法时,传入的指定的数据

核心:

pushState和replaceState都会改变url且不会刷新页面

pushState往history中插入一条,replaceState是替换当前的这条会话历史

二、创建router类
class newHistoryRouter {
    constructor(path = []) {
      // 创建路由对象,用key,value存储路由
      this.routes = path;
      // 监听popstate方法(),触发时更新页面
      this.bindPopState();
    }

    // 初始化挂载路由
    init(path) {
      history.replaceState({ path: path }, null, path);
      this.setRouter(path);
    }

    // 路由跳转
    go(path) {
      // history插入新路由
      history.pushState({ path: path }, null, path);
      this.setRouter(path);
    }

    // 监听popstate方法,相当于监听go,forward,back这些方法
    // 因为触发go,forward,back这些方法,之后会触发监听popstate
    bindPopState() {
      window.addEventListener("popstate", (e) => {
        const path = e.state && e.state.path;
        this.setRouter(path);
      });
    }

    // 设置路由
    setRouter(path) {
      let curRoute = this.routes.find((route) => route.path === path);
      if (!curRoute) {
        this.routes.find((route) => route.path === "/");
      }

      let { component } = curRoute; // 解构出路由的component字段
      // 将结构出来的component挂载在页面
      document.getElementById("main").innerHTML = component;
    }
  }
三、实例化路由对象
const router = new newHistoryRouter([
  {
    path: "/",
    name: "home",
    component: "<div>首页内容</div>"
  },
  {
    path: "/shop",
    name: "shop",
    component: "<div>商城内容</div>"
  },
  {
    path: "/shopping-cart",
    name: "shopping-cart",
    component: "<div>购物车内容</div>"
  },
  {
    path: "/mine",
    name: "mine",
    component: "<div>我的内容</div>"
  }
]);
// 初始化入口链接
router.init(location.pathname);
四、路由实现
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"
      name="viewport"
    />
    <title>实现简单的history路由</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      html,
      body {
        height: 100%;
      }
      #main {
        height: calc(100vh - 50px);
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 3em;
      }
      #nav {
        height: 50px;
        position: fixed;
        left: 0;
        bottom: 0;
        width: 100%;
        display: flex;
      }
      #nav a {
        width: 25%;
        display: flex;
        justify-content: center;
        align-items: center;
        border: 1px solid black;
      }
      #nav a:not(:last-of-type) {
        border-right: none;
      }
    </style>
  </head>
  <body>
    <main id="main"></main>
    <nav id="nav">
      <a onclick="clickhref('/')">首页</a>
      <a onclick="clickhref('/shop')">商城</a>
      <a onclick="clickhref('/shopping-cart')">购物车</a>
      <a onclick="clickhref('/mine')">我的</a>
    </nav>
  </body>
  <script>
    class newHistoryRouter {
      constructor(path = []) {
        // 创建路由对象,用key,value存储路由
        this.routes = path;
        // 监听popstate方法(),触发时更新页面
        this._bindPopState();
      }

      // 初始化挂载路由
      init(path) {
        history.replaceState({ path: path }, null, path);
        this.setRouter(path);
      }

      // 路由跳转
      go(path) {
        // history插入新路由
        console.log(path);
        history.pushState({ path: path }, null, path);
        this.setRouter(path);
      }

      // 监听popstate方法
      _bindPopState() {
        window.addEventListener("popstate", (e) => {
          const path = e.state && e.state.path;
          this.setRouter(path);
        });
      }

      // 设置路由
      setRouter(path) {
        let curRoute = this.routes.find((route) => route.path === path);
        if (!curRoute) {
          this.routes.find((route) => route.path === "/");
        }

        let { component } = curRoute; // 解构出路由的component字段
        // 将结构出来的component挂载在页面
        document.getElementById("main").innerHTML = component;
      }
    }
    const router = new newHistoryRouter([
      {
        path: "/",
        name: "home",
        component: "<div>首页内容</div>"
      },
      {
        path: "/shop",
        name: "shop",
        component: "<div>商城内容</div>"
      },
      {
        path: "/shopping-cart",
        name: "shopping-cart",
        component: "<div>购物车内容</div>"
      },
      {
        path: "/mine",
        name: "mine",
        component: "<div>我的内容</div>"
      }
    ]);
    router.init(location.pathname);
    function clickhref(path) {
      router.go(path);
    }
  </script>
</html>
五、实际效果
六、注意

history模式刷新可以会报错,因为浏览器会把这个链接当成一个正式的请求发送到服务器,如果找不到这个静态资源就会报错。

所以一般情况下需要配置nginx

// 告诉服务器,当我们访问的路径资源不存在的时候,默认指向静态资源index.html
location / {   try_files $uri $uri/ /index.html; }

总结

  1. hash模式不用服务器配合,通过监听hashchange事件来处理前端业务逻辑,当拿到回调之后,匹配路由如果有就将对应的内容插入指定节点
  2. history模式需要服务器配合,通过监听pushState及replaceState事件,这两个操作时不会触发页面刷新结合popstate方法,对go、back、forward操作时,通过pushState及replaceState事件进行页面链接的替换及将对应的内容插入指定节点

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanfekce
系列文章
更多 icon
同类精品
更多 icon
继续加载