实现前端路由

在单页应用上,前端路由并不陌生。单页应用是指在浏览器中运行的应用,在使用期间页面不会重新加载。 
      基本原理:以 hash 形式(也可以使用 History API 来处理)为例,当 url 的 hash 发生改变时,触发 hashchange 注册的回调,回调中去进行不同的操作,进行不同的内容的展示。 
      基于hash的前端路由优点是:能兼容低版本的浏览器。 
history 是 HTML5 才有的新 API,可以用来操作浏览器的 session history (会话历史)。 
      从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。

SPA的核心即是前端路由。何为路由呢?说的通俗点就是网址,比如https://www.talkingcoder.com/article/6333760306895988699;专业点就是每次GET或者POST等请求,在服务端有一个专门的正则配置列表,然后匹配到具体的一条路径后,分发到不同的Controller,然后进行各种操作后,最终将html或数据返回给前端,这就完成了一次IO。当然,目前绝大多数的网站都是这种后端路由,也就是多页面的,这样的好处有很多,比如页面可以在服务端渲染好直接返回给浏览器,不用等待前端加载任何js和css就可以直接显示网页内容,再比如对SEO的友好等。那SPA的缺点也是很明显的,就是模板是由后端来维护或改写。前端开发者需要安装整套的后端服务,必要还得学习像PHP或Java这些非前端语言来改写html结构,所以html和数据、逻辑混为一谈,维护起来即臃肿也麻烦。然后就有了前后端分离的开发模式,后端只提供API来返回数据,前端通过Ajax获取到数据后,再用一定的方式渲染到页面里,这么做的优点就是前后端做的事情分的很清楚,后端专注在数据上,前端专注在交互和可视化上,从此前后搭配,干活不累,如果今后再开发移动App,那就正好能使用一套API了,当然缺点也很明显,就是首屏渲染需要时间来加载css和js。这种开发模式被很多公司认同,也出现了很多前端技术栈,比如以jQuery+artTemplate+Seajs(requirejs)+gulp为主的开发模式所谓是万金油了。在Node.js出现后,这种现象有了改善,就是所谓的大前端,得益于Node.js和JavaScript的语言特性,html模板可以完全由前端来控制,同步或异步渲染完全由前端自由决定,并且由前端维护一套模板,这就是为什么在服务端使用artTemplate、React以及即将推出的Vue2.0原因了。那说了这么多,到底怎样算是SPA呢,其实就是在前后端分离的基础上,加一层前端路由。

