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

詳解vue中router-view組件的生成原理

 更新時(shí)間:2024年01月19日 08:25:34   作者:唐朝人  
在vue的使用過程中,有一個(gè)組件,幾乎是必用的,那就是router-view,它是所有組件的入口,是單頁面系統(tǒng)的一把利劍,如果你的系統(tǒng)是火箭,那么router-view無疑將是這艘火箭的北斗衛(wèi)星,本文將給大家介紹vue中的router-view組件是如何生成的,感興趣的朋友可以參考下

前言

在vue的使用過程中,有一個(gè)組件,幾乎是必用的,那就是router-view。它是所有組件的入口,是單頁面系統(tǒng)的一把利劍。如果你的系統(tǒng)是火箭,那么router-view無疑將是這艘火箭的北斗衛(wèi)星。

router-view

< router-view />是 vue-router 默認(rèn)注冊(cè)的全局組件。如果你從0搭建過系統(tǒng)的話,一定記得在Layout或者AppMain組件中有過這樣一行代碼:

 <transition name="fade-transform" mode="out-in">
    <div style="height: 100%">
    // 所有組件的入口
      <router-view />
    </div>
</transition>

我們一直在用,但是有沒有想過:這個(gè)組件是干嘛用的?為什么注冊(cè)為全局組件,又為什么是所有頁面組件的入口?它……究竟有什么用?

帶著這樣的疑問,我打開了 vue-router 的gitHub切換到 vue2 分支

然后 在 src->components->view.ts 中找到了 router-view 的相關(guān)代碼:

下面來分析一下這個(gè)組件的源碼,看一下 vue-router 是怎么設(shè)計(jì)這個(gè)組件的,以及這種設(shè)計(jì)帶給我們的思考有哪些?

為了便于理解,我將這段源碼粘貼下來:

// @ts-nocheck

import { Component } from 'vue'

const View: Component = {
  name: 'RouterView',
  functional: true,

  props: {
    name: {
      type: String,
      default: 'default',
    },
  },

  render(_, { children, parent, data, props }) {
    data.routerView = true
    const h = parent.$createElement
    const route = parent.$route

    // determine current view depth, also check to see if the tree
    // has been toggled inactive but kept-alive.
    let depth = 0
    // let inactive = false
    // @ts-ignore
    while (parent && parent._routerRoot !== parent) {
      const vnodeData = parent.$vnode && parent.$vnode.data
      if (vnodeData) {
        // @ts-ignore
        if (vnodeData.routerView) {
          depth++
        }
        // if (vnodeData.keepAlive && parent._inactive) {
        //   inactive = true
        // }
      }
      parent = parent.$parent
    }
    data.routerViewDepth = depth
    const matched = route.matched[depth]
    if (!matched) return h()

    const component = matched.components[props.name]

    return h(component, data, children)
  },
}

export default View
  • 引入依賴

引入 vue 中的 component 組件,然后注冊(cè)一個(gè) name 為 RouterView 的組件,這里的functional:true 表示這個(gè)組件是一個(gè)函數(shù)式組件。

import { Component } from 'vue'
const View: Component = {
  name: 'RouterView',
  functional: true,

  props: {
    name: {
      type: String,
      default: 'default',
    },
  }

組件內(nèi)部定義了一個(gè) props,接受參數(shù) name。一般情況下,router-view 很少傳 name,所以這個(gè) 參數(shù)可以忽略

  • render函數(shù)的參數(shù)通過解構(gòu)賦值拿到組件內(nèi)部屬性

我們?cè)?nbsp;render 中拿到了 children、parent、data、props 等屬性。在 parent 中我們?nèi)〉搅?nbsp;$createElement 內(nèi)部方法,以及 route 路由信息,然后定義了一個(gè) depth 變量,并初始賦值為 0。

