Front-end routing

0. Preface

The backend has a backend route, and returns a specific web page according to the route. The representative is the traditional mvc mode, template engine + node. The front-end also has front-end routing. When we use the three major frameworks for spa, it is always inseparable from routing. There are two main methods: hash-based routing and history-based

1. Hash routing

The content behind # is the web page location identifier, usually the anchor <a name='xx'>or id attribute <div id='xx'>. This value can be obtained through location.hash, and the common return to the top can also be used href=‘#’. Changing the content after the # will not cause the page to refresh, but there will be a history, so you can go back. This is especially useful for ajax applications, where you can use different # values ​​to indicate different access states, and then give the user a link to access a certain state. But IE 6 and IE 7 won't have history. The content after # will not be submitted to the server.

For the a tag, there is usually a routine operation: the one cursor:pointer(finger) that wants to click a button to become the a tag, usually wrap the text with the a tag, <a href="#">按钮</a>but this way there will be a history record, so we should change become<a href="javascript:void 0">按钮</a>

When we use vue routing, we can actually find that router-linkit is an a label at the end. And we also know that the a tag has an href attribute. If it is a hash route, it will not cause a page refresh. So there is usually a routine operation, returning to the top is the a tag href=“#”, which is to jump directly to the top of the page. If we give the dom an id, #<id>jump to the location of that dom.

For front-end routing, we have an event that can be used, onhashchange, which listens for hash changes and executes the corresponding callback function. So we can write the code of the routing class: 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()

We tried to click the a tag and found that the content after the # above the url changed, and the console printed the corresponding number

Using Routing in 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 routing

If you don't understand, click here to learn about history routing

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)

Quoting a sentence from the Vue official website: If you think hash routing is ugly, you can use history routing. However, there is a problem with history routing. We know that pushState and replaceState only change the url bar and will not trigger page refresh, but only cause the history object to change, and they cannot cross domains. So in this example, you can't open it directly by double-clicking, because the file has no domain name to talk about, you can only open this page through the background. Since the page update will not be triggered, and the http request will not be sent, there is a problem: if the url is directly entered and the backend does not have the corresponding url processing, it must be 404, and the hash routing can directly enter the url Navigate directly to a view.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325993727&siteId=291194637