欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue中兩種路由模式的實現(xiàn)詳解

 更新時間:2023年08月13日 10:17:24   作者:閩南,  
這篇文章主要為大家詳細介紹了vue中兩種路由模式的實現(xiàn),文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解一下

平時我們編寫路由時,通常直接下載插件使用,在main.js文件中引入直接通過引入vue-router中的Router通過Vue.use使用以后定義一個routeMap數(shù)組,里邊是我們編寫路由的地方,最后通過實例化一個 Router實例 將routes=我們定義的routeMao路由數(shù)組。

但是我們并不知道它是如何實現(xiàn)的,因此我們可以通過自己編寫插件的形式,實現(xiàn)一個vue-router

常用路由步驟:

//router/index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export const routeMap= [
     {
         path: '/home',
         component: () => import('../components/Home/Home.vue')
     },
     {
         path: '/list',
         component: () => import('../components/List/List.vue')
    },
]
const router = new Router({
    routes: constantRouterMap
})
export default router
//main.js
import router from './router'
new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

我們來實現(xiàn)一下如何實現(xiàn)一個hash模式的路由

由于我們不適用插件形式實現(xiàn),因此我們使用步驟與平常實現(xiàn)有一些差異。

router/index.js是我們的路由文件,里面放置我們的路由

plugin/router.js是我們的自定義插件文件,里面放置我們自定義插件內(nèi)容

components是我們組件目錄,放置我們的路由組件(通常使用view定義路由組件)

main.js是我們的入口文件,需要在該文件引入router并且實例化vue的時候需要將引入的router使用

1、首先我們在App.vue文件中,通過<router-view/>以及<router-link/>定義聲明式導航和路由占位

<div>
    <router-link to="/home">首頁</router-link>
    <router-link to="/list">列表</router-link>
    <hr>
    <router-view></router-view>
</div>

這里我們會發(fā)現(xiàn)使用以后會報錯,因為我們沒有下載插件,因此沒有這兩個組件。

我們需要配置plugin插件

由于沒有這兩個全局組件因此我們需要配置兩個全局組件

install方法是為了將我們的路由掛載在我們的組件實例上,通過mixin全局混入,將我們的實例上掛載$router屬性

然后定義兩個全局組件,router-link由于它渲染出來相當于html中的a標簽,使用render方法,參數(shù)為一個createElement方法接收三個參數(shù)(第一個參數(shù)創(chuàng)建的元素,第二個參數(shù)元素具有的屬性, 第三個參數(shù)元素的內(nèi)容)

router-view由于是一個路由占位符,因此返回的是個組件,渲染組件。

通過routesMap是我們存放的路由,current是我們的當前的path路由,因此可以通過查找路由中key值為我們當前path路徑的,查找到我們的組件。通過return渲染我們的組件

VueRouter.install = function (_Vue) {
    //1、保存Vue
    Vue = _Vue
    //2、將以下代碼延遲到vue實例初始化完畢執(zhí)行
    Vue.mixin({
        beforeCreate() {
            //判斷如果有router屬性就執(zhí)行下方代碼
            if (this.$options.router) {
                Vue.prototype.$router = this.$options.router;
            }
        }
    })
    //創(chuàng)建全局組件router-link和router-view
    //創(chuàng)建router-link組件
    Vue.component('router-link', {
        props: {
            to: {
                type: String | Object,
                required: true
            }
        },
        render(h) {// h 有三個參數(shù),第一個參數(shù)創(chuàng)建的元素,第二個參數(shù)元素具有的屬性, 第三個參數(shù)元素的內(nèi)容
            return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default)
        }
    })
    //創(chuàng)建router-view組件
    Vue.component('router-view', {
        // 組件要重新渲染,必須要讓數(shù)據(jù)發(fā)生改變的時候,重新去執(zhí)行render函數(shù)
        render(h) {
            const router = this.$router
            console.log(router.routesMap, 'routesMap');
            let component = router.routesMap[router.current];//組件
            //獲取到外部傳遞的路由表
            return h(component)
        }
    })
}

2、我們定義一個路由類,該類會獲取到我們的路由信息從而進行路由監(jiān)聽以及組件渲染。

(1)、該類中constructor是我們通過實例化vueRouter傳入的數(shù)據(jù),我們需要通過將數(shù)據(jù)保存在vueRouter實例上,獲取到當前的url path路徑。

