vue-router 运行机制 及 底层原理

1.测试页面

index.html

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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .router-link-active{color: red;}
    </style>
</head>
<body>
    <!--
        路由:异步加载
    -->
    <!--VueJs核心库-->
    <script src="vue.js"></script>
    <!--Router-->
    <script src="vue-router.js"></script>
 
    <div id="app">
        <h1>Hello App</h1>
        <!--router-link被渲染成a标签,为什么直接用a标签而用router-link?-->
        <router-link to="/index">Go to Index</router-link>
        <router-link to="/subpage">Go to SubPage</router-link>
        <!--渲染位置-->
        <router-view></router-view>
    </div>
 
    <script>
        //VueJS的router-link,在没有使用之前,不会对任何Tag(标签)起到任何作用
        //const和var一样都是声明变量的,ES6语法,const(声明常量)
        //两套模板
        const Foo = {template:'<div>Index</div>'}
        const Bar = {template:'<div>SubPage</div>'}
 
        const routes = [ // 配置
            //{路由名称:名字和路径,模板:模板的变量}
            {path:'/index',component:Foo},
            {path:'/subpage',component:Bar}
        ]
 
        const router = new VueRouter({ // 得到VueRouter的实例
            routes
        });
 
        // new Vue({
        //  el:"#app", // 指定渲染位置
        //  data:{ // 数据
        //      message:'Hello App'
        //  }
        // });
 
        const app = new Vue({ //在一个地方传入的是一个对象,需要一对大括号
            router
        }).$mount('#app'); //指定位置
    </script>
</body>
</html>

index2.html

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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .router-link-active{color: red;}
    </style>
</head>
<body>
    <div id="app">
        <div>
            <router-link to="/user/foo">/user/foo</router-link>
        </div>
        <div>
            <router-link to="/user/bar">/user/bar</router-link>
        </div>
        <div>
            <router-view></router-view>
        </div>
    </div>
 
    <!--VueJs核心库-->
    <script src="vue.js"></script>
    <!--Router-->
    <script src="vue-router.js"></script>
     
    <!--配置动态路由-->
    <script>
        const User = {
            template:`<div>User:{{$route.params.id}}</div>`
        }
 
        const router = new VueRouter({
            routes:[
                {path:'/user/:id',component:User}
            ]
        });
 
        const app = new Vue({router}).$mount('#app');
    </script>
</body>
</html>

2.函数封装

index3.html

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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .router-link-active{color: red;}
    </style>
</head>
<body>
    <a href="#/index?index=1">异步加载首页</a>
    <a href="#/list?list=1">异步加载列表</a>
    <a href="#/detail?detail=1">异步加载详情</a>
    <a href="#/detail2?detail2=1">异步加载详情2</a>
 
    <div id="content">
        默认
    </div>
     
    <script src="myroute.js"></script>
    <script>
        // window.addEventListener('hashchange',function() { // 监听URL的改变
        //  console.log("Hello");
        // });
 
        spaRouters.init();
 
        /*
        1.开发都是异步的
        */
 
        spaRouters.map("/index",function(transition){
            spaRouters.asyncFun("index.js",transition)
        })
 
        spaRouters.map("/list",function(transition){
            spaRouters.asyncFun("list.js",transition)
        })
    </script>
</body>
</html>

index.js

1
2
3
SPA_RESOLVE_INIT = function (transition) {
    document.getElementById("content").innerHTML = "当前是渲染的页面";
}

list.js

1
2
3
SPA_RESOLVE_INIT = function (transition) {
    document.getElementById("content").innerHTML = "当前是渲染的页面";
}

myroute.js

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
95
96
97
98
99
100
101
(function() { // 匿名函数,让代码处于局部
    // 通过监听,改变页面的显示
    function spaRouters() {
        this.routers = {}; // 保存注册所有路由,也可以理解为缓存
    }
 
    var util = { // 声明公共类
        getParamsUrl:function(){ // 获取路由的路径和参数
            var hasDetail = location.hash.split("?");
            var hasName = hasDetail[0].split("#")[1]; // 得到路由地址
            var params = hasDetail[1]?hasDetail[1].split("&"):[]; // 得到参数
            var query = {};
 
            for (var i = 0; i < params.length; i++) {
                var item = params[i].split("=");
                query[item[0]] = item[1];
            }
 
            return {
                path:hasName,
                query:query
            }; // 返回一个路由名称
        }
    }
 
    // 一块业务
    spaRouters.prototype = {
        init:function(){
            var self = this;
            window.addEventListener('hashchange',function() { // 监听URL的改变
                // 只是知道发生了改变,并不知道路径,需要路由处理
                self.urlChange();
            });
 
            window.addEventListener('load',function() { // 监听URL的改变
                // 只是知道发生了改变,并不知道路径,需要路由处理
                self.urlChange();
            });
        },
        refresh:function(currentHash){ // 加载
            var self = this;
            if (self.beforeFun) {
                self.beforeFun({
                    to:{
                        path:currentHash.path,
                        query:currentHash.query
                    },
                    next:function(){
                        self.routers[currentHash.path].callback.call(self,currentHash);
                    }
                })
            }else{
                self.routers[currentHash.path].callback.call(self,currentHash);
            }
        },
        // URL 路由处理
        urlChange:function(){
            var currentHash = util.getParamsUrl();
            if(this.routers[currentHash.path]){
                this.refresh(currentHash);
            }
        },
        // 仅仅作为注册路由
        map:function(path,callback){
            // 清除空格
            path = path.replace(/\s*/g,""); // 过滤空格
            if(callback && Object.prototype.toString.call(callback) === "[object Function]"){
                this.routers[path] = {
                    callback:callback,
                    fn:null // 缓存异步文件状态
                }
            }else{
                console.trace("注册"+path+"需要注册回调信息");
            }
        },
        asyncFun:function(file,transition){
            var self = this;
            if(self.routers[transition.path].fn){
                self.afterFun && self.afterFun(transition)
                self.routers[transition.path].fn(transition)
            }else{
                console.log("开始异步下载js文件"+file);
                var _body = document.getElementsByTagName("body")[0];
                var scriptEle = document.createElement("script");
                scriptEle.type = 'text/javascript';
                scriptEle.src = file;
                scriptEle.async = true;
                SPA_RESOLVE_INIT = null;
                scriptEle.onload = function(){ // 加载文件之后
                    console.log("下载"+file+"完成");
                    self.afterFun && self.afterFun(transition)
                    self.routers[transition.path].fn = SPA_RESOLVE_INIT;
                    self.routers[transition.path].fn(transition)
                }
                _body.appendChild(scriptEle);
            }
        }
    }
 
    window.spaRouters = new spaRouters(); // 注册到全局
})();

.

posted @   每天都要进步一点点  阅读(1209)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示