美文网首页
扒一扒路由的演变过程

扒一扒路由的演变过程

作者: dkvirus | 来源:发表于2018-01-21 21:58 被阅读0次
路由

1. 从前的请求 —— 服务端渲染(SSR:Server Side Render)

在最开始,在浏览器中向服务端发送一个请求,服务端会把 html 字符串生成好,再发送给客户端,客户端直接渲染即可。

并不是说一个 html 就只请求了一次服务端。一个 html 里可能会引用一些 js、css 文件,这些静态资源都是放在服务端的。当浏览器渲染服务端返回的 html 字符串,读到诸如
<script src="js/jquery.js"></script> 时会再次向服务端发送一条请求去获取 jquery.js 资源的,获取回来之后在浏览器中加载一遍。

缺点:在后管系统中,当从“用户管理”菜单跳转到“角色管理”菜单时,往往变化的只是表格的字段以及数据,但在服务端渲染中每次都需要全部请求一遍。请求头部横条,请求左侧菜单栏,重新加载 jquery.js 等等。我们希望不需要改变的东东就别动了,修改变局部。

2. Ajax 出现实现局部刷新

ajax 的出现解决了上面每次请求页面都全部刷新的问题,只是请求数据,然后通过 Dom 操作修改 html 中表格相关的东东。

缺点:使用 ajax 异步请求之后,点击浏览器的回退上一个页面会发现没效果,因为这次请求仅仅是数据的请求,并没有重新刷新页面,也就没有加入到浏览器历史栈中。

3. 单页应用(SPA:Single Pagination Application)

单页应用的出现解决了服务端渲染和 ajax 存在的问题。

解决服务端渲染的问题:

人们开始想,从“用户管理”菜单跳转到“角色管理”菜单时,需要请求服务端获取 html 之后在浏览器中渲染。这个渲染的过程包括创建一个个 dom 元素,如 div dom 元素,p dom 元素。他们会认为这一过程很消耗性能,事实也是如此,可以试着在浏览器调试台中输入:document.createElement('div') 会发现仅仅创建一个 div 元素附带创建了很多属性和方法,那些东东你可能压根就用不上。

单页应用的解决方式是,在页面第一次加载的时候就把“用户管理”的表格 dom 元素和“角色管理”的表格 dom 元素都加载进来,当再次从“用户管理”切换到“角色管理”时,只需要渲染
“角色管理” 的表格 dom,而不是像服务端渲染那样将整个页面都渲染一遍,渲染的少了,性能上无疑得到了提升。这一点和 ajax 有点相似。

单页应用与 ajax 的区别:
ajax 是先请求数据,然后在浏览器通过 js 创建 dom 进行替换。单页应用在第一次加载应用的时候将 dom 都加载到浏览器中,只不过先用了“用户管理”表格 dom,“角色管理”表格 dom 也加载进来了,放在那暂时不用。这种通过点击不同菜单,自动替换不同的 dom 的方式就叫做路由。

还有一点区别就是单页应用解决了 ajax 的问题:单页应用通过 hashHistory 和 browerHistory 可以将每次的路由都加入到浏览器的历史栈,这样点击回退按钮就可以回到上一个页面。
说起来 ajax 也可以通过 hashHistory 和 browerHistory 将路由添加到历史栈,只不过历史大环境下决定它还是功能专一点。

当然,单页应用也有个大问题,那就是首次加载时间很长,造成页面出现白屏。单页应用第一次加载时就会取请求服务端获取所有 html 和 js,然后接下来的操作都在浏览器端进行了,
浏览器会去渲染这些文件,但由于东东太多了,在浏览器端会出现短暂白屏的现象。
为什么服务端渲染不会有白屏现象:因为服务端只会返回 html字符串,浏览器只要渲染一下即可,渲染的东西少了,自然就快了。

4. 路由的概念

去银行办理业务,银行小姐姐会询问你办理什么业务,然后教你不同的操作。有一张表:

业务 操作
办理银行卡 先做xx,再做xx
办理网上银行业务 先做yy,再做yy

去上厕所,如果你是女生,就进入女厕所,你是男生,就进入男厕所。有一张表:

性别 厕所
男生 男厕所
女生 女厕所

你去你女朋友宿舍楼下找她,你告诉宿管大妈你女朋友是xx专业xx班的学生,宿管大妈告诉你去几楼几零几。有一张表:

姓名 宿舍
张晓丽 503 宿舍
李美丽 301 宿舍

回到浏览器路由,在浏览器中输入“localost:8000/”会显示首页,输入“localost:8000/user”会显示用户页面,输入“localost:8000/role”会显示角色页面。有一张表:

路由 视图
/ 首页
/user 用户页面
/role 角色页面

在浏览器中路由的作用就是根据你的输入的地址,显示不同的视图。那就意味着首先要定义这样一张路由表。

5. 路由/单页应用的实现原理

了解了路由表,好奇宝宝肯定想知道具体如何实现呢?

单页应用路由的实现分为两个步骤:改变浏览器地址栏地址,视图切换