(2)、通過監(jiān)聽方法hashchange監(jiān)聽我們hash值的變化,通過方法進行監(jiān)聽,但是一定要注意這里方法的this指向必須是vueRouter實例不可以是window,因此需要通過bind改變this指向

(3)、通過defineReactive來講我們的path路徑變?yōu)轫憫?yīng)式,這樣每次路徑發(fā)生變化可以監(jiān)測到變化。

(4)、定義routesMap為我們的路由對象,遍歷我們傳入的路由數(shù)組,將我們每個path路徑對應(yīng)組件,為一組一組的鍵值對。

這樣可以實現(xiàn)一套hash路由模式的路由跳轉(zhuǎn)。

全部代碼如下:

//plugin/router.js
let Vue;
class VueRouter {
    constructor(options) {
        //保存選項
        this.options = options;
        // console.log(options, '路由數(shù)據(jù)');
        // 定義一個響應(yīng)式的變量current,保存當前的hash值
        let url = location.hash.slice(1,) || '/';
        // defineReactive定義響應(yīng)式的對象
        Vue.util.defineReactive(this, 'current', url)
        // hashchange事件來監(jiān)聽hash值的變化, 注意this指向問題
        addEventListener('hashchange', this.changeHash.bind(this))
        this.routesMap = {};
        //對routes中的對象做一個映射:routesMap = {'/home':component,'/list': component}
        this.options.routes.forEach(route => {
            this.routesMap[route.path] = route.component
        })
    }
    //監(jiān)聽hash值變化的函數(shù)
    changeHash() {
        //通過location.hash來獲取到hash值
        this.current = location.hash.slice(1,)
        console.log(this.routesMap, '555');
        // console.log(this.current);//當前path路徑
    }
}
VueRouter.install = function (_Vue) {
    //1、保存Vue
    Vue = _Vue
    //2、將以下代碼延遲到vue實例初始化完畢執(zhí)行
    Vue.mixin({
        beforeCreate() {
            //判斷如果有router屬性就執(zhí)行下方代碼
            if (this.$options.router) {
                Vue.prototype.$router = this.$options.router;
            }
        }
    })
    //創(chuàng)建全局組件router-link和router-view
    //創(chuàng)建router-link組件
    Vue.component('router-link', {
        props: {
            to: {
                type: String | Object,
                required: true
            }
        },
        render(h) {// h 有三個參數(shù),第一個參數(shù)創(chuàng)建的元素,第二個參數(shù)元素具有的屬性, 第三個參數(shù)元素的內(nèi)容
            return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default)
        }
    })
    //創(chuàng)建router-view組件
    Vue.component('router-view', {
        // 組件要重新渲染,必須要讓數(shù)據(jù)發(fā)生改變的時候,重新去執(zhí)行render函數(shù)
        render(h) {
            const router = this.$router
            console.log(router.routesMap, 'routesMap');
            let component = router.routesMap[router.current];//組件
            console.log(component, 'component');
            //獲取到外部傳遞的路由表
            return h(component)
        }
    })
}
export default VueRouter;

接下來實現(xiàn)歷史路由模式

我們知道歷史路由模式和hash路由模式區(qū)別是域名是否存在#因此我們可以通過在路由文件中定義mode屬性判斷是歷史路由模式還是hash路由模式。

先大白話來說一下大概的實現(xiàn)思路(hash和history實現(xiàn)區(qū)別):

1、我們通過我們定義的mode判斷是hash路由模式還是history路由模式,router-link點擊跳轉(zhuǎn)的時候如果是hash路由模式,我們通過render方法返回我們渲染到瀏覽器域名的數(shù)據(jù),hash模式是帶#的,因此我們定義href屬性需要+#,但是history模式是不帶#的,因此我們不需要加#。其次,因為hash模式自動檢測我們的域名,因此我們實現(xiàn)歷史模式需要手動加一個點擊事件,并且需要阻止a鏈接默認跳轉(zhuǎn)的行為(preventDefault取消默認行為),并且通過pushState方法,實現(xiàn)跳轉(zhuǎn),這是歷史路由模式的方法pushState(obj,title,url),最后設(shè)置我們的路由當前path路徑為我們跳轉(zhuǎn)的路徑。

