专栏首页lhyt前端之路前端路由0.前言1.哈希路由2.history路由

前端路由0.前言1.哈希路由2.history路由

0.前言

后端有后端路由,根据路由返回特定的网页,代表者是传统的mvc模式,模板引擎+node。前端也有前端的路由,我们用三大框架做spa的时候,总是和路由离不开关系。主要有两种方法:基于哈希路由、基于history

1.哈希路由

#后面的内容是网页位置标识符,一般是锚点<a name='xx'>或id属性<div id='xx'>。通过location.hash可以取到该值,常见的返回顶部也可以利用href=‘#’。改变#后面的内容不会引起页面重新刷新,但是会有历史记录,所以可以后退。这对于ajax应用程序特别有用,可以用不同的#值,表示不同的访问状态,然后向用户给出可以访问某个状态的链接。但是IE 6和IE 7不会有历史记录。#后面的内容不会提交到服务器。

对于a标签,平时有一个常规的操作: 想要在某个点击按钮变成a标签的那个cursor:pointer(手指),一般就用a标签包住文字, <a href="#">按钮</a>但是这样子是会有历史记录,所以我们应该改成 <a href="javascript:void 0">按钮</a>

我们在用vue路由的时候,其实可以发现,router-link到最后就是一个a标签。而我们也知道a标签有一个href属性,如果是哈希路由就不会引发页面的刷新。所以平时也有一种常规操作,返回顶部,就是a标签的href=“#”,就是直接跳转到页面顶部。如果我们给dom一个id,#<id>就跳转到那个dom的位置。

对于前端路由,我们有一个事件可以利用的,onhashchange,监听哈希的变化然后执行相应的回调函数。于是我们可以写下路由类的代码: html:

        <a href="#1">1</a>
        <a href="#2">2</a>
        <a href="#3">3</a>
	<button onclick="r.back()">后退</button>
	<button onclick="r.forward()">前进</button>
复制代码

js:

const addEvent = (function () {//事件
    if (window.addEventListener) {
        return function (ele, event, handle, isBunble) {
            isBunble = isBunble || false
            ele.addEventListener(event, handle, isBunble)
        }
    } else if (window.attachEvent) {
        return function (ele, event, handle) {
            ele.attachEvent('on' + event, handle)
        }
    } else {
        return function (ele, event, handle) {
            ele['on' + event] = handle
        }
    }
})()

class Router {
    constructor () {
        this.routes = {}
        this.currentUrl = '/'
        this.pre = this.pre || null
        this.next = this.next || null
        addEvent(window, 'load', () => {
            this.updateUrl()
        })
        addEvent(window, 'hashchange', () => {
            this.pre = this.currentUrl
            this.updateUrl()
        })  
    }

    route (path, cb) {
        this.routes[path] = cb || function () {}
    }

    updateUrl () {//路由更新的回调
        this.currentUrl = window.location.hash.slice(1) || '/'
        console.log(this.currentUrl)
    }

    back () {//后退
        if( !this.currentUrl ) return;
        this.next = this.currentUrl
        window.location.hash = '#' + this.pre
    }

    forward () {//前进
        if( !this.next ) return ;
        window.location.hash = '#' + this.next
    }
}
const r = new Router()
复制代码

我们尝试点击一下a标签,发现url上面的#后面 内容改变,而且控制台打印了相应的数字

在VUE中使用路由

html:

<div id="app">
        <a href="#1">1</a>
        <a href="#2">2</a>
        <a href="#3">3</a>
        <component :is="page"></component>
</div>
    <template id="page1">
        <div>
            <h1>这是第一页</h1>
        </div>
    </template>
    <template id="page2">
        <div>
            <h1>这是第二页</h1>
            <p>通过监听路由改变来改变视图</p>
        </div>
    </template>
    <template id="page3">
        <div>
            <h1>这是第三页</h1>
            <p>动态改变组件,模拟类似于前端路由的效果</p>
        </div>
    </template>
复制代码

js:

        const vm = new Vue({
            el: "#app",
            data () {
                return {
                    page: "page1"
                }
            },
            components:{
                "page1":{
                    template:'#page1'
                },
                "page2":{
                    template:'#page2'
                },     
                "page3":{
                    template:'#page3'
                }                             
            }
        });


const addEvent = (function () {
    if (window.addEventListener) {
        return function (ele, event, handle, isBunble) {
            isBunble = isBunble || false
            ele.addEventListener(event, handle, isBunble)
        }
    } else if (window.attachEvent) {
        return function (ele, event, handle) {
            ele.attachEvent('on' + event, handle)
        }
    } else {
        return function (ele, event, handle) {
            ele['on' + event] = handle
        }
    }
})()

class Router {
    constructor () {
        this.routes = {}
        this.currentUrl = '/'
        this.pre = this.pre || null
        this.next = this.next || null
        addEvent(window, 'hashchange', () => {
            this.pre = this.currentUrl
            this.updateUrl()
        })  
    }

    route (path, cb) {
        this.routes[path] = cb || function () {}
    }

    updateUrl () {
        this.currentUrl = window.location.hash.slice(1) || '/'
        console.log(this.currentUrl)
        vm.$data.page = "page" + this.currentUrl
    }

