欧美亚洲韩国_av电影院在线看_久久久久97_台湾佬中文娱乐网欧美电影

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

一文聊聊Vue-Router的實現(xiàn)原理

一文聊聊Vue-Router的實現(xiàn)原理

前端(vue)入門到精通課程,老師在線輔導(dǎo):聯(lián)系老師
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調(diào)試工具:點擊使用

路由的概念相信大部分同學(xué)并不陌生,我們在用 Vue 開發(fā)過實際項目的時候都會用到 Vue-Router 這個官方插件來幫我們解決路由的問題。它的作用就是根據(jù)不同的路徑映射到不同的視圖。本文不再講述路由的基礎(chǔ)使用和API,不清楚的同學(xué)可以自行查閱官方文檔vue-router3 對應(yīng) vue2 和 vue-router4 對應(yīng) vue3。

今天我們主要是談?wù)?code>Vue-Router的實現(xiàn)原理,感興趣的小伙伴可以繼續(xù)往下看,大佬請止步。

本文 vue-router 版本為 3.5.3

路由

既然我們在分析路由,我們首先來說說什么是路由,什么是后端路由、什么是前端路由。

路由就是根據(jù)不同的 url 地址展示不同的內(nèi)容或頁面,早期路由的概念是在后端出現(xiàn)的,通過服務(wù)器端渲染后返回頁面,隨著頁面越來越復(fù)雜,服務(wù)器端壓力越來越大。后來ajax異步刷新的出現(xiàn)使得前端也可以對url進行管理,此時,前端路由就出現(xiàn)了。(學(xué)習(xí)視頻分享:web前端開發(fā)、編程基礎(chǔ)視頻)

我們先來說說后端路由

后端路由

后端路由又可稱之為服務(wù)器端路由,因為對于服務(wù)器來說,當(dāng)接收到客戶端發(fā)來的HTTP請求,就會根據(jù)所請求的URL,來找到相應(yīng)的映射函數(shù),然后執(zhí)行該函數(shù),并將函數(shù)的返回值發(fā)送給客戶端。

對于最簡單的靜態(tài)資源服務(wù)器,可以認為,所有URL的映射函數(shù)就是一個文件讀取操作。 對于動態(tài)資源,映射函數(shù)可能是一個數(shù)據(jù)庫讀取操作,也可能是進行一些數(shù)據(jù)的處理,等等。

然后根據(jù)這些讀取的數(shù)據(jù),在服務(wù)器端就使用相應(yīng)的模板來對頁面進行渲染后,再返回渲染完畢的HTML頁面。早期的jsp就是這種模式。

前端路由

剛剛也介紹了,在前后端沒有分離的時候,服務(wù)端都是直接將整個 HTML 返回,用戶每次一個很小的操作都會引起頁面的整個刷新(再加上之前的網(wǎng)速還很慢,所以用戶體驗可想而知)。

在90年代末的時候,微軟首先實現(xiàn)了 ajax(Asynchronous JavaScript And XML) 這個技術(shù),這樣用戶每次的操作就可以不用刷新整個頁面了,用戶體驗就大大提升了。

雖然數(shù)據(jù)能異步獲取不用每個點擊都去請求整個網(wǎng)頁,但是頁面之間的跳轉(zhuǎn)還是會加載整個網(wǎng)頁,體驗不是特別好,還有沒有更好的方法呢?

至此異步交互體驗的更高級版本 SPA單頁應(yīng)用 就出現(xiàn)了。單頁應(yīng)用不僅僅是在頁面交互是無刷新的,連頁面跳轉(zhuǎn)都是無刷新的。既然頁面的跳轉(zhuǎn)是無刷新的,也就是不再向后端請求返回 HTML頁面。

頁面跳轉(zhuǎn)都不從后端獲取新的HTML頁面,那應(yīng)該怎么做呢?所以就有了現(xiàn)在的前端路由。

可以理解為,前端路由就是將之前服務(wù)端根據(jù) url 的不同返回不同的頁面的任務(wù)交給前端來做。在這個過程中,js會實時檢測url的變化,從而改變顯示的內(nèi)容。

前端路由優(yōu)點是用戶體驗好,用戶操作或頁面跳轉(zhuǎn)不會刷新頁面,并且能快速展現(xiàn)給用戶。缺點是首屏加載慢,因為需要js動態(tài)渲染展示內(nèi)容。而且由于內(nèi)容是js動態(tài)渲染的所以不利于SEO

下面我們正式進入Vue-Router原理分析階段。

分析Vue-Router.install方法

我們先來看看install.js,這個方法會在Vue.use(VueRouter)的時候被調(diào)用。

// install.js  import View from './components/view' import Link from './components/link'  export let _Vue  export function install (Vue) {   // 不會重復(fù)安裝   if (install.installed && _Vue === Vue) return   install.installed = true    _Vue = Vue    const isDef = v => v !== undefined    // 為router-view組件關(guān)聯(lián)路由組件   const registerInstance = (vm, callVal) => {     let i = vm.$options._parentVnode     // 調(diào)用vm.$options._parentVnode.data.registerRouteInstance方法     // 而這個方法只在router-view組件中存在,router-view組件定義在(../components/view.js @71行)     // 所以,如果vm的父節(jié)點為router-view,則為router-view關(guān)聯(lián)當(dāng)前vm,即將當(dāng)前vm做為router-view的路由組件     if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {       i(vm, callVal)     }   }    Vue.mixin({     beforeCreate () {       // 這里只會進來一次,因為只有Vue根實例才會有router屬性。       if (isDef(this.$options.router)) {         // 所以這里的this就是Vue根實例         this._routerRoot = this         this._router = this.$options.router         this._router.init(this)         // 將 _route 變成響應(yīng)式         Vue.util.defineReactive(this, '_route', this._router.history.current)       } else {         // 子組件會進入這里,這里也是把Vue根實例保存帶_routerRoot屬性上         this._routerRoot = (this.$parent && this.$parent._routerRoot) || this       }       // 為router-view組件關(guān)聯(lián)路由組件       registerInstance(this, this)     },     destroyed () {       // destroyed hook觸發(fā)時,取消router-view和路由組件的關(guān)聯(lián)       registerInstance(this)     }   })    // 在原型上注入$router、$route屬性,方便快捷訪問   Object.defineProperty(Vue.prototype, '$router', {     // 上面說到每個組件的_routerRoot都是Vue根實例,所以都能訪問_router     get () { return this._routerRoot._router }   })    // 每個組件訪問到的$route,其實最后訪問的都是Vue根實例的_route   Object.defineProperty(Vue.prototype, '$route', {     get () { return this._routerRoot._route }   })    // 注冊router-view、router-link兩個全局組件   Vue.component('RouterView', View)   Vue.component('RouterLink', Link)    const strats = Vue.config.optionMergeStrategies   // use the same hook merging strategy for route hooks   strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created }
登錄后復(fù)制

主要做了如下幾件事情:

避免重復(fù)安裝

為了確保 install 邏輯只執(zhí)行一次,用了 install.installed 變量做已安裝的標(biāo)志位。

傳遞Vue引用減少打包體積

用一個全局的 _Vue 來接收參數(shù) Vue,因為作為 Vue 的插件對 Vue 對象是有依賴的,但又不能去單獨去 import Vue,因為那樣會增加包體積,所以就通過這種方式拿到 Vue 對象。

注冊全局混入

Vue-Router 安裝最重要的一步就是利用 Vue.mixin,在beforeCreatedestroyed生命周期函數(shù)中注入路由邏輯。

