zoukankan      html  css  js  c++  java
  • 详解H5中的history单页面,手动实现单页面开发,细说h5单页面原理

    就目前来看,前端的单页面开发占了很大一部分,一方面无刷新的切换增强了体验,并且浏览器记录依然存在,前进后退都没问题,在之前我们通地址栏中的hash改变来触发onhashchange方法来实现单页面应用,但是#的形式总是令人不爽,幸好h5新增了history.pushState与history.replaceState。

    1.介绍API

    history.pushState(data, title [, url]):

    往历史记录堆栈顶部添加一条记录; data会在onpopstate事件触发时作为参数传递过去,title为页面标题,当前所有浏览器都会 忽略此参数(我们在自己实现的时候可以随便填写),url为页面地址,就是如果history.pushState({name:'home'},'home page' ,'home')则地址栏就成了/home,更神奇的是此时不会向后端发送请求,仅仅是url改变。

    history.replaceState(data, title [, url]) :

    更改当前的历史记录,参数跟history.pushState(data, title [, url])一致,只不过不会像浏览器历史栈添加数据,而是替代之前的历史记录; 

    history.state:用于存储以上方法的data数据,

    window.onpopstate:响应pushState或replaceState的调用;

    2.介绍实现单页面原理

    通过以上几个方法我们完全可以改变url并且监听到url的变化,比如url由localhost:8000改变成localhost:8000/home,此时我们通过onpopstate监听到了这个变化,并且拿到data数据,假设拿到了name,此时假设有以下对应路由表,其实可以随便定义,

    let route = {
        home:{
            name:'home',
            url:'./home.html',
            des:'home page'
        },
         class:{
             name:'class',
             url:'./class.html',
             des:'class page'
          }
    }
    

      那我们就知道此时home对应应该是./home.html,于是我们利用ajax将./home.html加载过来,此时我们拿到了home.html的所有信息,于是跟vue或者其他框架一样挂载到当前页面的一个元素上。

    注意点:

    我们主动 利用history.pushState({name:'home'},'home page' ,'home')时候并不会触发onpopstate,就是说此时是无法知道url变动了,为了让页面顺利跳转又触发我们提供的ajax,那么我们就要修改一下history.pushState

    var pushState = history.pushState;   // 存储原生 replaceState
    history.pushState = function(state, param) {     // 改写 replaceState
            var urlName = arguments[2];
            var url = route[urlName].url;
            ajax(url)
            return pushState.apply(history, arguments);    // 调用原生的 replaceState
     };
    

      如上,我们不仅在使用 history.pushState时候,触发我们自己定义的ajax函数,加载了页面,又调用了原生的方法,是不会影响原生历史记录和跳转等问题。

    现在我们知道我们每次调用history.pushState都会触发ajax函数

    <div id="app"></div>
    
        <script>
            function ajax(url){
                //步骤一:创建异步对象
                var ajax = new XMLHttpRequest();
                //步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端
                ajax.open('get',url);
                //步骤三:发送请求
                ajax.send();
                //步骤四:注册事件 onreadystatechange 状态改变就会调用
                ajax.onreadystatechange = function () {
                    if (ajax.readyState==4 &&ajax.status==200) {
                        //步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
                     //输入相应的内容
                        document.querySelector('#app').innerHTML = ajax.responseText
                  }
                }
            }
        <script>
    

      利用这个ajax就可以将别的页面的内容加载到本页面的#app这个元素上,实现了单页面跳转。

    3.需要注意的地方和坑:

    1.在尝试该方法前,需要其启动服务器代理html文件,即静态的html文件打开会报错

    2.我们在通过history.pushState改变url浏览器并不会跟处理普通url一样新发送请求,但是我们在刷新的时候浏览器还是会发送请求,即localhost:8000/home刷新浏览器就会请求这个接口,就会导致后台根本没有这个路由返回404,(这也是vue-route经常会出现刷新404问题的原因)解决办法就是遇到404的都代理给index.html,我测试使用express来起服务的,有一个插件叫 connect-history-api-fallback,使用之后就不会出现这个问题

    如果有想要自己尝试的,这里附上我们demo:https://github.com/jiangzhenfei/h5History,下载还只要执行node server.js即可,打开浏览器就可以尝试了。

  • 相关阅读:
    有趣的网抑云
    [扩展阅读] timeit 模块详解(准确测量小段代码的执行时间)
    第044讲:魔法方法:简单定制
    第043讲:魔法方法:算术运算2
    第042讲:魔法方法:算术运算1
    第041讲:魔法方法:构造和析构
    吴恩达深度学习 第一课第四周课后编程作业 assignment4_2
    吴恩达深度学习 第一课第四周课后编程作业 assignment4_1
    第040讲:类和对象:一些相关的BIF
    [扩展阅读] property 的详细使用方法
  • 原文地址:https://www.cnblogs.com/zhenfei-jiang/p/9599105.html
Copyright © 2011-2022 走看看