zoukankan      html  css  js  c++  java
  • 前端路由(history+hash)

    在传统网站开发中,我们一般使用比如asp、php、jsp等技术进行开发,开发完成后统一部署在服务器上,我们访问时,会在浏览器中发送带有'.asp','.php','.jsp'等后缀路径的url请求,服务器会根据对应的路由映射表,找到我们请求的页面并渲染成html,然后把html页面直接返回给浏览器展示,这就是所谓的服务器端渲染SSR(Server Side Render)。

    然而随着前端页面复杂性的提高以及前端技术的兴起(尤其是Ajax技术的兴起),行业内越来越推崇前后端分离的开发模式。使服务器端不在关注HTML页面的渲染,而是只专注于逻辑的开发,通过Api提供数据;前端只专注于UI的开发,把从服务器请求的数据生成DOM插入到页面中去。从服务器请求数据,然后由客户端通过前端技术生成展示页面的方式就是客户端渲染CSR(Client Side Render)。

    客户端渲染使前后端进行了分离,各自只关注属于自己的部分,并且使用户体验也得到了提升,用户交互不用每次都刷新页面。基于这些优点,单页应用(SPA(Single Page Web Application))的开发模型备受青睐。可以做到动态重写当前页面来与用户交互,而不需要重新加载整个页面。然而要实现单页应用,做到交互和跳转都不需要刷新的体验,需要解决一个重要问题,就是路由问题。所以就有了前端路由,其实前端路由是相对于服务器端路由的称谓,由前端控制维护url和UI之间的映射关系,url更改后引起ui更新,而无需刷新页面。

    下面就让我们通过两种方式实现前端路由:

    实现前端路由的整体思路:首先维护一张包含path和对应的页面内容的路由映射表,当监听到路由发生变化后,从路由映射表中筛选出对应的路由信息,并把路由信息中对应的内容页面渲染添加到html页面展示。开始之前先了解下两种方式的基本知识。

    1.window.history

    Window.history是一个只读属性,用来获取包含操作浏览器会话历史History 对象。
    主要方法:
    back()
    前往上一页, 用户可点击浏览器左上角的返回按钮模拟此方法. 等价于 history.go(-1)
    forward()
    在浏览器历史记录里前往下一页,用户可点击浏览器左上角的前进按钮模拟此方法. 等价于 history.go(1)
    go()
    通过当前页面的相对位置从浏览器历史记录( 会话记录 )加载页面
    pushState()
    按指定的名称和URL(如果提供该参数)将数据push进会话历史栈,数据被DOM进行不透明处理;你可以指定任何可以被序列化的JavaScript对象。
    replaceState()
    按指定的数据,名称和URL(如果提供该参数),更新历史栈上最新的入口。这个数据被DOM 进行了不透明处理。你可以指定任何可以被序列化的JavaScript对象。

    电脑刺绣绣花厂 http://www.szhdn.com 广州品牌设计公司https://www.houdianzi.com

    2.location.hash

    hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)。

    实现代码如下:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>window.history路由</title>
    </head>
    
    <body>
      <div>
        <div id="routerLink">
          <div>
            <button onclick="historyChange('home')">首页(history)/button>
              <button onclick="historyChange('about')">关于(history)</button>
          </div>
          <div>
            <button onclick="hashChange('home')">首页(hash)</button>
            <button onclick="hashChange('about')">关于(hash)</button>
          </div>
        </div>
        <div>
          <div id="routerView">
    
          </div>
        </div>
      </div>
      <!-- 2.创建子视图模板 -->
      <template id="home">
        <div>hello,我是首页</div>
      </template>
      <template id="about">
        <div>hello,我是关于</div>
      </template>
      <script>
        //1.首先创建路由表
        const routerTable = [
          {
            path: 'home',
            component: '#home'
          },
          {
            path: 'about',
            component: '#about'
          }
        ]
    
        //*********** 方式一:window.history **************
        //3.(window.history)监听路由更改,根据新路由path加载对应的内容
        function historyChange(path) {
          render({ path: path })
        }
        //添加popstate状态监听
        window.addEventListener('popstate', function (e) {
          if (e) {
            render({ path: e.state, isPush: false })
          }
        })
    
        //************** 方式二:location.hash ***************
        function hashChange(path) {
          render({ path: path, mode: 'hash' })
        }
        //添加hashchange监听
        window.addEventListener('hashchange', function () {
          let path = location.hash
          //path移除开始的#
          render({ path: path.substring(1, path.length - 2), mode: 'hash' })
        })
    
        //**************公共方法*******************
        //渲染方法
        function render(data) {
          //默认值,mode默认为history,isPush=true,isReplace=false,path=home
          data = Object.assign({ mode: 'history', isPush: true, isReplace: false, path: 'home' }, data)
          if (data.path) {
            //查询路由信息
            const route = routerTable.find(p => p.path == data.path);
            if (route) {
              if (data.mode == 'history') {
                if (data.isPush) {
                  //更改url---后退、前进不更改
                  if (data.isReplace) {
                    window.history.replaceState(data.path, '', data.path)
                  } else {
                    window.history.pushState(data.path, '', data.path)
                  }
                }
              } else if (data.mode == 'hash') {
                location.hash = data.path
              }
              //更新html
              document.querySelector("#routerView").innerHTML = document.querySelector(route.component).innerHTML
            }
          }
        }
      </script>
    </body>
    </html>
  • 相关阅读:
    mysql数据增删改查
    Python中的逻辑运算
    Python的格式化输出
    Python变量的命名规则
    解释型语言和编译型语言的比较?
    SQLAlchemy
    ansible
    算法
    数据分析
    scrapy之日志等级
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/13821658.html
Copyright © 2011-2022 走看看