Vue.mixin我們知道就是全局 mixin,所以也就相當(dāng)于每個組件的beforeCreatedestroyed生命周期函數(shù)中都會有這些代碼,并在每個組件中都會運行。

Vue.mixin({   beforeCreate () {     if (isDef(this.$options.router)) {       this._routerRoot = this       this._router = this.$options.router       this._router.init(this)       Vue.util.defineReactive(this, '_route', this._router.history.current)     } else {       this._routerRoot = (this.$parent && this.$parent._routerRoot) || this     }     registerInstance(this, this)   },   destroyed () {     registerInstance(this)   } })
登錄后復(fù)制

在這兩個鉤子中,this是指向當(dāng)時正在調(diào)用鉤子的vue實例

這兩個鉤子中的邏輯,在安裝流程中是不會被執(zhí)行的,只有在組件實例化時執(zhí)行到鉤子時才會被調(diào)用

先看混入的 beforeCreate 鉤子函數(shù)

它先判斷了this.$options.router是否存在,我們在new Vue({router})時,router才會被保存到到Vue根實例$options上,而其它Vue實例$options上是沒有router的,所以if中的語句只在this === new Vue({router})時,才會被執(zhí)行,由于Vue根實例只有一個,所以這個邏輯只會被執(zhí)行一次。

對于根 Vue 實例而言,執(zhí)行該鉤子函數(shù)時定義了 this._routerRoot 表示它自身(Vue根實例);this._router 表示 VueRouter 的實例 router,它是在 new Vue 的時候傳入的;

另外執(zhí)行了 this._router.init() 方法初始化 router,這個邏輯在后面講初始化的時候再介紹。

然后用 defineReactive 方法把 this._route 變成響應(yīng)式對象,保證_route變化時,router-view會重新渲染,這個我們后面在router-view組件中會細講。

我們再看下else中具體干了啥

主要是為每個組件定義_routerRoot,對于子組件而言,由于組件是樹狀結(jié)構(gòu),在遍歷組件樹的過程中,它們在執(zhí)行該鉤子函數(shù)的時候 this._routerRoot 始終指向的離它最近的傳入了 router 對象作為配置而實例化的父實例(也就是永遠等于根實例)。

所以我們可以得到,在每個vue組件都有 this._routerRoot === vue根實例this._routerRoot._router === router對象

對于 beforeCreatedestroyed 鉤子函數(shù),它們都會執(zhí)行 registerInstance 方法,這個方法的作用我們也是之后會介紹。

添加$route、$router屬性

接著給 Vue 原型上定義了 $router$route 2 個屬性的 get 方法,這就是為什么我們可以在任何組件實例上都可以訪問 this.$router 以及 this.$route

Object.defineProperty(Vue.prototype, '$router', { get () { return this._routerRoot._router } })  Object.defineProperty(Vue.prototype, '$route', { get () { return this._routerRoot._route } })
登錄后復(fù)制

我們可以看到,$router其實返回的是this._routerRoot._router,也就是vue根實例上的router,因此我們可以通過this.$router來使用router的各種方法。

$route其實返回的是this._routerRoot._route,其實就是this._router.history.current,也就是目前的路由對象,這個后面會細說。

注冊全局組件

通過 Vue.component 方法定義了全局的 <router-link><router-view> 2 個組件,這也是為什么我們在寫模板的時候可以直接使用這兩個標(biāo)簽,它們的作用我想就不用筆者再說了吧。

鉤子函數(shù)的合并策略

最后設(shè)置路由組件的beforeRouteEnterbeforeRouteLeavebeforeRouteUpdate守衛(wèi)的合并策略。

總結(jié)

那么到此為止,我們分析了 Vue-Router 的安裝過程,Vue 編寫插件的時候通常要提供靜態(tài)的 install 方法,我們通過 Vue.use(plugin) 時候,就是在執(zhí)行 install 方法。Vue-Routerinstall 方法會給每一個組件注入 beforeCreatedestoryed 鉤子函數(shù),在beforeCreate 做一些私有屬性定義和路由初始化工作。并注冊了兩個全局組件,然后設(shè)置了鉤子函數(shù)合并策略。在destoryed 做了一些銷毀工作。

下面我們再來看看Vue-Router的實例化。

分析init方法

前面我們提到了在 install 的時候會執(zhí)行 VueRouterinit 方法( this._router.init(this) ),那么接下來我們就來看一下 init 方法做了什么。