render(_, { children, parent, data, props }) {
    data.routerView = true
    const h = parent.$createElement
    const route = parent.$route

    // determine current view depth, also check to see if the tree
    // has been toggled inactive but kept-alive.
    let depth = 0 

這個(gè) depth 意義重大!一開始我也在疑惑,vueRouter 在設(shè)計(jì)時(shí)為什么要有這 個(gè) depth,這個(gè)變量有什么用?

后來仔細(xì)翻看了代碼,發(fā)現(xiàn) depth 記錄了每一條路由的索引,然后又將該索引賦值給$vnode->data->routerViewDepth

// has been toggled inactive but kept-alive.
    let depth = 0
    // let inactive = false
    // @ts-ignore
    while (parent && parent._routerRoot !== parent) {
      const vnodeData = parent.$vnode && parent.$vnode.data
      if (vnodeData) {
        // @ts-ignore
        if (vnodeData.routerView) {
          depth++
        }
        // if (vnodeData.keepAlive && parent._inactive) {
        //   inactive = true
        // }
      }
      parent = parent.$parent
    }
    data.routerViewDepth = depth
    const matched = route.matched[depth]

注意看:routerViewDepth 就是這個(gè) depth 值。

可是,routerViewDepth 只是記錄了這個(gè)值而已,depth 難道沒有其他作用了嗎?當(dāng)然不是,如果僅僅是記錄一個(gè)索引值,但就沒必要大動(dòng)干戈地調(diào)用 while 循環(huán)深度遍歷了。所以,我們繼續(xù)往下看:

    const matched = route.matched[depth]
    if (!matched) return h()

    const component = matched.components[props.name]

    return h(component, data, children)

在當(dāng)前路由下,有個(gè) route 對(duì)象,里面記錄了頁面的基本信息。其中有一個(gè) matched 屬性至關(guān)重要,它是一個(gè) components 集合。也就是說,在當(dāng)前路由下的所有組件(包括父級(jí) 組件以及兄弟組件),都存在于這個(gè) matched 集合里。

而 depth 是當(dāng)前路由的索引,也就是 matched 集合中的 key。通過 depth 我們能對(duì)應(yīng)到路由中對(duì)應(yīng)好的 component。

所以我們前面為什么說depth 意義重大,原因就在這里。

const matched = route.matched[depth]
    if (!matched) return h()

    const component = matched.components[props.name]

    return h(component, data, children)

最后,源碼中增加了一層判斷,如果沒有找到 matched 則返回一個(gè)空的 vnode,如果找到了則返回對(duì)應(yīng)的 component,最后完成渲染。

matched

matched 集合是從路由記錄樹中根據(jù)當(dāng)前路由的路徑生成的。當(dāng)發(fā)生路由導(dǎo)航時(shí),Vue Router 會(huì)遍歷路由配置,并根據(jù)當(dāng)前路徑匹配對(duì)應(yīng)的路由記錄。這個(gè)過程是自動(dòng)完成的,無需手動(dòng)操作。

例如:假設(shè)你的路由如下:

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    children:[
       {
        path: '/about',
        name: 'About',
        component: About,
      },
    ]
  },
 
  // ...
];

當(dāng)訪問 /about 路徑時(shí),Vue Router 會(huì)生成一個(gè) matched數(shù)組,其中包含與當(dāng)前路徑 /about匹配的路由記錄。在這種情況下,matched數(shù)組可能如下所示:

[
  {
    name:'Home',
    alias: xx,
    beforeEnter: (...),
    components: Object,
    enteredCbs: (...),
    instances: (...),
    matchAs: (...),
    meta: (...),
    xxx
  },
  {
    alias: xx,
    name:'About',
    beforeEnter: (...),
    components: Object,
    enteredCbs: (...),
    instances: (...),
    matchAs: (...),
    meta: (...),
    xxx
  },
]

matched數(shù)組的順序是根據(jù)路由配置的嵌套關(guān)系確定的,父級(jí)路由記錄在數(shù)組中的順序靠前。

注意,matched數(shù)組是在路由導(dǎo)航過程中生成的,因此在路由導(dǎo)航之前或?qū)Ш降轿炊x的路徑時(shí),matched 數(shù)組可能為空。

可以通過在路由組件中訪問 this.$route.matched 來獲取當(dāng)前路由的匹配路由記錄數(shù)組。

總結(jié)