    back () {
        if( !this.currentUrl ) return;
        this.next = this.currentUrl
        window.location.hash = '#' + this.pre
    }

    forward () {
        if( !this.next ) return ;
        window.location.hash = '#' + this.next
    }
}

const r = new Router()
复制代码

2.history路由

如果不了解的,点击这里了解history路由

html:

    <div id="app">
        <component :is="page"></component>
        <button @click="to1">page1</button>
        <button @click="to2">page2</button>
        <button @click="to3">page3</button>
    </div>

    <template id="page1">
        <div>
            <h1>这是第一页</h1>
        </div>
    </template>
    <template id="page2">
        <div>
            <h1>这是第二页</h1>
            <p>通过监听路由改变来改变视图</p>
        </div>
    </template>
    <template id="page3">
        <div>
            <h1>这是第三页</h1>
            <p>动态改变组件,模拟类似于前端路由的效果</p>
        </div>
    </template>
复制代码

js:

        const vm = new Vue({
            el: "#app",
            data () {
                return {
                    page: "page1"
                }
            },
            components:{
                "page1":{
                    template:'#page1'
                },
                "page2":{
                    template:'#page2'
                },     
                "page3":{
                    template:'#page3'
                }                             
            },
            methods: {
                to1(){
                    r.go('1')
                },
                to2(){
                    r.go('2')
                },
                to3(){
                    r.go('3')
                }                                
            }
        });


const addEvent = (function () {
    if (window.addEventListener) {
        return function (ele, event, handle, isBunble) {
            isBunble = isBunble || false
            ele.addEventListener(event, handle, isBunble)
        }
    } else if (window.attachEvent) {
        return function (ele, event, handle) {
            ele.attachEvent('on' + event, handle)
        }
    } else {
        return function (ele, event, handle) {
            ele['on' + event] = handle
        }
    }
})()

class Router  {
    constructor (from, history) {
        this.from = from//保存起点
        this.history = history
        this.list = {} //缓存k-v对
    }

    go (pagename) {
        if(!this.list[pagename]){
            this.list[pagename] = ++this.from
            window.history.pushState({page:pagename},pagename,pagename)
        }else{
            window.history.go(this.list[pagename])
        }
        vm.$data.page = "page" + pagename
    }
}

const r = new Router(window.history.length, window.history)
复制代码

引用vue官网一句话:如果你嫌哈希路由难看可以用history路由。不过history路由有一个问题,我们知道pushState和replaceState只是对url栏进行改变,不会触发页面刷新,只是导致history对象发生变化,另外也不能跨域。所以这个例子你不能直接双击打开了,因为file没有域名好讲,你只能通过后台打开这个页面。既然不会触发页面更新,那么也不会发送http请求,就有了一个问题:如果直接输入url,后端又没有对应的url处理的话,那肯定是404,而哈希路由则可以直接输入 url直接定位到某个视图。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从MDN上的canvas例子受到的启发0.前言1.面向对象编程的实践2.相互纠缠的现象3.解决方案4.模拟核裂变5.大鱼吃小鱼

    在面对碰撞检测后还有后续动作的情况,必须考虑一下相互纠缠的问题: 如果两个小球被检测到碰撞的时候,而且加上他们的速度下一步还是处于碰撞范围内,就像引力一样无法脱...

    lhyt
  • 从一次react异步setState引发的思考0. 前言1. 不想一个个改了2. 不想直接改3. 添加业务生命周期4. 更简单一些吧5. 让我们更疯狂一点

    一个异步请求,当请求返回的时候,拿到数据马上setState并把loading组件换掉,很常规的操作。但是,当那个需要setState的组件被卸载的时候(切换路...

    lhyt
  • 当AOP和react愉快玩耍的时候,我的代码量更少了

    AOP(面向切面编程)针对业务中的一些关键点/关键时刻所做的事情(即切面)进行抽离,抽离的是代码执行的过程中的某个关键步骤。简单来说,AOP关注的是什么时间点下...

    lhyt
  • 数据可视化之风向图

    Peter Lu
  • 简易路由实现——(hash路由)

    前阵子逛 github 的时候,看见一篇文章 《原生JS实现hash路由》, 想着照着 vue-router 的 api,参考这篇文章实现一个可直接用于 htm...

    小皮咖
  • React-实现上拉加载更多

    yuezhongbao
  • 深入浅出JavaScript之this

    JavaScript中的this比较灵活,根据在不同环境下,或者同一个函数在不同方式调用下,this都有可能是不同的。但是有一个总的原则,那就是this指的是,...

    哲洛不闹
  • 俄罗斯方块之心(cocos2d-js+html5)

    就截取了两张图,有兴趣的朋友可以去微博上查阅视频版。 微博地址: http://video.weibo.com/show?fid=1034:42671171...

    李小白是一只喵
  • Flutter开发:关于隐藏Appbar相关属性的知识点

    this.automaticallyImplyLeading = true,

    三掌柜
  • (二十三)c#Winform自定义控件-等待窗体

    GitHub:https://github.com/kwwwvagaa/NetWinformControl

    冰封一夏

扫码关注云+社区

领取腾讯云代金券