init (app: any /* Vue component instance */) {   // ...    this.apps.push(app)    // ...    // main app previously initialized   // return as we don't need to set up new history listener   if (this.app) {     return   }    this.app = app    const history = this.history      if (history instanceof HTML5History || history instanceof HashHistory) {     const handleInitialScroll = routeOrError => {       const from = history.current       const expectScroll = this.options.scrollBehavior       const supportsScroll = supportsPushState && expectScroll        if (supportsScroll && 'fullPath' in routeOrError) {         handleScroll(this, routeOrError, from, false)       }     }          // 1.setupListeners 里會對 hashchange或popstate事件進行監(jiān)聽     const setupListeners = routeOrError => {       history.setupListeners()       handleInitialScroll(routeOrError)     }     // 2.初始化導(dǎo)航     history.transitionTo(       history.getCurrentLocation(),       setupListeners,       setupListeners     )   }    // 3.路由全局監(jiān)聽,維護當(dāng)前的route    // 當(dāng)路由變化的時候修改app._route的值   // 由于_route是響應(yīng)式的,所以修改后相應(yīng)視圖會同步更新   history.listen(route => {     this.apps.forEach(app => {       app._route = route     })   }) }
登錄后復(fù)制

這里主要做了如下幾件事情:

設(shè)置了路由監(jiān)聽

const setupListeners = routeOrError => {   history.setupListeners()   handleInitialScroll(routeOrError) }
登錄后復(fù)制

這里會根據(jù)當(dāng)前路由模式監(jiān)聽hashchangepopstate事件,當(dāng)事件觸發(fā)的時候,會進行路由的跳轉(zhuǎn)。(后面說到路由模式的時候會細說)

初始化導(dǎo)航

history.transitionTo(   history.getCurrentLocation(),   setupListeners,   setupListeners )
登錄后復(fù)制

進入系統(tǒng)會進行初始化路由匹配,渲染對應(yīng)的組件。因為第一次進入系統(tǒng),并不會觸發(fā)hashchange或者popstate事件,所以第一次需要自己手動匹配路徑然后進行跳轉(zhuǎn)。

路由全局監(jiān)聽

history.listen(route => {   this.apps.forEach(app => {     app._route = route   }) })
登錄后復(fù)制

當(dāng)路由變化的時候修改app._route的值。由于_route是響應(yīng)式的,所以修改后相應(yīng)視圖會同步更新。

總結(jié)

這里主要是做了一些初始化工作。根據(jù)當(dāng)前路由模式監(jiān)聽對應(yīng)的路由事件。初始化導(dǎo)航,根據(jù)當(dāng)前的url渲染初始頁面。最后切換路由的時候修改_route,由于_route是響應(yīng)式的,所以修改后相應(yīng)視圖會同步更新。

分析VueRouter實例化

實例化就是我們new VueRouter({routes})的過程,我們來重點分析下VueRouter的構(gòu)造函數(shù)。

constructor (options: RouterOptions = {}) {   // ...      // 參數(shù)初始化   this.app = null   this.apps = []   this.options = options   this.beforeHooks = []   this.resolveHooks = []   this.afterHooks = []   // 創(chuàng)建matcher   this.matcher = createMatcher(options.routes || [], this)    // 設(shè)置默認模式和做不支持 H5 history 的降級處理   let mode = options.mode || 'hash'   this.fallback =     mode === 'history' && !supportsPushState && options.fallback !== false   if (this.fallback) {     mode = 'hash'   }   if (!inBrowser) {     mode = 'abstract'   }   this.mode = mode    // 根據(jù)不同的 mode 實例化不同的 History 對象   switch (mode) {     case 'history':       this.history = new HTML5History(this, options.base)       break     case 'hash':       this.history = new HashHistory(this, options.base, this.fallback)       break     case 'abstract':       this.history = new AbstractHistory(this, options.base)       break     default:       if (process.env.NODE_ENV !== 'production') {         assert(false, `invalid mode: ${mode}`)       }   } }
登錄后復(fù)制

這里主要做了如下幾件事情:

初始化參數(shù)

我們看到在最開始有些參數(shù)的初始化,這些參數(shù)到底是什么呢?

this.app 用來保存根 Vue 實例。

this.apps 用來保存持有 $options.router 屬性的 Vue 實例。

this.options 保存?zhèn)魅氲穆酚膳渲茫簿褪乔懊嬲f的RouterOptions

this.beforeHooksthis.resolveHooksthis.afterHooks 表示一些鉤子函數(shù)。

this.fallback 表示在瀏覽器不支持 historyapi的情況下,根據(jù)傳入的 fallback 配置參數(shù),決定是否回退到hash模式。

this.mode 表示路由創(chuàng)建的模式。

創(chuàng)建matcher

matcher,匹配器。簡單理解就是可以通過url找到我們對應(yīng)的組件。這一塊內(nèi)容較多,這里筆者就不再詳細分析了。

確定路由模式

路由模式平時都會只說兩種,其實在vue-router總共實現(xiàn)了 hashhistoryabstract 3 種模式。

VueRouter會根據(jù)options.modeoptions.fallbacksupportsPushStateinBrowser來確定最終的路由模式。

如果沒有設(shè)置mode就默認是hash模式。

確定fallback值,只有在用戶設(shè)置了mode:history并且當(dāng)前環(huán)境不支持pushState且用戶沒有主動聲明不需要回退(沒設(shè)置fallback值位undefined),此時this.fallback才為true,當(dāng)fallbacktrue時會使用hash模式。(簡單理解就是如果不支持history模式并且只要沒設(shè)置fallbackfalse,就會啟用hash模式)

如果最后發(fā)現(xiàn)處于非瀏覽器環(huán)境,則會強制使用abstract模式。

實例化路由模式

根據(jù)mode屬性值來實例化不同的對象。VueRouter的三種路由模式,主要由下面的四個核心類實現(xiàn)

  • History

    • 基礎(chǔ)類
    • 位于src/history/base.js
  • HTML5History

    • 用于支持pushState的瀏覽器
    • src/history/html5.js
  • HashHistory

    • 用于不支持pushState的瀏覽器
    • src/history/hash.js
  • AbstractHistory

    • 用于非瀏覽器環(huán)境(服務(wù)端渲染)
    • src/history/abstract.js

HTML5HistoryHashHistoryAbstractHistory三者都是繼承于基礎(chǔ)類History

這里我們詳細分析下HTML5HistoryHashHistory類。

HTML5History類

當(dāng)我們使用history模式的時候會實例化HTML5History類

// src/history/html5.js  ...  export class HTML5History extends History {   _startLocation: string    constructor (router: Router, base: ?string) {     // 調(diào)用父類構(gòu)造函數(shù)初始化     super(router, base)      this._startLocation = getLocation(this.base)   }    // 設(shè)置監(jiān)聽,主要是監(jiān)聽popstate方法來自動觸發(fā)transitionTo   setupListeners () {     if (this.listeners.length > 0) {       return     }      const router = this.router     const expectScroll = router.options.scrollBehavior     const supportsScroll = supportsPushState && expectScroll          // 若支持scroll,初始化scroll相關(guān)邏輯     if (supportsScroll) {       this.listeners.push(setupScroll())     }      const handleRoutingEvent = () => {       const current = this.current        // 某些瀏覽器,會在打開頁面時觸發(fā)一次popstate        // 此時如果初始路由是異步路由,就會出現(xiàn)`popstate`先觸發(fā),初始路由后解析完成,進而導(dǎo)致route未更新        // 所以需要避免       const location = getLocation(this.base)       if (this.current === START && location === this._startLocation) {         return       }              // 路由地址發(fā)生變化,則跳轉(zhuǎn),如需滾動則在跳轉(zhuǎn)后處理滾動       this.transitionTo(location, route => {         if (supportsScroll) {           handleScroll(router, route, current, true)         }       })     }          // 監(jiān)聽popstate事件     window.addEventListener('popstate', handleRoutingEvent)     this.listeners.push(() => {       window.removeEventListener('popstate', handleRoutingEvent)     })   }    // 可以看到 history模式go方法其實是調(diào)用的window.history.go(n)   go (n: number) {     window.history.go(n)   }    // push方法會主動調(diào)用transitionTo進行跳轉(zhuǎn)   push (location: RawLocation, onComplete?: Function, onAbort?: Function) {     const { current: fromRoute } = this     this.transitionTo(location, route => {       pushState(cleanPath(this.base + route.fullPath))       handleScroll(this.router, route, fromRoute, false)       onComplete && onComplete(route)     }, onAbort)   }    // replace方法會主動調(diào)用transitionTo進行跳轉(zhuǎn)   replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {     const { current: fromRoute } = this     this.transitionTo(location, route => {       replaceState(cleanPath(this.base + route.fullPath))       handleScroll(this.router, route, fromRoute, false)       onComplete && onComplete(route)     }, onAbort)   }    ensureURL (push?: boolean) {     if (getLocation(this.base) !== this.current.fullPath) {       const current = cleanPath(this.base + this.current.fullPath)       push ? pushState(current) : replaceState(current)     }   }    getCurrentLocation (): string {     return getLocation(this.base)   } }  export function getLocation (base: string): string {   let path = window.location.pathname   const pathLowerCase = path.toLowerCase()   const baseLowerCase = base.toLowerCase()   // base="/a" shouldn't turn path="/app" into "/a/pp"   // https://github.com/vuejs/vue-router/issues/3555   // so we ensure the trailing slash in the base   if (base && ((pathLowerCase === baseLowerCase) ||     (pathLowerCase.indexOf(cleanPath(baseLowerCase + '/')) === 0))) {     path = path.slice(base.length)   }   return (path || '/') + window.location.search + window.location.hash }
登錄后復(fù)制

可以看到HTML5History類主要干了如下幾件事。

  • 繼承于History類,并調(diào)用父類構(gòu)造函數(shù)初始化。

  • 實現(xiàn)了setupListeners方法,在該方法中檢查了是否需要支持滾動行為,如果支持,則初始化滾動相關(guān)邏輯,監(jiān)聽了popstate事件,并在popstate觸發(fā)時自動調(diào)用transitionTo方法。

  • 實現(xiàn)了go、push、replace等方法,我們可以看到,history模式其實就是使用的history api

// 可以看到 history模式go方法其實是調(diào)用的window.history.go(n) go (n: number) {   window.history.go(n) }  // push、replace調(diào)用的是util/push-state.js,里面實現(xiàn)了push和replace方法 // 實現(xiàn)原理也是使用的history api,并且在不支持history api的情況下使用location api  export function pushState (url?: string, replace?: boolean) {   ...   const history = window.history   try {     if (replace) {       const stateCopy = extend({}, history.state)       stateCopy.key = getStateKey()       // 調(diào)用的 history.replaceState       history.replaceState(stateCopy, '', url)     } else {       // 調(diào)用的 history.pushState       history.pushState({ key: setStateKey(genStateKey()) }, '', url)     }   } catch (e) {     window.location[replace ? 'replace' : 'assign'](url)   } }  export function replaceState (url?: string) {   pushState(url, true) }
登錄后復(fù)制

總結(jié)

所以history模式的原理就是在js中路由的跳轉(zhuǎn)(也就是使用pushreplace方法)都是通過history apihistory.pushStatehistory.replaceState兩個方法完成,通過這兩個方法我們知道了路由的變化,然后根據(jù)路由映射關(guān)系來實現(xiàn)頁面內(nèi)容的更新。

對于直接點擊瀏覽器的前進后退按鈕或者js調(diào)用 this.$router.go()this.$router.forward()this.$router.back()、或者原生js方法history.back()history.go()history.forward()的,都會觸發(fā)popstate事件,通過監(jiān)聽這個事件我們就可以知道路由發(fā)生了哪些變化然后來實現(xiàn)更新頁面內(nèi)容。

注意history.pushStatehistory.replaceState這兩個方法并不會觸發(fā)popstate事件。在這兩個方法里面他是有手動調(diào)用transitionTo方法的。

接下來我們再來看看HashHistory類

HashHistory類

當(dāng)我們使用hash模式的時候會實例化HashHistory類

//src/history/hash.js  ...  export class HashHistory extends History {   constructor (router: Router, base: ?string, fallback: boolean) {     super(router, base)     // check history fallback deeplinking     if (fallback && checkFallback(this.base)) {       return     }     ensureSlash()   }    setupListeners () {     if (this.listeners.length > 0) {       return     }      const router = this.router     const expectScroll = router.options.scrollBehavior     const supportsScroll = supportsPushState && expectScroll      if (supportsScroll) {       this.listeners.push(setupScroll())     }      const handleRoutingEvent = () => {       const current = this.current       if (!ensureSlash()) {         return       }       this.transitionTo(getHash(), route => {         if (supportsScroll) {           handleScroll(this.router, route, current, true)         }         if (!supportsPushState) {           replaceHash(route.fullPath)         }       })     }     // 事件優(yōu)先使用 popstate     // 判斷supportsPushState就是通過return window.history && typeof window.history.pushState === 'function'     const eventType = supportsPushState ? 'popstate' : 'hashchange'     window.addEventListener(       eventType,       handleRoutingEvent     )     this.listeners.push(() => {       window.removeEventListener(eventType, handleRoutingEvent)     })   }      // 其實也是優(yōu)先使用history的pushState方法來實現(xiàn),不支持再使用location修改hash值   push (location: RawLocation, onComplete?: Function, onAbort?: Function) {     const { current: fromRoute } = this     this.transitionTo(       location,       route => {         pushHash(route.fullPath)         handleScroll(this.router, route, fromRoute, false)         onComplete && onComplete(route)       },       onAbort     )   }    // 其實也是優(yōu)先使用history的replaceState方法來實現(xiàn),不支持再使用location修改replace方法   replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {     const { current: fromRoute } = this     this.transitionTo(       location,       route => {         replaceHash(route.fullPath)         handleScroll(this.router, route, fromRoute, false)         onComplete && onComplete(route)       },       onAbort     )   }    // 也是使用的history go方法   go (n: number) {     window.history.go(n)   }    ensureURL (push?: boolean) {     const current = this.current.fullPath     if (getHash() !== current) {       push ? pushHash(current) : replaceHash(current)     }   }    getCurrentLocation () {     return getHash()   } }  function checkFallback (base) {   const location = getLocation(base)   if (!/^/#/.test(location)) {     window.location.replace(cleanPath(base + '/#' + location))     return true   } }  function ensureSlash (): boolean {   const path = getHash()   if (path.charAt(0) === '/') {     return true   }   replaceHash('/' + path)   return false }  // 獲取 # 后面的內(nèi)容 export function getHash (): string {   // We can't use window.location.hash here because it's not   // consistent across browsers - Firefox will pre-decode it!   let href = window.location.href   const index = href.indexOf('#')   // empty path   if (index < 0) return ''    href = href.slice(index + 1)    return href }  function getUrl (path) {   const href = window.location.href   const i = href.indexOf('#')   const base = i >= 0 ? href.slice(0, i) : href   return `${base}#${path}` }  function pushHash (path) {   if (supportsPushState) {     pushState(getUrl(path))   } else {     window.location.hash = path   } }  function replaceHash (path) {   if (supportsPushState) {     replaceState(getUrl(path))   } else {     window.location.replace(getUrl(path))   } }
登錄后復(fù)制

可以看到HashHistory類主要干了如下幾件事。

  • 繼承于History類,并調(diào)用父類構(gòu)造函數(shù)初始化。這里比HTML5History多了回退操作,所以,需要將history模式的url替換成hash模式,即添加上#,這個邏輯是由checkFallback實現(xiàn)的

  • 實現(xiàn)了setupListeners方法,在該方法中檢查了是否需要支持滾動行為,如果支持,則初始化滾動相關(guān)邏輯。 監(jiān)聽了popstate事件或hashchange事件,并在相應(yīng)事件觸發(fā)時,調(diào)用transitionTo方法實現(xiàn)跳轉(zhuǎn)。

通過const eventType = supportsPushState ? 'popstate' : 'hashchange'我們可以發(fā)現(xiàn)就算是hash模式優(yōu)先使用的還是popstate事件。

  • 實現(xiàn)了go、push、replace等方法。

我們可以看到,hash模式實現(xiàn)的push、replace方法其實也是優(yōu)先使用history里面的方法,也就是history api

// 可以看到 hash 模式go方法其實是調(diào)用的window.history.go(n) go (n: number) {   window.history.go(n) }  // 在支持新的history api情況下優(yōu)先使用history.pushState實現(xiàn) // 否則使用location api function pushHash (path) {   if (supportsPushState) {     pushState(getUrl(path))   } else {     window.location.hash = path   } }  // 在支持新的history api情況下優(yōu)先使用history.replaceState實現(xiàn) // 否則使用location api function replaceHash (path) {   if (supportsPushState) {     replaceState(getUrl(path))   } else {     window.location.replace(getUrl(path))   } }
登錄后復(fù)制

總結(jié)

在瀏覽器鏈接里面我們改變hash值是不會重新向后臺發(fā)送請求的,也就不會刷新頁面。并且每次 hash 值的變化,還會觸發(fā)hashchange 這個事件。

所以hash模式的原理就是通過監(jiān)聽hashchange事件,通過這個事件我們就可以知道 hash 值發(fā)生了哪些變化然后根據(jù)路由映射關(guān)系來實現(xiàn)頁面內(nèi)容的更新。(這里hash值的變化不管是通過js修改的還是直接點擊瀏覽器的前進后退按鈕都會觸發(fā)hashchange事件)

對于hash模式,如果是在瀏覽器支持history api情況下,hash模式的實現(xiàn)其實是和history模式一樣的。只有在不支持history api情況下才會監(jiān)聽hashchange事件。這個我們可以在源碼中看出來。

一文聊聊Vue-Router的實現(xiàn)原理

總結(jié)

總的來說就是使用 Vue.util.defineReactive 將實例的 _route 設(shè)置為響應(yīng)式對象。在push, replace方法里會主動更新屬性 _route。而 go,back,forward,或者通過點擊瀏覽器前進后退的按鈕則會在 hashchange 或者 popstate 的回調(diào)中更新 _route_route 的更新會觸發(fā) RoterView 的重新渲染。

對于第一次進入系統(tǒng),并不會觸發(fā)hashchange或者popstate事件,所以第一次需要自己手動匹配路徑然后通過transitionTo方法進行跳轉(zhuǎn),然后渲染對應(yīng)的視圖。

(學(xué)習(xí)視頻分享:web前端開發(fā)、編程基礎(chǔ)視頻)

贊(0)
分享到: 更多 (0)
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
主站蜘蛛池模板: 五月婷久久 | jlzzjizz在线播放观看 | 天堂网色| 国产精品国产三级欧美 | 伊人春色视频 | 国产精品99久久久久久动医院 | 日韩资源在线观看 | 欧美性xxxxx极品娇小 | 69视频在线| jzzijzzij亚洲成熟少妇在线播放 一区二区视频在线播放 | 久操视频在线免费观看 | 呦呦精品| 九九热九九爱 | 久久午夜国产 | 久久午夜影视 | 亚洲一区二区三区四区视频 | 国产亚洲欧美久久久久 | 香蕉网站视频 | 天堂伊人| 日韩精品成人免费观看视频 | 日本免费一级片 | 国产情侣激情自拍 | 高跟av| 制服.丝袜.亚洲.中文.综合懂色 | 国产伦精品一区二区三区四区免费 | 男人的亚洲天堂 | 国产精品成人免费视频 | 国产成人在线影院 | 欧美日韩中文字幕在线视频 | 国产老头户外野战xxxxx | 三级麻豆| 香蕉视频好色先生 | 淫综合网 | 麻豆网站在线播放 | 黄视频免费看在线 | av网页在线 | 狠狠操麻豆| а√在线中文网新版地址在线 | 在线看毛片网站 | 亚洲欧美国产一区二区 | 亚洲911精品成人18网站 | 成人3d动漫在线观看 | www狠狠 | 久久怡红院 | 亚洲成a人v | 天天操夜夜操视频 | 久久最新视频 | 亚洲黄色免费在线观看 | 日韩免费观看一区二区 | 亚洲第一视频网 | 一级片黄色 | 中文字幕色图 | 成人久久18免费网站 | 最近2019中文字幕一页 | 五月婷婷综合网 | 亚洲激情图 | 天堂在线一区二区 | 91精品婷婷国产综合久久蝌蚪 | 欧美91av | 蜜臀精品一区二区三区 | 在线观看91精品国产网站 | 国内特级毛片 | 欧美综合亚洲 | 久久久久久久久久久久久大色天下 | 国产97色 | 国产一区二区中文字幕 | javxxx| 欧美在线中文字幕 | 97视频久久 | 国产不卡一二三 | 国产成人一区二区 | 天天夜夜人人 | 91理论片 | 色吧综合网 | 亚洲自拍99 | 黄色成年视频 | 欧美精品乱码99久久蜜桃 | 啪啪视屏 | 操操网站 | wwww黄色片 | 色香蕉在线| 888奇米影视 | 黄色免费在线播放 | 九九精品视频在线观看 | 亚洲欧美视频一区 | 青青草华人在线 | 亚洲国产中文在线 | 一级做a爱片性色毛片www | 国产一及毛片 | 国产精品亚洲视频 | 国产做受网站 | 中文字幕在线观看av | 日本黄色视 | 91免费福利视频 | 91久久极品少妇xxxxⅹ软件 | 男人天堂五月天 | 国内成人自拍视频 | 女人性做爰100部免费 | 国产普通话bbwbbwbbw | 孕妇毛片| 国产男女无套 | 亚洲视频免费在线看 | 欧美成人黑人xx视频免费观看 | 欧美日韩久久精品 | 欧美性色网站 | 欧美一级二级三级视频 | 一级免费黄色片 | 日本在线播放一区 | 国产精品爽爽久久久久久 | 国产3级| 欧美久久久久久久久久久 | 青青草在线免费视频 | 成人黄色免费网址 | 国产高潮自拍 | 妖精视频在线观看 | 天天干天天操天天舔 | 四级毛片 | 欧美日韩性生活视频 | 精品一区二区三区久久久 | 激情综合五月婷婷 | 欧美综合视频在线观看 | 色噜噜日韩精品欧美一区二区 | 97插插插 | 国产成人99久久亚洲综合精品 | 天堂av免费 | 国产精品入口夜色视频大尺度 | 欧美黑吊大战白妞欧美大片 | 亚洲一区二区三区国产精华液 | 黄色大片在线播放 | 在线视频免费观看 | 国产又粗又黄又爽视频 | 成人小视频在线播放 | 日本中文字幕网站 | 永久免费看成人av的动态图 | 伊人院| 国产精品久久久久影院老司 | 亚洲国产成人精品女人久久 | 亚洲少妇一区二区三区 | 天堂伊人网 | 中文在线观看视频 | 成人7777 | 国产又粗又爽视频 | 九九热超碰| 嫩草国产精品 | 天堂在线资源8 | 欧美一区二区激情视频 | 一区精品视频 | 国产a∨精品一区二区三区仙踪林 | 欧美片一区二区 | 九九热精品在线观看 | 成人精品久久久 | 91精品美女 | 亚洲不卡视频在线观看 | 国产首页| 欧美精品福利 | 亚洲一区二区精华液 | 福利社毛片 | 国产黄a三级三级三级看三级男男 | 日韩黄网 | 午夜影院0606| 国产乱色精品成人免费视频 | 亚洲不卡免费视频 | 免费成人小视频 | 精品人成 | 手机在线精品视频 | 亚洲乱码一区二区三区三上悠亚 | 国产无毛av | 成人综合影院 | 亚洲黄在线观看 | 视频一区在线免费观看 | 一级大片免费看 | 国产一区一区 | 一区二区三区波多野结衣 | 免费国产羞羞网站视频 | 亚洲自拍另类 | 久久中文娱乐网 | 天天操天 | 92国产精品 | 国产娇小性色xxxxx视频 | www.com黄色 | 在线观看免费高清在线观看 | 亚洲品质自拍 | 精品国产乱码久久久久久绯色 | 国产尤物网站 | 高h校园不许穿内裤h调教 | 熊猫av| 天天射日日射 | 亚洲va久久久噜噜噜久久天堂 | 成人宗合 | japanese21ⅹxx日本 | 波多野结衣一区二区三区在线 | 黄色在线播放网站 | www.四虎.com| 99热在线只有精品 | 97碰 | 99午夜视频 | 正在播放亚洲 | 天天干女人 | 国产在线观 | 亚洲欧美另类中文字幕 | av网站在线观看免费 | 加勒比一区二区三区 | 国产精品999 | 在线成人| 欧美综合激情网 | 亚洲视频99 | 黄色高清视频在线观看 | 久久的色偷偷 | 另类专区亚洲 | 最新精品在线 | 日韩久久av| 午夜精品免费视频 | 中文字幕义父 | 嘿咻视频在线观看 | 99精品视频在线观看免费 | 日本黄色大片免费看 | 在线免费观看国产视频 | 伊人网在线播放 | 在线观看 中文字幕 | 人人澡超碰碰97碰碰碰 | 精品一区二区三区在线视频 | 亚洲精品一卡二卡 | 性欧美videos另类极品小说 | 日本午夜大片 | 久久高清av | 中文字幕一区二区免费 | 茄子爱啪啪| 激情丁香六月 | 四虎午夜影院 | av资源网在线观看 | 蜜桃一区二区 | 国产对白精品刺激二区国语 | 国产区久久 | www.香蕉视频在线观看 | 欧美在线观看一区二区三区 | 中文字幕精品一区二区三区精品 | 日韩精品av一区二区三区 | 国产专区一区二区 | 欧美一极片 | 久草一本 | 游戏涩涩免费网站 | 波多野结衣一二三区 | 超碰偷拍| 在线亚洲成人 | 欧美大片黄| 高潮久久久久久久久 | 乱亲女h秽乱长久久久 | 日韩精品免费看 | 日韩精品一区二区三区在线观看 | 久久婷婷av| 一级做a爰 | 欧美久久久久久久久久 | 深夜福利av | 久久久精品天堂 | 精品视频亚洲 | 九九影院最新理论片 | 91狠狠综合| 日韩色网 | 成人午夜淫片免费观看 | 四虎国产精品永久在线国在线 | 成人在线播放av | 在线播放91灌醉迷j高跟美女 | 鸭子av| 一本大道香蕉大a√在线 | 天天艹夜夜| 狠狠干成人| 国产又色又爽又黄的 | 福利一区福利二区 | 玖玖视频在线 | 国产又粗又猛又爽又黄的视频一 | 国产欧美一区二区三区精品酒店 | 国产91网| 男人的天堂av网站 | 麻豆啪啪 | 91激情网站| 怡红院毛片 | 2018天天干天天操 | 国产乱码精品一区二区三区爽爽爽 | 欧美黑人一级片 | 国产高清在线不卡 | 在线综合色 | 九九热国产在线 | 色网站免费观看 | 天堂网中文| 奇米超碰在线 | 国产乱淫a∨片免费观看 | 999xxxx | 久久午夜网站 | 精品久久久一区 | 国产老头户外野战xxxxx | 欧美在线一 | 久久久久久久久久久影院 | 大香焦久久 | 国产污在线观看 | 亚洲天堂91 | av黄色影院 | 久久国产色av | 在线观看97 | 日韩喷潮| 欧亚av在线 | 色吧av色av| 国产精品福利在线观看 | 亚洲精品老司机 | 免费观看日批视频 | 国产区在线观看视频 | 国产一级生活片 | 亚洲激情视频网站 | 久久亚洲国产成人精品性色 | 一本色综合网 | 自拍偷拍国产精品 | 国产网站黄色 | 国产色在线| 天天插天天操天天干 | 成人在线毛片 | 伊人精品综合 | 伊人资源网 | 一个色在线视频 | 激情小说亚洲图片 | 亚洲免费黄色网址 | 亚洲天堂第一页 | a国产一区二区免费入口 | 亚洲午夜久久久 | 精品成人av一区二区三区 | 亚洲国产91 | 蜜桃综合网 | 久久久久久久久久久免费 | 亚洲精选中文字幕 | 久久久久国产视频 | 成人av影视在线观看 | 黄色av小说在线观看 | www国产成人免费观看视频,深夜成人网 | 高清av不卡 | av在线播放网址 | 成人a在线 | 欧美福利视频一区二区 | 99re国产精品 | 日本三级一区 | 97久久人国产精品婷婷 | 国内9l自拍 | 国产精品19p | 日韩成人精品在线 | 亚洲 欧美 激情 另类 | 亚洲精品成人区在线观看 | 亚洲天堂视频网站 | 亚洲怕怕 | 陪读偷伦初尝小说 | 丁香花高清在线 | 亚洲国产成人精品视频 | 玖操| 中文字幕一区二区三区手机版 | 日韩精品黄 | 经典毛片 | 草草草在线 | 六月婷婷在线观看 | 免费在线日韩 | 91极品视频 | 久久中文一区 | 看免费黄色大片 | 中文在线a√在线8 | 插插插干干干 | 国产在线成人精品午夜 | 天堂综合 | 激情网站在线观看 | 日本少妇性高潮 | 国产麻豆一区二区三区 | 欧美日韩理论 | 欧美日韩色 | 国产不卡视频在线 | 天天色天天色 | 日本中文字幕在线观看视频 | 日韩一卡二卡在线 | 天天干在线播放 | 亚洲大尺度在线观看 | 成人va在线观看 | 久夜精品 | 91麻豆国产在线 | 午夜免费影院 | 伊人久久青青草 | 深夜福利视频在线观看 | 两性囗交做爰视频 | 伊人国产在线 | 6080一区| 欧美亚洲91| www国产亚洲精品久久麻豆 | 日韩网站免费 | 色眯眯视频| 11孩岁女毛片 | 亚州av免费| 人人爽人人爽人人片av | 亚洲精品久久久蜜桃动漫 | 国产精品自产拍在线观看 | 久热只有精品 | 欧美成人91 | 公车痴汉媚药强抹在线观看 | 国产a久久麻豆入口 | 亚洲欧美午夜 | 中文久久久 | 精品国产三级 | 99国产精品久久不卡毛片 | 男人天堂最新网址 | 爱看av| 亚洲天堂系列 | 丁香花高清在线 | 亚洲一区二区在线 | 一本色道久久综合亚洲精品按摩 | 97精品久久人人爽人人爽 | 久久久www成人免费无遮挡大片 | 中文幕无线码中文字蜜桃 | 国产精品久久久久久久不卡 | 成年人看片网站 | 好色婷婷 | 欧美黄色大片网站 | 午夜肉体高潮免费毛片 | 人人色网 | 色偷偷噜噜噜亚洲男人的天堂 | 一级大黄色片 | 韩毛片 | av老司机在线播放 | 欧美一级片免费观看 | 免费伊人网 | 波多野结衣高清视频 | 欧美日韩国产a | 激情综合网五月天 | 四虎影院免费视频 | 青娱乐欧美| 欧美激情一区二区三区 | 亚洲高潮 | 日韩欧美高清 | 午夜精品久久久久久毛片 | 日日射射| 久久夜色精品国产欧美乱极品 | 黄色a级片网站 | 成年人在线网站 | 狠狠艹 | 天海翼一区二区 | 日韩一二三四区 | 亚洲免费福利 | 久操精品视频 | 精品免费一区二区 | 欧美污视频在线观看 | 国产超碰人人模人人爽人人添 | 在线精品一区二区三区 | 五月天综合网 | 色噜噜一区二区三区 | 3d动漫精品啪啪一区二区竹菊 | 97精品超碰一区二区三区 | 成人免费福利网站 | av网站中文字幕 | 久热国产在线 | 日本精品久久久久 | 噜噜色网 | 久草视频在线播放 | 在线播放www | 天堂在线视频tv | 亚洲综合第一页 | 久久精品美女 | 久久艹在线观看 | 中文成人无字幕乱码精品区 | 一级黄色片视频 | 免费黄色在线视频 | 超薄肉色丝袜一区二区 | 97中文在线 | xxxx国产精品 | 欧美日韩亚洲在线 | 丁香激情小说 | 国内精品久久久久久久久久久 | 亚洲黄色www | 资源av | 精品日韩一区二区三区免费视频 | 欧美男人亚洲天堂 | 国产区精品 | 国产精品一区二区三区在线播放 | 五月婷婷久久久 | 国产精品一品二区三区的使用体验 | 夜夜骑天天干 | 日本美女操 | 超碰在线网 | 亚洲综合在线观看视频 | 青草av在线 | 国产草逼网站 | 国产乱在线 | 国产精品99久久久久久www | 欧美高清性 | 插吧插吧网 | 天天插天天射 | 嫩草天堂 | 国产伦理av | 欧美日韩卡一卡二 | 午夜av一区二区三区 | av综合资源 | 国产一级淫片a视频免费观看 | 国产精品一区二区三区在线播放 | 五月色丁香 | 日本在线观看 | 亚洲精品一区中文字幕乱码 | 色婷婷小说 | 最近中文在线观看 | 欧美精品乱码久久久久久按摩 | 天天精品视频 | 在线观看免费国产视频 | 午夜在线观看免费视频 | 日韩欧美精品久久 | av色先锋 | 久久青青草原 | 91精品在线免费观看 | 69婷婷国产精品入口 | 国产精品2 | 欧美精品黄色 | 悠悠色av | 中文字幕免费观看视频 | 男人操女人的网站 | 欧美日韩乱国产 | 久久免费福利视频 | 4438亚洲最大 | 97视频精品 | 精品视频一区二区 | 艹男人的日日夜夜 | 午夜天堂精品xbxb | 午夜视频福利在线观看 | 亚洲性久久久 | 色xxxxxx | 日韩av网站在线观看 | 国产破处在线 | 亚洲高清毛片一区二区 | 成年人免费黄色 | 性生活香蕉视频 | 美日韩免费 | 欧美国产免费 | 日韩中文字幕免费在线观看 | 最新中文字幕av专区 | 国产寡妇色xxⅹ交肉视频 | 免费视频一区 | 婷婷久久久久久 | 在线免费观看黄色片 | 亚洲乱码国产乱码精品精大量 | 一二区在线观看 | 国产精品成人国产乱 | 日韩丰满少妇 | 国产男女av| 黄色a一级视频 | 天天综合国产 | 91涩| 精品中文字幕在线播放 | 国产精选在线 | 91久久一区 | 久久视频免费在线观看 | 妹子色综合 | 高清av网站 | 国产爽爽爽 | 久热精品视频在线 | 38激情 | 在线成人国产 | www.夜夜| 日韩男人的天堂 | 99热热99 | 午夜激情国产 | 蜜臀精品一区二区三区 | 色综合视频在线 | 黑森林av导航 | 日韩在线视频一区二区三区 | 超碰在线91| 日韩亚洲欧美在线 | 最新中文字幕2019 | 亚洲天堂视频在线播放 | 少妇精品一区二区三区 | 亚洲福利在线视频 | 亚洲成人av网址 | 奇米影视亚洲春色 | 在线h网| 久久久久久久福利 | 成人免费看片又大又黄 | 欧美日韩a v | 精品一区在线视频 | 男人艹女人网站 | 最新日韩av在线 | 一级色网站 | 日韩高清一区 | 玖玖玖视频 | 五月婷婷激情小说 | 成人性生交大片免费看r链接 | 国产丝袜自拍 | 久久久久久网址 | 亚色av| 日韩美女网站 | 日韩无套 | 在线看视频 | 一区二区三区手机在线观看 | 亚洲精视频 | 亚洲欧美日韩精品永久在线 | 国产精自产拍久久久久久蜜 | 国产精品久久久久久久久久久久久久久久久 | 精品久久久久久中文字幕 | 久久成人综合 | 国产精选视频在线观看 | 成年人黄色录像 | 青娱乐自拍视频 | 在线色| 中日韩在线播放 | 亚洲成人7777| www.中文字幕在线观看 | 羞羞的铁拳在线观看 | 日韩在线视频网站 | 欧美日韩黄色 | 青草国产| 免费午夜影院 | 亚洲激情视频网 | 在线播放视频高清在线观看 | 亚洲欧美一区二区三区在线 | 国产农村乱色xxxx | 成人综合久久 | www.成人av| 成年人网av毛片 | 二区三区偷拍浴室洗澡视频 | exo妈妈mv在线播放高清免费 | 国产亚洲精品久久久久久青梅 | 噜噜噜av| 福利在线视频导航 | 欧美日韩五区 | 日韩国产欧美视频 | 性猛交xxxx乱大交孕妇2十 | 一级片aaaa | 一区二区免费在线视频 | 国产免费av一区二区 | 激情欧美成人 | 永久黄网站 | 黄在线免费 | 情侣在线视频 | 欧美日韩中文在线观看 | 日韩美一区二区 | 国产精品久久久久久久久久东京 | 日韩欧美三级在线 | 欧美寡妇性猛交ⅹxxx | www.奇米.com | 69堂视频 | 999xxxxx| 啪啪五月天 | 一级特黄特色的免费大片视频 | 国产精品不卡一区 | 成年人午夜视频 | 国产精品99久久久久久人免费 | 在线精品视频播放 | 欧美69av| 91丨porny丨| 一级片免费看视频 | 国产网红主播三级精品视频 | 全部免费毛片 | 在线视频一区二区 | 日本久久久久久久久久 | 亚洲男人的天堂在线播放 | 国产在线成人精品午夜 | 日韩无马 | 成人欧美一区二区三区黑人孕妇 | 久久综合在线 | 国内自拍视频在线观看 | 国产精品久久久久久无人区 | 尤物视频在线观看免费 | 成年人免费在线观看视频网站 | eeuss一区| 日批视频在线 | 精品综合久久 | 亚洲看看 | 婷婷激情六月 | 狠狠狠狠狠| 欧美激情图区 | 久久久噜噜噜久久久白丝袜 | 久久久久夜色精品国产老牛91 | 另类综合在线 | 天天干干 | av一区在线观看 | 欧美一级在线观看 | 国产精品国产三级国产普通话对白 | 精品视频一区二区在线观看 | 日韩中文字幕精品视频 | 伊人婷婷综合 | 亚洲一区在线视频 | 在线永久看片免费的视频 | 性高跟鞋xxxxhd人妖 | 泽村玲子在线 | 日本高清在线观看 | 亚洲逼院| 一区二区三区四区视频在线观看 | 久久黄色片 | 国产伦理吴梦梦伦理 | 九九热在线视频观看 | 国产www视频 | 国内精品福利视频 | 国内久久久久 | 成人激情小视频 | 毛片com | 亚洲天堂免费观看 | 日韩免费高清视频网站 | 午夜av一区二区三区 | av一级久久| se日韩| 亚洲欧美日韩一区二区三区四区 | 免费日批视频 | 一区二区视频在线 | 日韩精品无 | 亚洲一区二区久久 | 国产露脸8mav| 懂色av蜜臀av粉嫩av分享吧 | 黄色在线免费网站 | 成人在线激情视频 | 手机在线成人av | 污视频在线观看网站 | 亚洲精品一级 | 午夜影院视频 | 亚色中文 | 香蕉在线视频免费 | 91视频在线观看视频 | 伊伊总综合网 | 亚洲一区二区三区乱码aⅴ 最新国产在线拍揄自揄视频 | jizz97| 色综合激情 | 青青综合网 | 久久网页 | 久久精品高清 | 久久久午夜精品福利内容 | 欧美成年人网站 | 日本一级淫片免费放 | 国产让女高潮的av毛片 | 一级片在线免费 | 有码在线| 少妇在线 | 欧美日韩亚洲激情 | 五月亚洲综合 | 超碰cc| 欧美日韩四区 | 成人欧美在线视频 | 久久aⅴ国产欧美74aaa | 国内精品视频在线 | 国语对白| 久久婷婷国产综合尤物精品 | 91av在线看 | 久久视频一区二区 | 国产一级片一区 | 欧美自拍第一页 | 伊人天天| 欧美第一色 | 88xxav| www.亚洲.com| 日韩午夜免费视频 | 91丨porny| 香蕉视频免费在线看 | av大片在线免费观看 | 欧美疯狂做受 | 免费成人深夜夜视频 | 不卡黄色| 欧美精品久久久久性色 | 亚洲精品77777 | 91香蕉国产在线观看软件 | re久久 | 成人爽爽爽 | 91精品免费看 | 伊人爱爱网 | 爱如潮水3免费观看日本高清 | 成人福利社 | 五月激情六月丁香 | 久天堂 | 在线看的av | 欧美性大战久久久久久久蜜桃 | 我要看18毛片| 污污在线观看视频 | 欧美日韩高清免费 | www.三级| 国产精品二区在线观看 | av网站在线免费看 | av男人资源 | 中文字幕在线精品 | 欧美三级韩国三级日本三斤在线观看 | 91麻豆精品国产91久久 | 一级片观看 | 国产日韩精品一区二区三区在线 | 自拍亚洲综合 | 国产精品高潮呻吟久久久 | 欧美精品免费在线观看 | 在线免费观看av网站 | 夜夜操女人 | 中文久久久 | 国产最新自拍 | 操穴网站 | 污污视频在线看 | 调教撅屁股啪调教打臀缝av | 中文字幕亚洲精品一区 | 丁香六月天婷婷 | 在线观看国产欧美 | 精品久久久久国产免费第一页 | 国产日韩成人 | 成人免费片| 黄色一级免费视频 | 国产亚洲视频在线观看 | 曰韩精品 | 欧美人与性动交α欧美精品 | www.我爱av| 在线中文字幕网站 | 亚洲综合站 | 国产三级理论 | 日韩激情一区二区三区 | 888夜夜爽夜夜躁精品 | 亚洲伊人一区二区 | 日本欧美黄色 | 视频精品一区二区 | 一级片一级| 五月婷中文字幕 | 国产激情在线免费观看 | 亚洲无卡视频 | 午夜精品一区二区三区免费视频 | 久久久一本精品99久久精品66 | 色播av | 国产91九色 | 日本理伦片午夜理伦片 | 免费在线看视频 | 中文字幕第一页久久 | 狠狠操麻豆 | 夜夜艹日日艹 | 在线观看欧美一区二区三区 | 亚洲视频一二 | 欧美精品久久久久久久多人混战 | 日本性久久| 亚洲综合小说 | 日韩欧美在线不卡 | 亚洲粉嫩 | 中文字幕在线观看网址 | 国产又黄又粗又猛又爽 | 伊人青青操 | 插插影视 | 高级毛片| 伊人久久免费视频 | 在线观看h网站 | av一卡| 夜夜撸 | 91在线无精精品一区二区 | 久久成人激情 | 麻豆va| 96看片| 日本视频免费观看 | 亚洲网址| 91视频导航 | jlzzjlzz欧美大全 | 中文字幕一区二区三区视频 | 蜜桃av噜噜一区二区三区麻豆 | 亚洲精品久久久久久国产精华液 | 日韩欧美亚洲一区二区三区 | 色午夜视频 | 成人综合av | 超碰在线看 | 99精品久久久久久中文字幕 | 在线中文字幕观看 | 久久免费黄色 | 放几个免费的毛片出来看 | 青青草免费在线观看视频 | 露脸丨91丨九色露脸 | 色很久 | 一区二区激情 | 黄瓜视频在线观看 | 亚洲精品av在线 | 精品一区在线播放 | av免费在线观 | 国产女同在线观看 | 欧美日韩中文字幕一区二区三区 | 国产高潮视频 | 亚洲性激情 | 污视频在线观看网站 | av资源站最新av | 亚洲不卡在线视频 | 国产一级理论片 | 九久久久久 | 在线久草 | 久久久最新地址 | 九九视频免费在线观看 | 天天综合永久 | 久久爱网| 亚洲一区二区精品在线 | 免费毛片在线播放免费 | www.天天操.com| 久久香蕉国产 | 欧美嫩草| 亚洲一区二区三区黄色 | 国产精品成人久久 | 日韩中文字幕一区二区 | 99视频 | 一级做a爱片性色毛片www | 日韩欧美一区二区三区久久婷婷 | 91精品国产综合久久久蜜臀九色 | 91麻豆产精品久久久久久 | 国产美女精品视频国产 | 99久久国产视频 | 黄色日皮网站 | 成人av自拍 | 91丝袜一区在线观看 | 亚洲一区 视频 | 久草免费在线观看视频 | 一本色道综合久久欧美日韩精品 | 激情中文网 | 亚洲精品激情 | 久久久久99精品国产片 | 日韩成人av在线 | 国产一级精品毛片 | 中文字幕_第2页_高清免费在线 | 精品美女www爽爽爽视频 | 国产在线自 | 亚洲欧美日韩国产一区二区 | 伊人网狠狠干 | caopor超碰| 99久久一区二区 | 人人干人人爽 | 亚洲国产成人av毛片大全 | 超碰人人插 | 亚洲天堂小视频 | 成人在线免费观看网站 | 97在线观视频免费观看 | 久久久免费av | 日日操狠狠操 | 日韩一区在线播放 | 老司机亚洲 | 国产激情在线 | 日本不卡免费 | 国产露脸91国语对白 | 成人欧美一区二区三区白人 | 中文字幕永久在线视频 | 国产精品日韩欧美大师 | 蕾丝视频污 | 玖玖在线免费视频 | 久久久久亚洲天堂 | 欧美高清一区 | 欧美一级视频免费 | 国产成人久久精品 | 在线免费观看国产视频 | 欧美黄色大片视频 | 久草黄色| 这里只有精品99re | 成人福利在线播放 | 国产激情一区二区三区 | 成人国产精品蜜柚视频 | av视屏在线 | 亚洲综合小说区 | 国产高清99 | 成人黄色免费在线观看 | 三级影片在线播放 | 人人干干 | 婷婷六月丁 | 激情视频一区二区三区 | 欧美天堂在线 | 99视频热| 久久久精品视频网站 | 自拍视频第一页 | 欧美黄色一级网站 | 午夜国产片 | 亚洲欧美日韩在线不卡 | 精品国产美女 | 久久在线看| 国产精品久久久久久久久久免费看 | 久久精品国产一区二区 | 午夜999| igao国产精品 | 亚洲成人av免费在线观看 | 瑟瑟综合网 | 日本a在线播放 | 国产在线伊人 | 黄色大片网站视频 | 狠狠干影视 | 国产网址视频 | 九九少妇 | 一级片视频在线 | 成人永久免费 | 国产午夜伦理 | 九九精品免费 | 亚洲高清视频免费观看 | 日韩免费av网站 | 91看片免费| 欧美在线视频播放 | 69性影院| 五月天综合激情网 | 欧美大片一区二区三区 | 在线观看aaa | 潘金莲一级淫片aaaaaa播放 | 九月婷婷网| 国产黑人| 欧美爽爽爽| 黄片毛片视频 | fc2成人免费人成在线观看播放 | 一本不卡 | 最新中文字幕av专区 | 一区二区三区免费观看视频 | 一卡二卡三卡在线观看 | 日韩一级二级三级 | 在线国产三级 | 毛片在线免费观看网站 | 欧美极品在线观看 | 国产aa| 99久久免费精品 | 在线欧美日韩 | 欧美特级黄色 | 欧美一级片免费观看 | 成人午夜在线观看视频 | 亚洲最大激情网 | 国产毛片毛片毛片毛片 | 中文字幕在线免费 | 久久久伊人网 |