• React 学习之路由HashRouter和BrowserRouter


    React路由有两种实现方式:

    • HashRouter:利用hash实现路由切换
    • BrowserRouter:利用h5 Api实现路由切换

    1.1 HashRouter

    利用hash实现路由切换

    <body>
        <div id="root"></div>
        <a href="#/a">去/a</a>
        <a href="#/b">去/b</a>
      </body>
      <script>
        let root = document.getElementById('root')
        window.addEventListener('hashchange',(event) =>{
          let hash = window.location.hash
          root.innerHTML = hash
        })
      </script>

    模拟点击切换页面,每当浏览器里的hash值发生变化之后,就会触发一个事件,叫hashchange,这个函数有一个回调,可以通过window.location.hash拿到当前的hash值。

     1.2 BrowserRouter (浏览器路由)

    利用h5 Api实现路由切换,主要是借助history对象。

    • history对象提供了操作浏览器会话的历史接口。
    • historylength属性声明了浏览器历史列表中的元素数量。
    • pushState,H5引入了history.pushState()和history.replaceState()方法,它们分别可以添加和修改历史记录的条目,这些方法通常与window.onpopstate配合使用
    • onpopstate,window.onpopstate是popstate事件再window对象上的事件处理程序
     setTimeout( () => {
          //pushState不会触发事件
          window.history.pushState({page: 1},'page1','/page1')
        },1000)
        setTimeout( () => {
          //pushState不会触发事件
          window.history.pushState({page: 2},'page2','/page2')
        },2000)
        setTimeout( () => {
          //pushState不会触发事件
          window.history.pushState({page: 3},'page3','/page3')
        },3000)
        //后退的时候触发popstate
        setTimeout( () => {
          //go(-1)后退一个,会触发popstate事件
          window.history.go(-1)
        },4000)

    通过 window.history.pushState可以向history容器中存入当前路径,这个容器结构类似于栈,后进先出,当然也可以通过window.history.go这个方法后退到前一个路径,这个方法会触发一个popstate事件,通过这个事件我们可以做一些操作,比如向页面添加内容等:

    //这个事件会在go(-1)的时候触发,可以在触发的时候改变文档内容
        window.onpopstate = function(event){
          console.log(event)
          root.innerHTML = window.location.pathname
        }

     history对象在回退的时候有事件,但是在pushstate的时候并不会触发事件,我们要想自己做一些操作就需要改写一个onpushState事件,以便我们进行页面操作。

    let root = document.getElementById('root')
        window.onpushstate = function(state,title,url) {
          root.innerHTML = url
        }
    
        ;(function (history) {
          //1.缓存原生的pushState方法
          let pushState = history.pushState 
          //2.改写pushState方法
          history.pushState = function(state,title,url) {
            
            //3.自定义改写后的事件名为onpushstate
            if(typeof window.onpushstate === 'function') {
              window.onpushstate(state,title,url)
            }
            //4.调用原生方法并且执行
            pushState.call(history,state,title,url)
          }
        })(window.history)

    看过vue源码的同学肯定知道vue里面对数组的响应式处理就是通过改写数组的那7个方法实现的。我们这里也一样,拦截了原生的方法,对原生方法进行了缓存,然后再改写原生方法,最后再执行,就这么简单。

    完整版:

    <body>
        <div id="root"></div>
      </body>
      <script>
        let root = document.getElementById('root')
        window.onpushstate = function(state,title,url) {
          root.innerHTML = url
        }
    
        ;(function (history) {
          //1.缓存原生的pushState方法
          let pushState = history.pushState 
          //2.改写pushState方法
          history.pushState = function(state,title,url) {
            
            //3.自定义改写后的事件名为onpushstate
            if(typeof window.onpushstate === 'function') {
              window.onpushstate(state,title,url)
            }
            //4.调用原生方法并且执行
            pushState.call(history,state,title,url)
          }
        })(window.history)
        //这个事件会在go(-1)的时候触发,可以在触发的时候改变文档内容
        window.onpopstate = function(event){
          console.log(event)
          root.innerHTML = window.location.pathname
        }
        // window.history 这是浏览器原生提供的对象,通过它来操作会话容器
        setTimeout( () => {
          //pushState不会触发事件
          window.history.pushState({page: 1},'page1','/page1')
        },1000)
        setTimeout( () => {
          //pushState不会触发事件
          window.history.pushState({page: 2},'page2','/page2')
        },2000)
        setTimeout( () => {
          //pushState不会触发事件
          window.history.pushState({page: 3},'page3','/page3')
        },3000)
        //后退的时候触发popstate
        setTimeout( () => {
          //go(-1)后退一个,会触发popstate事件
          window.history.go(-1)
        },4000)
    
      </script>

    下一节写一个自己的路由库!

    不积跬步无以至千里
  • 相关阅读:
    关于CTeX的几个大坑
    latex与word之间的各种转化方法
    事件的三种绑定方式
    实例操作JSONP原理
    Content Security Policy 入门教程
    video.js
    Javascript面向对象类文章目录
    javaScript的原型继承与多态性
    javaScript的变量
    document.documentElement.clientHeight 与 document.body.clientHeight(杜绝千篇一律的抄袭!!)
  • 原文地址:https://www.cnblogs.com/lyt0207/p/12716369.html
Copyright © 2020-2023  润新知