美文网首页
前端路由 router 原理及表现

前端路由 router 原理及表现

作者: 南枫小谨 | 来源:发表于2021-05-10 20:36 被阅读0次

    原始时代路由

    路由全部都是由服务端控制的,前端代码和服务代码过度融合在一起。
    客户端/前端发起http请求,服务端通过不同的url路径去匹配不同的路由/返回不同的数据
    优点:直接返回一个html文档,渲染页面结构。SEO效果很好,首屏时间快
    缺点: 前端代码和服务代码融合在一起,开发协同非常混乱。服务器压力大,因为把构建html的工作放在服务端。

    单页面应用

    所谓的单页面是指只有一个html 文档。
    特点:

    1. 页面中的交互是不刷新页面的,比如点击按钮,比如点击出现一个弹窗
    2. 多页面间的交互不需要刷新页面,比如跳转
    3. 加载过的公共资源无需重复加载
    4. 不同url 会渲染不同内容

    Hsah 与History

    1. 直观上看 hash路由有#,history 路由没有
    2. hash 的#部分内容不会给服务端,history 路由的所有内容都会给服务端
    3. hash 通过hashchange 监听变化,history 通过 popstate 监听变化

    Hsah

    特点

    1. url 中带有#号, # 后面的部分不会传递给服务端
      举个例子 www.XXX.com/#/uder/xiaoming 服务器只能拿到 www.XXX.com/
    2. hash 值得更改不会导致页面刷新
      location.hash = '#user' 改为 location.hash = '#home'
      html 文档不会刷新
    3. hash 值得更改,会在浏览器的访问历史中添加一条记录,所以我们才可以通过浏览器的返回、前进按钮来控制hash的切换
    4. hash 值得更改会触发hashchange 事件
      location.hash = '#user' 改为 location.hash = '#home' 可以通过
      window.addEventLisenter('hashchange',()=>{})监听

    如何更改hash

    1. location.hash="#xiaoming"
    2. html 标签样式 <a href="#xiaoming" >点击跳转到xiaoming</a>

    html5 history

    window.history.back() // 后退
    window.history.forward() // 前进
    window.history.go() // 可传一个number ,正值前进 负值后退
    window.history.pushState(null,null,null)
    window.history.replaceState(null,null,null)
    

    pushState/replaceState 的参数

    1. state 是一个对象与指定网址相关,当popstate 事件触发的时候该对象会传入回调函数
    2. title 新页面的标题,浏览器支持不一,null
    3. url 页面新地址

    History 的特性

    pushState时会触发popState 吗?

    1. 没有#
    2. pushState/replaceState 并不会触发 popstate 事件, 这时我们需要手动触发页面的重新渲染。
    3. 我们可以使用 popstate 来监听 url 的变化
    4. popstate 到底什么时候才能触发。
      4.1 点击浏览器后退按钮
      4.2 点击浏览器前进按钮
      4.3 js 调用 back 方法
      4.4 js 调用 forward 方法
      4.5 js 调用 go 方法

    手写一个hashRouter 简易版

    class BaseRouter{
        constructor(){
            this.routes = {}
            this.refresh = this.refresh.bind(this);
            window.addEventListener('load', this.refresh); 
            window.addEventListener('hashchange', this.refresh); 
        }
        router(path,callback){
            this.routes[path] = callback || function(){}
        }
        refresh(){
            const path = `/${location.hash.slice(1) || '' }`
            this.routes[path]();
        }
    
    }
    
    
    let body = document.querySelector('body')
    
    function changeBgColor(color){
        body.style.backgroundColor= color
    }
    
    const Router = new BaseRouter()
    Router.router('/',function(){
        changeBgColor('white')
    })
    Router.router('/green',function(){
        changeBgColor('green')
    })
    Router.router('/gray',function(){
        changeBgColor('gray')
    })
    

    手写一个historyRouter 简易版

    class BaseRouter{
        constructor(){
            this.routers = {}
            this.init(location.pathname)
            this._bindPopState()
        }
        init(path){
            window.history.replaceState(path,null,path)
            const cb = this.routers[path] 
            cb && cb()
        }
        router(path,callback){
            this.routers[path] = callback || function(){}
        }
        _bindPopState(){
            window.addEventListener('popsate',(e)=>{
                const path = e.state && e.state.path
                this.routers[path] && this.routers[path]()
            })
        }
        go(path){
            window.history.pushState({path},null,path)
            const cb = this.routers[path]
            cb && cb()
        }
       
    }
    
    
    let body = document.querySelector('body')
    const container = document.querySelector('.container');
    function changeBgColor(color){
        body.style.backgroundColor= color
    }
    
    const Router = new BaseRouter()
    Router.router('/',function(){
        changeBgColor('white')
    })
    Router.router('/green',function(){
        changeBgColor('green')
    })
    Router.router('/gray',function(){
        changeBgColor('gray')
    })
    container.addEventListener('click',(e)=>{
        if(e.target.tagName === 'A'){
            e.preventDefault()
            Router.go(e.target.getAttribute('href'))
        }
    })
    

    historyRouter 需要后端配合,将路由映射地址改为index.html

    相关文章

      网友评论

          本文标题:前端路由 router 原理及表现

          本文链接:https://www.haomeiwen.com/subject/fdfwdltx.html