1)HashHistory 的应用

  • 改变浏览器地址栏地址
    window.location.hash = 'bbbb' 浏览器地址会变成 localhost:8080/#bbbb
    window.location 对象专门处理浏览器地址栏各种操作。
    使用 window.location.hash 操作时,已经将路由 '#bbbb' 添加到了浏览器历史栈中,点击回退按钮可以回退到上一个页面。
  • 添加浏览器事件监听函数
    window.addEventListener('hashchange', function () {})
    此时如果 hash 变化了,就会触发该事件,在这个事件里就可以实现替换局部 dom 的实现了。

2)Browser History (h5 history)的出现
使用 HashHistory 产生的路由 localhost:8080/#bbbb 会有个井号 #,很多人认为这很不美观,但一直也无计可施,直到 h5 的出现,带来了新的 API —— window.history 的更新。

  • 改变浏览器的地址栏地址
    var stateObj = { foo: "bar" };
    history.pushState(stateObj, "page 2", "user");
    可以看到路由变成了 localhost:8000/user,没有了那不美观的 #。关于history api 具体用法,参考:http://blog.csdn.net/tianyitianyi1/article/details/user
  • 添加浏览器事件监听函数
    通过 history api 改变浏览器地址栏地址同样会触发一个事件
    window.onpopstate = function () { }

3)手写 js 实现一个简单的路由功能:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Hash</title>
</head>
<body>
        <ul class="cs">
            <li class="li">
                <a href="#/" class="button button-primary">首页</a>
            </li>
            <li class="li">
                <a href="#/nav" class="button button-highlight">菜单</a>
            </li>
            <li class="li">
                <a href="#/subpage" class="button button-royal">子页</a>
            </li>
        </ul>
        <div id="app" style="border:2px solid #f00;height:30px;">
                Hello
        </div>
<script>
function Router(){
    //有个名字,用做一件事情
    this.routes = [];
    this.currentUrl = "";
    this.init();//先让他初始化监听事件,然后才调用路由
}

Router.prototype = {
    constructor:Router,
    router:function(path,callback){
        this.routes[path] = callback || function(){};
    },
    refresh:function(){
        this.currentUrl = location.hash.slice(1) || '/';
        this.routes[this.currentUrl]();//通过路由名字去调用相对应的方法
    },
    init:function(){//监听页面:加载的时候、监听改变的时候
        window.addEventListener("load",this.refresh.bind(this),false);
        window.addEventListener("hashchange",this.refresh.bind(this),false);
    }
}

var appObj = document.getElementById("app");
function changeText(text){
    appObj.innerHTML = text;
}

var router = new Router();

router.router("/",function(){
    changeText("首页");
});
router.router("/nav",function(){
    changeText("菜单");
});
router.router("/subpage",function(){
    changeText("子页");
});
</script>
</body>
</html>

6. 最终

目前由于单页应用操作起来更快速,除了首屏加载尴尬的问题,人们提出的方案是使用服务端渲染首屏,之后其它操作都进行单页应用的操作来规避首屏加载的问题。

最终,当硬件与软件发展到一定程度,网速加速到一定程度,单页应用首屏加载虽然需要请求很多东东,但由于网速的变快一瞬间就加载下来,服务端渲染可能就会慢慢退出历史舞台,这也是一种技术的发展趋势。

相关文章

  • 扒一扒路由的演变过程

    1. 从前的请求 —— 服务端渲染(SSR:Server Side Render) 在最开始,在浏览器中向服务端发...

  • 猫扒扒目录

    第一章:猫扒扒简介 第二章:猫扒扒添加商品 第三章:猫扒扒启动 第四章:猫扒扒接单演示 第五章:猫扒扒自动收取红包...

  • 扒一扒

    今天特别有感触,也不知是为何,就想书写一点点东西波动一下在这喧哗的世界已然沉寂已久的心。 都说扒开人的内心,会有两...

  • 双亲家庭的孩子,心理状态就一定比单亲家庭的孩子好吗?

    咱先来扒一扒婚姻制度演变的历史吧。远古时期,母系氏族,一女多夫。女性挑选多个自己喜欢的男性,和他们发生关系,生...

  • 做朋友一定得依着性情

    人的生活就是扒吃扒喝和在人群里扒着友谊的过程。 做朋友一定得依着性情,而不是别的目的,待朋友就多理解朋友,体谅朋友...

  • 聚众吃小龙虾可以搞这么嗨,砸核桃怎么不可以?

    今天跟朋友以打麻将的阵容出席了沪胖某店的日常运营。 整个聚众扒虾的过程,可以说是很普通了:扒,吃,扒,吃,……但是...

  • 猫扒扒启动

    开始启动猫扒扒 1,启动并登陆微信 2,点击启动服务 3,自动跳转微信成功 猫扒扒介绍:猫扒扒是一款 为微商打造的...

  • 看看就得了呗! 扒,扒你妹啊扒!!!

  • 扒一扒RPC

    前言:本篇文章是继JDK动态代理超详细源码分析之后的,因为RPC是基于动态代理的。想必大家都听过RPC,但是可能并...

  • 扒一扒DOM

    目录1.什么是DOM2.节点的概念3.节点的属性和方法4.Element对象的属性和方法5.Attribute对象...

网友评论

      本文标题:扒一扒路由的演变过程

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