前端路由,即由前端来维护一个路由规则。实现有两种,一种是利用url的hash,就是常说的锚点(#),JS通过hashChange事件来监听url的改变,IE7及以下需要用轮询;另一种就是HTML5的History模式,它使url看起来像普通网站那样,以"/"分割,没有#,但页面并没有跳转,不过使用这种模式需要服务端支持,服务端在接收到所有的请求后,都指向同一个html文件,不然会出现404。所以,SPA只有一个html,整个网站所有的内容都在这一个html里,通过js来处理。

前端路由的优点有很多,比如页面持久性,像大部分音乐网站,你都可以在播放歌曲的同时,跳转到别的页面而音乐没有中断,再比如前后端彻底分离。前端路由的框架,通用的有Director,更多还是结合具体框架来用,比如Angular的ngRouter,React的ReactRouter,以及我们后面用到的Vue的vue-router。这也带来了新的开发模式:MVC和MVVM。如今前端也可以MVC了,这也是为什么那么多搞Java的钟爱于Angular。

开发一个前端路由,主要考虑到页面的可插拔、页面的生命周期、内存管理等。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

(function() {

    window.Router = function() {

        var self = this;

        self.hashList = {}; /* 路由表 */

        self.index = null;

        self.key = ‘!‘;

        window.onhashchange = function() {

            self.reload();

        };

    };

    /**

     * 添加路由,如果路由已经存在则会覆盖

     * @param addr: 地址

     * @param callback: 回调函数,调用回调函数的时候同时也会传入相应参数

     */

    Router.prototype.add = function(addr, callback) {

        var self = this;

        self.hashList[addr] = callback;

    };

    /**

     * 删除路由

     * @param addr: 地址

     */

    Router.prototype.remove = function(addr) {

        var self = this;

        delete self.hashList[addr];

    };

    /**

     * 设置主页地址

     * @param index: 主页地址

     */

    Router.prototype.setIndex = function(index) {

        var self = this;

        self.index = index;

    };

    /**

     * 跳转到指定地址

     * @param addr: 地址值

     */

    Router.prototype.go = function(addr) {

        var self = this;

        window.location.hash = ‘#‘ + self.key + addr;

    };

    /**

     * 重载页面

     */

    Router.prototype.reload = function() {

        var self = this;

        var hash = window.location.hash.replace(‘#‘ + self.key, ‘‘);

        var addr = hash.split(‘/‘)[0];

        var cb = getCb(addr, self.hashList);

        if(cb != false) {

            var arr = hash.split(‘/‘);

            arr.shift();

            cb.apply(self, arr);

        } else {

            self.index && self.go(self.index);

        }

    };

    /**

     * 开始路由,实际上只是为了当直接访问路由路由地址的时候能够及时调用回调

     */

    Router.prototype.start = function() {

        var self = this;

        self.reload();

    }

    /**

     * 获取callback

     * @return false or callback

     */

    function getCb(addr, hashList) {

        for(var key in hashList) {

            if(key == addr) {

                return hashList[key]

            }

        }

        return false;

    }

})();

  每次hash的变化我们还可以通过onhashchange事件【核心+精髓】来监听,然后做出相应的处理。。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

<!DOCTYPE html>

<html>

    <head>

        <meta charset="utf8" />

        <script type="text/javascript" src="./router.js"></script>

        <style type="text/css">

        </style>

    </head>

    <body>

        <a href="#!index">go to index</a><br />

        <a href="#!search/SB/shi/ni">go to search</a>

    </body>

    <script type="text/javascript">

        window.onload = function() {

            var router = new Router();

            router.add(‘index‘, function() {

                alert(‘current page: index‘);

            });

            router.add(‘search‘, function(wd, sortType, sortBy) {

                alert(‘current page: search‘ + ‘\nwd: ‘ + wd + ‘\nsortType: ‘ + sortType + ‘\nsortBy: ‘ + sortBy);

            });

            router.setIndex(‘index‘);

            router.start();

        };

    </script>

</html>

原文地址:https://www.cnblogs.com/ckAng/p/10234596.html

时间: 2024-11-03 02:33:40

实现前端路由的相关文章

利用JS实现前端路由

在以前的web程序中,路由字眼只出现在后台中.但是随着SPA单页面程序的发展,便出现了前端路由一说.单页面顾名思义就是一个网站只有一个html页面,但是点击不同的导航显示不同的内容,对应的url也会发生变化,这就是前端路由做的事.也就是通过JS实时检测url的变化,从而改变显示的内容. 目前很多前端框架都有接口去实现路由,比如vuejs的vue-route等.我们可以利用原生的hashchange事件来模拟一个简单的路由. 实例的html代码: Document index news about

Web开发中 前端路由 实现的几种方式和适用场景

浅析Web开发中前端路由实现的几种方式 主题 Web开发 故事从名叫Oliver的绿箭虾`说起,这位大虾酷爱社交网站,一天他打开了 Twitter ,从发过的tweets的选项卡一路切到followers选项卡,Oliver发现页面的内容变化了,URL也变化了,但为什么页面没有闪烁刷新呢?于是Oliver打开的网络监控器(没错,Oliver是个程序员),他惊讶地发现在切换选项卡时,只有几个XHR请求发生,但页面的URL却在对应着变化,这让Oliver不得不去思考这一机制的原因- 叙事体故事讲完,

自己动手写一个前端路由插件

在单页应用上,前端路由并不陌生.单页应用是指在浏览器中运行的应用,在使用期间页面不会重新加载.       基本原理:以 hash 形式(也可以使用 History API 来处理)为例,当 url 的 hash 发生改变时,触发 hashchange 注册的回调,回调中去进行不同的操作,进行不同的内容的展示.       基于hash的前端路由优点是:能兼容低版本的浏览器. history 是 HTML5 才有的新 API,可以用来操作浏览器的 session history (会话历史). 

前端路由和后端路由

前端路由的典型:ng-route,后端路由典型:express (结合模板,返回的是html文件,感觉模板略像jsp,没有分离) 前端路由根据不同的url展示页面,服务端根据 url 的不同返回不同的页面实现的.在单页面应用,大部分页面结构不变,只改变部分内容的使用 优点 用户体验好,不需要每次都从服务器全部获取,快速展现给用户 缺点 使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存 单页面无法记住之前滚动的位置,无法在前进,后退的时候记住滚动的位置 由于单页Web应用在一个页面

原生JS实现一个简单的前端路由(原理)

说一下前端路由实现的简要原理,以 hash 形式(也可以使用 History API 来处理)为例, 当 url 的 hash 发生变化时,触发 hashchange 注册的回调,回调中去进行不同的操作,进行不同的内容的展示. 直接看代码或许更直观. 1 function Router() { 2 this.routes = {}; 3 this.currentUrl = ''; 4 } 5 Router.prototype.route = function(path, callback) {

浅析Web开发中前端路由实现的几种方式

故事从名叫Oliver的绿箭虾`说起,这位大虾酷爱社交网站,一天他打开了 Twitter ,从发过的tweets的选项卡一路切到followers选项卡,Oliver发现页面的内容变化了,URL也变化了,但为什么页面没有闪烁刷新呢?于是Oliver打开的网络监控器(没错,Oliver是个程序员),他惊讶地发现在切换选项卡时,只有几个XHR请求发生,但页面的URL却在对应着变化,这让Oliver不得不去思考这一机制的原因… 叙事体故事讲完,进入正题.首先,我们知道传统而经典的Web开发中,服务器端

前端路由的原理

什么是路由?简单的说,路由是根据不同的 url 地址展示不同的内容或页面 使用场景?前端路由更多用在单页应用上, 也就是SPA, 因为单页应用, 基本上都是前后端分离的, 后端自然也就不会给前端提供路由. 前端的路由和后端的路由在实现技术上不一样,但是原理都是一样的.在 HTML5 的 history API 出现之前,前端的路由都是通过 hash 来实现的,hash 能兼容低版本的浏览器. 两种实现前端路由的方式HTML5 History两个新增的API:history.pushState 和

通过hash实现前端路由

router.js //构造函数 function Router() { this.routes = {}; this.currentUrl = ''; } Router.prototype.route = function(path, callback) { this.routes[path] = callback || function(){};//给不同的hash设置不同的回调函数 }; Router.prototype.refresh = function() { //console.l

原生 js前端路由系统实现1

在看了百度手机小说网站源码之后  突然兴起想自己实现一个基于网页hash技术的路由系统 源码 我放到oscgit上面了 地址: https://git.oschina.net/diqye/route.js 适用场景: 局部刷新页面    通过ajax局部刷新页面会有一个问题就是 分享url或者刷新页面时不能记录 当前网页的状态  前端路由可解决这个问题 期望的路由: 1  当访问网页 http://localhost/index.html 或者 http://localhost/index.ht

前端路由 or 后端路由

关于这个问题,无论是平时工作中,还是业余学习中,都有过思考.到底什么样的项目适合前端路由,什么样的项目适合后端路由?可能我目前的想法还很稚嫩不成熟,欢迎吐槽. 首先需要明确的是,无论前端还是后端路由,我们看到的 URL 都是马甲,需要通过路由触发/执行真实需要执行的逻辑路径. 先说前端路由,很重要的一点是 页面不刷新,和后端采用 ajax 交互,实际生产中多用在 单页应用 中.举个例子,webapp 一类就比较适合用前端路由,页面不刷新使得交互友好(毕竟移动端请求还是挺耗时的),另外,单页应用通