雖然現(xiàn)在已經(jīng)進(jìn)入了 vue3 的世界,但是 vue2 源碼中的諸多設(shè)計(jì)仍然值得我們借鑒,技術(shù)始終服務(wù)于業(yè)務(wù)。相信現(xiàn)在不少公司仍然有大量的 vue2 項(xiàng)目在維護(hù),推翻 shi 山,深度重構(gòu)不是一朝一夕的事。對(duì)于源碼,我們可以抱著學(xué)習(xí)的態(tài)度去看待,或者看成是一種興趣。源碼看多了,你的代碼不會(huì)再 shi,在不知不覺中逐漸向優(yōu)秀的人靠齊。

以上就是詳解vue中的router-view組件是如何生成的的詳細(xì)內(nèi)容,更多關(guān)于vue router-view組件生成的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • el-select 的下拉框中新增倆自定義按鈕的操作方法

    el-select 的下拉框中新增倆自定義按鈕的操作方法

    文章介紹了在Element UI的el-select組件中新增自定義按鈕的方法,并詳細(xì)說明了設(shè)置`popper-append-to-body`屬性為false的重要性,以及如何通過修改樣式來實(shí)現(xiàn)自定義按鈕的添加和樣式效果展示,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • Vue兩個(gè)通信方式與動(dòng)畫過度及混入使用介紹

    Vue兩個(gè)通信方式與動(dòng)畫過度及混入使用介紹

    最近在寫vue的一個(gè)項(xiàng)目要實(shí)現(xiàn)過渡的效果,雖然vue動(dòng)畫不是強(qiáng)項(xiàng),庫也多,但是基本的坑還是得踩扎實(shí),下面這篇文章主要給大家介紹了關(guān)于Vue中實(shí)現(xiàn)過渡動(dòng)畫效果的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • Vue響應(yīng)式原理及雙向數(shù)據(jù)綁定示例分析

    Vue響應(yīng)式原理及雙向數(shù)據(jù)綁定示例分析

    這篇文章主要為大家介紹了Vue響應(yīng)式原理及雙向數(shù)據(jù)綁定的示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • vue 函數(shù)調(diào)用加括號(hào)與不加括號(hào)的區(qū)別

    vue 函數(shù)調(diào)用加括號(hào)與不加括號(hào)的區(qū)別

    這篇文章主要介紹了vue 函數(shù)調(diào)用加括號(hào)與不加括號(hào)的區(qū)別,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下
    2020-10-10
  • axios解決高并發(fā)的方法:axios.all()與axios.spread()的操作

    axios解決高并發(fā)的方法:axios.all()與axios.spread()的操作

    這篇文章主要介紹了axios解決高并發(fā)的方法:axios.all()與axios.spread()的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Vue3?響應(yīng)式高階用法之customRef()的使用

    Vue3?響應(yīng)式高階用法之customRef()的使用

    customRef()是Vue3的高級(jí)工具,允許開發(fā)者創(chuàng)建具有復(fù)雜依賴跟蹤和自定義更新邏輯的ref對(duì)象,本文詳細(xì)介紹了customRef()的使用場景、基本用法、功能詳解以及最佳實(shí)踐,包括防抖、異步更新等用例,旨在幫助開發(fā)者更好地理解和使用這一強(qiáng)大功能
    2024-09-09
  • VUE開發(fā)一個(gè)圖片輪播的組件示例代碼

    VUE開發(fā)一個(gè)圖片輪播的組件示例代碼

    本篇文章主要介紹了VUE開發(fā)一個(gè)圖片輪播的組件示例代碼,對(duì)圖片輪播效果感興趣的小伙伴們可以參考一下。
    2017-03-03
  • Vue組件通信的幾種實(shí)現(xiàn)方法

    Vue組件通信的幾種實(shí)現(xiàn)方法

    這篇文章主要介紹了Vue組件通信的幾種實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Vue利用路由鉤子token過期后跳轉(zhuǎn)到登錄頁的實(shí)例

    Vue利用路由鉤子token過期后跳轉(zhuǎn)到登錄頁的實(shí)例

    下面小編就為大家?guī)硪黄猇ue利用路由鉤子token過期后跳轉(zhuǎn)到登錄頁的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • vue+elementui通用彈窗的實(shí)現(xiàn)(新增+編輯)

    vue+elementui通用彈窗的實(shí)現(xiàn)(新增+編輯)

    這篇文章主要介紹了vue+elementui通用彈窗的實(shí)現(xiàn)(新增+編輯),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評(píng)論