2、當我們定義好它的router-link全局組件以后,這時我們hash路由模式和history路由模式已經(jīng)可以基本實現(xiàn),hash模式帶#,history路由模式不帶#。但是我們?nèi)砸x一個監(jiān)聽歷史路由模式變化的監(jiān)聽事件。這里我們通過mode判斷是什么模式從而監(jiān)聽不同的事件,歷史路由模式監(jiān)聽需要通過監(jiān)聽popState方法,來判斷是否發(fā)生變化,它堅挺的是我們?yōu)g覽器的前進后退的變化。

歷史路由模式監(jiān)聽事件為hashchange方法,這個事件是用來監(jiān)聽我們hash值的變化,通過設(shè)置兩個方法從而設(shè)置我們當前路徑為對應(yīng)的path路徑。hash模式會通過slice剪切到#,歷史路由模式則通過location.pathname獲取到當前path路徑。

實現(xiàn)如下:

let Vue;
class VueRouter {
    constructor(options) {
        //保存選項
        this.options = options;
        // console.log(options, '路由數(shù)據(jù)');
        // 定義一個響應(yīng)式的變量current,保存當前的hash值
        let url = location.hash.slice(1,) || '/';
        // defineReactive定義響應(yīng)式的對象
        Vue.util.defineReactive(this, 'current', url)
        //判斷當前的路由模式
        if (this.options.mode === 'hash') {
            // hashchange事件來監(jiān)聽hash值的變化, 注意this指向問題
            addEventListener('hashchange', this.changeHash.bind(this))
        } else if (this.options.mode === 'history') {
            // history模式監(jiān)聽的事件叫做:popstate, 監(jiān)聽的是瀏覽器左上角的兩個小箭頭的變化
            addEventListener('popstate', this.changeHistory.bind(this))
        }
        this.routesMap = {};
        //對routes中的對象做一個映射:routesMap = {'/home':component,'/list': component}
        this.options.routes.forEach(route => {
            this.routesMap[route.path] = route.component
        })
    }
    //監(jiān)聽hash值變化的函數(shù)
    changeHash() {
        //通過location.hash來獲取到hash值
        this.current = location.hash.slice(1,)
        console.log(this.routesMap, '555');
        // console.log(this.current);//當前path路徑
    }
    // history
    changeHistory() {
        // console.log(location.pathname)
        this.current = location.pathname;
    }
}
 VueRouter.install = function (_Vue) {
    //1、保存Vue
    Vue = _Vue
    //2、將以下代碼延遲到vue實例初始化完畢執(zhí)行
    Vue.mixin({
        beforeCreate() {
            //判斷如果有router屬性就執(zhí)行下方代碼
            if (this.$options.router) {
                Vue.prototype.$router = this.$options.router;
            }
        }
    })
    //創(chuàng)建全局組件router-link和router-view
    //創(chuàng)建router-link組件
    Vue.component('router-link', {
        props: {
            to: {
                type: String | Object,
                required: true
            }
        },
        render(h) {// h 有三個參數(shù),第一個參數(shù)創(chuàng)建的元素,第二個參數(shù)元素具有的屬性, 第三個參數(shù)元素的內(nèi)容
            const router = this.$router;
            if (router.options.mode === 'hash') {
                return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default)
            } else if (router.options.mode === 'history') {
                return h('a', {
                    attrs: { href: this.to },
                    on: {
                        'click': ev => {
                            // 1. 阻止a鏈接的默認跳轉(zhuǎn)行為
                            ev.preventDefault()
                            // 2. 調(diào)用pushState方法來實現(xiàn)跳轉(zhuǎn): pushState(obj, title, url)
                            history.pushState({}, '', this.to)
                            // 3. 設(shè)置current的值
                            router.current = this.to;
                        }
                    }
                }, this.$slots.default)
            }
        }
    })
    //創(chuàng)建router-view組件
    Vue.component('router-view', {
        // 組件要重新渲染,必須要讓數(shù)據(jù)發(fā)生改變的時候,重新去執(zhí)行render函數(shù)
        render(h) {
            const router = this.$router
            console.log(router.routesMap, 'routesMap');
            let component = router.routesMap[router.current];//組件
            console.log(component, 'component');
            //獲取到外部傳遞的路由表
            return h(component)
        }
    })
}

這一期我們講解了,如何實現(xiàn)一個基本的hash路由模式以及history路由模式,但是我們通常使用情況下路由嵌套通過一級路由下定義children屬性來定義二級路由,這并沒有實現(xiàn),下一期來實現(xiàn)路由嵌套。

到此這篇關(guān)于vue中兩種路由模式的實現(xiàn)詳解的文章就介紹到這了,更多相關(guān)vue路由模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論