Javascript 实现一个原生的路由系统

本文介绍了一个简单的自制路由系统,包括核心代码实现与HTML页面演示。利用JavaScript动态改变页面内容,实现不同URL路径对应的页面展示。

实现一个原生的路由系统

  • 先看核心代码
function Router(){
    this.routes={};
    this.currentUrl='';
}
Router.prototype.route=function(path,callback){
    this.routes[path]=callback||function(){}; //保证回调的时候不报错
}
Router.prototype.refresh=function(){
    this.currentUrl=location.hash.slice(1)||'/'; //location.hash 指的是url 最后#后面的数据
    this.routes[this.currentUrl]();//调用 callback函数
}
Router.prototype.init=function(){
    window.addEventListener('load',this.refresh.bind(this),false);
    window.addEventListener('hashchange',this.refresh.bind(this),false);
}
window.Router=new Router();
window.Router.init();
  • 具体的效果html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试javascript路由</title>
    <script type="text/javascript">
        function Router(){
            this.routes={};
            this.currentUrl='';
        }
        Router.prototype.route=function(path,callback){
            this.routes[path]=callback||function(){}; //保证回调的时候不报错
        }
        Router.prototype.refresh=function(){
            this.currentUrl=location.hash.slice(1)||'/'; //location.hash 指的是url 最后#后面的数据
            this.routes[this.currentUrl]();//调用 callback函数
        }
        Router.prototype.init=function(){
            window.addEventListener('load',this.refresh.bind(this),false);
            window.addEventListener('hashchange',this.refresh.bind(this),false);
        }
        window.Router=new Router();
        window.Router.init();
    </script>
</head>
<body>
    <div>路由系统Router对象实现,主要提供三个方法</div>
    <ul>
        <li>init 监听浏览器url hash更新事件</li>
        <li>route 存储路由更新时的回调到回调数组routes中,回调函数将负责对页面的更新</li>
        <li>refrsh 执行当前url对应的回调函数,更新页面</li>
    </ul>
    <div>Demo实例,Router调用方式以及呈现效果如下:点击触发url的hash改变,并对应地更新内容,这里为更新body背景颜色</div>

    <ul>
        <li>
            <a href="#/">变为白色</a>
        </li>
        <li>
            <a href="#/blue">变为蓝色</a>       
        </li>
        <li>
            <a href="#/green">变为绿色</a>      
        </li>
    </ul>
    <script type="text/javascript">
        var content = document.querySelector('body');
        function changeBgColor(color){
            content.style.backgroundColor=color;
        }
        Router.route('/',function(){
            changeBgColor('white');
        });
        Router.route('/blue',function(){
            changeBgColor('blue');
        });
        Router.route('/green',function(){
            changeBgColor('green');
        });
    </script>
</body>
</html>

核心函数的设计的知识点

  • this的奥秘

官方的解释:this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是哪个调用它的对象。

例子1

function printProduct(){
    var product="橘子";
    console.log(this.product);//undefined
    console.log(this);//window
}
printProduct();
window.printProduct();

例子2

//这里的this指向的是对象funProduct,因为getProduct函数是通过调用funProduct.getProduct()执行的
var funProduct={
    product:"橘子",
    getProduct:function(){
        console.log(this.product);//橘子
    }
}
funProduct.getProduct();

例子3

//这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象
var wrapper={
    product:"苹果",,
    funProduct:{
            product:"橘子",
            getProduct:function(){
                console.log(this.product);//橘子
            }
    }
}
wrapper.funProduct.getProduct();

例子4

//this永远指向的是最后调用它的对象,也就是看它执行的时候是谁在调用
var wrapper={
    product:"苹果",,
    funProduct:{
            product:"橘子",
            getProduct:function(){
                console.log(this.product);//undefined
                console.log(this);//window
            }
    }
}
var triggerFun = wrapper.funProduct.getProduct;
triggerFun();
  • bind的奥秘

首先call apply bind 都能够改变函数执行的上下文对象,也就是调整改变了this的指向。

bind 方法,顾名思义,就是绑定的意思,到底是怎么绑定然后怎么用,看下面的例子。

//语法
fun.bind(this,arg1,arg2,......)
bind()方法会创建一个新的函数,称为绑定函数,fun方法在this环境下调用
该方法可传入两个参数,第一个参数作为this,第二个及以后的参数则作为函数的参数调用

创建绑定函数

this.total=1;
var mathModule={
    total:2,
    getTotal:function(){
        return this.total;
    }
};
mathModule.getTotal();//2

var getTotal_temp = mathModule.getTotal;
// getTotal在外部调用,此时的this指向了全局对象
getTotal_temp();//1

//再把getTotal_temp方法绑定到mathModule环境上
var getTotal_temp2=getTotal.bind(mathModule);
getTotal_temp2();

从上面的例子可以看出,为什么要创建绑定函数,就是当我们调用某些函数的时候是要在特定环境下才能调用到,所以我们就要把函数放在特定环境下,就是使用bind把函数绑定到特定的所需的环境下。

让函数拥有预设的参数

使用bind()方法使函数拥有预设的初始参数,这些参数会排在最前面,传给绑定函数的参数会跟在它们后面。

function list(){
    //让类数组arguments拥有数组的方法slice,这个函数实现了简单把类数组转换成数组
    return Array.prototype.slice.call(arguments);
}

list(1,2,3);//[1,2,3]

//给list绑定一个预设参数4
var listDefault=list.bind(undefined,4);
listDefault(); //[4]
listDefault(1,2,3);//[4,1,2,3]

setTimeout的使用

正常情况下,调用setTimeout的时候this 会指向全局对象,但是使用类的方法时我们需要指向类的实例,所以要把this,绑定要回调函数方便继续使用实例

function fun_temp1(){
    this.name=1;
}
fun_temp1.prototype.fun2=function(){
    window.setTimeout(this.fun3.bind(this),1000);
}
fun_temp1.prototype.fun3=function(){
    console.log('name:'=this.name);//name:1
}
var fun=new fun_temp1();
fun.fun2();

快捷方法-把类数组转换成数组

第一种方法是使用apply方法

function fun(){
    var slice = Array.prototype.slice;
    return slice.apply(arguments);
}

fun(1,2,3);// [1,2,3]

第二种方法是使用call方法和bind方法一起使用

function fun(){
    var unboundSlice = Array.prototype.slice;
    // 把函数的call方法绑定在数组slice方法上,之后再给call方法传递参数
    var slice = Function.prototype.call.bind(unboundSlice);
    return slice(arguments);
}

fun(1,2,3);// [1,2,3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值