亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

從vue-router看前端路由的兩種實現(xiàn)

 更新時間:2021年05月10日 08:40:00   作者:喵了個咪同學  
本文由淺入深觀摩vue-router源碼是如何通過hash與History interface兩種方式實現(xiàn)前端路由,介紹了相關原理,并對比了兩種方式的優(yōu)缺點與注意事項。最后分析了如何實現(xiàn)可以直接從文件系統(tǒng)加載而不借助后端服務器的Vue單頁應用。

隨著前端應用的業(yè)務功能越來越復雜、用戶對于使用體驗的要求越來越高,單頁應用(SPA)成為前端應用的主流形式。大型單頁應用最顯著特點之一就是采用前端路由系統(tǒng),通過改變URL,在不重新請求頁面的情況下,更新頁面視圖。

“更新視圖但不重新請求頁面”是前端路由原理的核心之一,目前在瀏覽器環(huán)境中這一功能的實現(xiàn)主要有兩種方式:

  • 利用URL中的hash(“#”)
  • 利用History interface在 HTML5中新增的方法

vue-router是Vue.js框架的路由插件,下面我們從它的源碼入手,邊看代碼邊看原理,由淺入深觀摩vue-router是如何通過這兩種方式實現(xiàn)前端路由的。

模式參數(shù)

在vue-router中是通過mode這一參數(shù)控制路由的實現(xiàn)模式的:

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

創(chuàng)建VueRouter的實例對象時,mode以構(gòu)造函數(shù)參數(shù)的形式傳入。帶著問題閱讀源碼,我們就可以從VueRouter類的定義入手。一般插件對外暴露的類都是定義在源碼src根目錄下的index.js文件中,打開該文件,可以看到VueRouter類的定義,摘錄與mode參數(shù)有關的部分如下:

export default class VueRouter {
  
  mode: string; // 傳入的字符串參數(shù),指示history類別
  history: HashHistory | HTML5History | AbstractHistory; // 實際起作用的對象屬性,必須是以上三個類的枚舉
  fallback: boolean; // 如瀏覽器不支持,'history'模式需回滾為'hash'模式
  
  constructor (options: RouterOptions = {}) {
    
    let mode = options.mode || 'hash' // 默認為'hash'模式
    this.fallback = mode === 'history' && !supportsPushState // 通過supportsPushState判斷瀏覽器是否支持'history'模式
    if (this.fallback) {
      mode = 'hash'
    }
    if (!inBrowser) {
      mode = 'abstract' // 不在瀏覽器環(huán)境下運行需強制為'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}`)
        }
    }
  }

  init (app: any /* Vue component instance */) {
    
    const history = this.history

    // 根據(jù)history的類別執(zhí)行相應的初始化操作和監(jiān)聽
    if (history instanceof HTML5History) {
      history.transitionTo(history.getCurrentLocation())
    } else if (history instanceof HashHistory) {
      const setupHashListener = () => {
        history.setupListeners()
      }
      history.transitionTo(
        history.getCurrentLocation(),
        setupHashListener,
        setupHashListener
      )
    }

    history.listen(route => {
      this.apps.forEach((app) => {
        app._route = route
      })
    })
  }

  // VueRouter類暴露的以下方法實際是調(diào)用具體history對象的方法
  push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    this.history.push(location, onComplete, onAbort)
  }

  replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    this.history.replace(location, onComplete, onAbort)
  }
}

可以看出:

作為參數(shù)傳入的字符串屬性mode只是一個標記,用來指示實際起作用的對象屬性history的實現(xiàn)類,兩者對應關系如下:

mode history hash abstract
history HTML5History HashHistory AbstractHistory

在初始化對應的history之前,會對mode做一些校驗:若瀏覽器不支持HTML5History方式(通過supportsPushState變量判斷),則mode強制設為'hash';若不是在瀏覽器環(huán)境下運行,則mode強制設為'abstract'

VueRouter類中的onReady(), push()等方法只是一個代理,實際是調(diào)用的具體history對象的對應方法,在init()方法中初始化時,也是根據(jù)history對象具體的類別執(zhí)行不同操作

在瀏覽器環(huán)境下的兩種方式,分別就是在HTML5History,HashHistory兩個類中實現(xiàn)的。他們都定義在src/history文件夾下,繼承自同目錄下base.js文件中定義的History類。History中定義的是公用和基礎的方法,直接看會一頭霧水,我們先從HTML5History,HashHistory兩個類中看著親切的push(), replace()方法的說起。

HashHistory

看源碼前先回顧一下原理:

hash(“#”)符號的本來作用是加在URL中指示網(wǎng)頁中的位置:

www.example.com/index.html#…

#符號本身以及它后面的字符稱之為hash,可通過window.location.hash屬性讀取。它具有如下特點:

  • hash雖然出現(xiàn)在URL中,但不會被包括在HTTP請求中。它是用來指導瀏覽器動作的,對服務器端完全無用,因此,改變hash不會重新加載頁面
  • 可以為hash的改變添加監(jiān)聽事件:
window.addEventListener("hashchange", funcRef, false)

每一次改變hash(window.location.hash),都會在瀏覽器的訪問歷史中增加一個記錄

利用hash的以上特點,就可以來實現(xiàn)前端路由“更新視圖但不重新請求頁面”的功能了。

HashHistory.push()

我們來看HashHistory中的push()方法:

push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  this.transitionTo(location, route => {
    pushHash(route.fullPath)
    onComplete && onComplete(route)
  }, onAbort)
}

function pushHash (path) {
  window.location.hash = path
}

transitionTo()方法是父類中定義的是用來處理路由變化中的基礎邏輯的,push()方法最主要的是對window的hash進行了直接賦值:

window.location.hash = route.fullPath

hash的改變會自動添加到瀏覽器的訪問歷史記錄中。

那么視圖的更新是怎么實現(xiàn)的呢,我們來看父類History中transitionTo()方法的這么一段:

transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  const route = this.router.match(location, this.current)
  this.confirmTransition(route, () => {
    this.updateRoute(route)
    ...
  })
}

updateRoute (route: Route) {
  
  this.cb && this.cb(route)
  
}

listen (cb: Function) {
  this.cb = cb
}

可以看到,當路由變化時,調(diào)用了History中的this.cb方法,而this.cb方法是通過History.listen(cb)進行設置的?;氐絍ueRouter類定義中,找到了在init()方法中對其進行了設置:

init (app: any /* Vue component instance */) {
    
  this.apps.push(app)

  history.listen(route => {
    this.apps.forEach((app) => {
      app._route = route
    })
  })
}

根據(jù)注釋,app為Vue組件實例,但我們知道Vue作為漸進式的前端框架,本身的組件定義中應該是沒有有關路由內(nèi)置屬性_route,如果組件中要有這個屬性,應該是在插件加載的地方,即VueRouter的install()方法中混合入Vue對象的,查看install.js源碼,有如下一段:

export function install (Vue) {
  
  Vue.mixin({
    beforeCreate () {
      if (isDef(this.$options.router)) {
        this._router = this.$options.router
        this._router.init(this)
        Vue.util.defineReactive(this, '_route', this._router.history.current)
      }
      registerInstance(this, this)
    },
  })
}

通過Vue.mixin()方法,全局注冊一個混合,影響注冊之后所有創(chuàng)建的每個 Vue 實例,該混合在beforeCreate鉤子中通過Vue.util.defineReactive()定義了響應式的_route屬性。所謂響應式屬性,即當_route值改變時,會自動調(diào)用Vue實例的render()方法,更新視圖。

總結(jié)一下,從設置路由改變到視圖更新的流程如下:

$router.push() --> HashHistory.push() --> History.transitionTo() --> History.updateRoute() --> {app._route = route} --> vm.render()

HashHistory.replace()

replace()方法與push()方法不同之處在于,它并不是將新路由添加到瀏覽器訪問歷史的棧頂,而是替換掉當前的路由:

replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  this.transitionTo(location, route => {
    replaceHash(route.fullPath)
    onComplete && onComplete(route)
  }, onAbort)
}
  
function replaceHash (path) {
  const i = window.location.href.indexOf('#')
  window.location.replace(
    window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path
  )
}

可以看出,它與push()的實現(xiàn)結(jié)構(gòu)上基本相似,不同點在于它不是直接對window.location.hash進行賦值,而是調(diào)用window.location.replace方法將路由進行替換。

監(jiān)聽地址欄

以上討論的VueRouter.push()和VueRouter.replace()是可以在vue組件的邏輯代碼中直接調(diào)用的,除此之外在瀏覽器中,用戶還可以直接在瀏覽器地址欄中輸入改變路由,因此VueRouter還需要能監(jiān)聽瀏覽器地址欄中路由的變化,并具有與通過代碼調(diào)用相同的響應行為。在HashHistory中這一功能通過setupListeners實現(xiàn):

setupListeners () {
  window.addEventListener('hashchange', () => {
    if (!ensureSlash()) {
      return
    }
    this.transitionTo(getHash(), route => {
      replaceHash(route.fullPath)
    })
  })
}

該方法設置監(jiān)聽了瀏覽器事件hashchange,調(diào)用的函數(shù)為replaceHash,即在瀏覽器地址欄中直接輸入路由相當于代碼調(diào)用了replace()方法

HTML5History

History interface是瀏覽器歷史記錄棧提供的接口,通過back(), forward(), go()等方法,我們可以讀取瀏覽器歷史記錄棧的信息,進行各種跳轉(zhuǎn)操作。

從HTML5開始,History interface提供了兩個新的方法:pushState(), replaceState()使得我們可以對瀏覽器歷史記錄棧進行修改:

window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
  • stateObject: 當瀏覽器跳轉(zhuǎn)到新的狀態(tài)時,將觸發(fā)popState事件,該事件將攜帶這個stateObject參數(shù)的副本
  • title: 所添加記錄的標題
  • URL: 所添加記錄的URL

這兩個方法有個共同的特點:當調(diào)用他們修改瀏覽器歷史記錄棧后,雖然當前URL改變了,但瀏覽器不會立即發(fā)送請求該URL(the browser won't attempt to load this URL after a call to pushState()),這就為單頁應用前端路由“更新視圖但不重新請求頁面”提供了基礎。

我們來看vue-router中的源碼:

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 (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)
}

// src/util/push-state.js
export function pushState (url?: string, replace?: boolean) {
  saveScrollPosition()
  // try...catch the pushState call to get around Safari
  // DOM Exception 18 where it limits to 100 pushState calls
  const history = window.history
  try {
    if (replace) {
      history.replaceState({ key: _key }, '', url)
    } else {
      _key = genKey()
      history.pushState({ key: _key }, '', url)
    }
  } catch (e) {
    window.location[replace ? 'replace' : 'assign'](url)
  }
}

export function replaceState (url?: string) {
  pushState(url, true)
}

代碼結(jié)構(gòu)以及更新視圖的邏輯與hash模式基本類似,只不過將對window.location.hash直接進行賦值window.location.replace()改為了調(diào)用history.pushState()和history.replaceState()方法。

在HTML5History中添加對修改瀏覽器地址欄URL的監(jiān)聽是直接在構(gòu)造函數(shù)中執(zhí)行的:

constructor (router: Router, base: ?string) {
  
  window.addEventListener('popstate', e => {
    const current = this.current
    this.transitionTo(getLocation(this.base), route => {
      if (expectScroll) {
        handleScroll(router, route, current, true)
      }
    })
  })
}

當然了HTML5History用到了HTML5的新特特性,是需要特定瀏覽器版本的支持的,前文已經(jīng)知道,瀏覽器是否支持是通過變量supportsPushState來檢查的:

// src/util/push-state.js
export const supportsPushState = inBrowser && (function () {
  const ua = window.navigator.userAgent

  if (
    (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
    ua.indexOf('Mobile Safari') !== -1 &&
    ua.indexOf('Chrome') === -1 &&
    ua.indexOf('Windows Phone') === -1
  ) {
    return false
  }

  return window.history && 'pushState' in window.history
})()

以上就是hash模式與history模式源碼的導讀,這兩種模式都是通過瀏覽器接口實現(xiàn)的,除此之外vue-router還為非瀏覽器環(huán)境準備了一個abstract模式,其原理為用一個數(shù)組stack模擬出瀏覽器歷史記錄棧的功能。當然,以上只是一些核心邏輯,為保證系統(tǒng)的魯棒性,源碼中還有大量的輔助邏輯,也很值得學習。此外在vue-router中還有路由匹配、router-view視圖組件等重要部分

兩種模式比較

在一般的需求場景中,hash模式與history模式是差不多的,但幾乎所有的文章都推薦使用history模式,理由竟然是:"#" 符號太丑...0_0 "

如果不想要很丑的 hash,我們可以用路由的 history 模式 ——官方文檔

當然,嚴謹?shù)奈覀兛隙ú粦撚妙佒翟u價技術的好壞。根據(jù)MDN的介紹,調(diào)用history.pushState()相比于直接修改hash主要有以下優(yōu)勢:

  • pushState設置的新URL可以是與當前URL同源的任意URL;而hash只可修改#后面的部分,故只可設置與當前同文檔的URL
  • pushState設置的新URL可以與當前URL一模一樣,這樣也會把記錄添加到棧中;而hash設置的新值必須與原來不一樣才會觸發(fā)記錄添加到棧中
  • pushState通過stateObject可以添加任意類型的數(shù)據(jù)到記錄中;而hash只可添加短字符串
  • pushState可額外設置title屬性供后續(xù)使用

history模式的一個問題

我們知道對于單頁應用來講,理想的使用場景是僅在進入應用時加載index.html,后續(xù)在的網(wǎng)絡操作通過Ajax完成,不會根據(jù)URL重新請求頁面,但是難免遇到特殊情況,比如用戶直接在地址欄中輸入并回車,瀏覽器重啟重新加載應用等。

hash模式僅改變hash部分的內(nèi)容,而hash部分是不會包含在HTTP請求中的:

http://oursite.com/#/user/id   // 如重新請求只會發(fā)送http://oursite.com/

故在hash模式下遇到根據(jù)URL請求頁面的情況不會有問題。

而history模式則會將URL修改得就和正常請求后端的URL一樣

http://oursite.com/user/id

在此情況下重新向后端發(fā)送請求,如后端沒有配置對應/user/id的路由處理,則會返回404錯誤。官方推薦的解決辦法是在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。同時這么做以后,服務器就不再返回 404 錯誤頁面,因為對于所有路徑都會返回 index.html 文件。為了避免這種情況,在 Vue 應用里面覆蓋所有的路由情況,然后在給出一個 404 頁面?;蛘?,如果是用 Node.js 作后臺,可以使用服務端的路由來匹配 URL,當沒有匹配到路由的時候返回 404,從而實現(xiàn) fallback。

直接加載應用文件

Tip: built files are meant to be served over an HTTP server.

Opening index.html over file:// won't work.

Vue項目通過vue-cli的webpack打包完成后,命令行會有這么一段提示。通常情況,無論是開發(fā)還是線上,前端項目都是通過服務器訪問,不存在 "Opening index.html over file://" ,但程序員都知道,需求和場景永遠是千奇百怪的,只有你想不到的,沒有產(chǎn)品經(jīng)理想不到的。

本文寫作的初衷就是遇到了這樣一個問題:需要快速開發(fā)一個移動端的展示項目,決定采用WebView加載Vue單頁應用的形式,但沒有后端服務器提供,所以所有資源需從本地文件系統(tǒng)加載:

// AndroidAppWrapper
public class MainActivity extends AppCompatActivity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        webView = new WebView(this);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.loadUrl("file:///android_asset/index.html");
        setContentView(webView);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
            webView.goBack();
            return true;
        }
        return false;
    }
}

此情此景看來是必須 "Opening index.html over file://" 了,為此,我首先要進行了一些設置

  • 在項目config.js文件中將assetsPublicPath字段的值改為相對路徑 './'
  • 調(diào)整生成的static文件夾中圖片等靜態(tài)資源的位置與代碼中的引用地址一致

這是比較明顯的需要改動之處,但改完后依舊無法順利加載,經(jīng)過反復排查發(fā)現(xiàn),項目在開發(fā)時,router設置為了history模式(為了美觀...0_0"),當改為hash模式后就可正常加載了。

為什么會出現(xiàn)這種情況呢?我分析原因可能如下:

當從文件系統(tǒng)中直接加載index.html時,URL為:

file:///android_asset/index.html

而首頁視圖需匹配的路徑為path: '/' :

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'index',
      component: IndexView
    }
  ]
})

我們先來看history模式,在HTML5History中:

ensureURL (push?: boolean) {
  if (getLocation(this.base) !== this.current.fullPath) {
    const current = cleanPath(this.base + this.current.fullPath)
    push ? pushState(current) : replaceState(current)
  }
}

export function getLocation (base: string): string {
  let path = window.location.pathname
  if (base && path.indexOf(base) === 0) {
    path = path.slice(base.length)
  }
  return (path || '/') + window.location.search + window.location.hash
}

邏輯只會確保存在URL,path是通過剪切的方式直接從window.location.pathname獲取到的,它的結(jié)尾是index.html,因此匹配不到 '/' ,故 "Opening index.html over file:// won't work" 。

再看hash模式,在HashHistory中:

export class HashHistory extends History {
  constructor (router: Router, base: ?string, fallback: boolean) {
    ...
    ensureSlash()
  }

  // this is delayed until the app mounts
  // to avoid the hashchange listener being fired too early
  setupListeners () {
    window.addEventListener('hashchange', () => {
      if (!ensureSlash()) {
        return
      }
      ...
    })
  }

  getCurrentLocation () {
    return getHash()
  }
}

function ensureSlash (): boolean {
  const path = getHash()
  if (path.charAt(0) === '/') {
    return true
  }
  replaceHash('/' + path)
  return false
}

export function getHash (): string {
  const href = window.location.href
  const index = href.indexOf('#')
  return index === -1 ? '' : href.slice(index + 1)
}

我們看到在代碼邏輯中,多次出現(xiàn)一個函數(shù)ensureSlash(),當#符號后緊跟著的是'/',則返回true,否則強行插入這個'/',故我們可以看到,即使是從文件系統(tǒng)打開index.html,URL依舊會變?yōu)橐韵滦问剑?/p>

file:///C:/Users/dist/index.html#/

getHash()方法返回的path為 '/' ,可與首頁視圖的路由匹配。

故要想從文件系統(tǒng)直接加載Vue單頁應用而不借助后端服務器,除了打包后的一些路徑設置外,還需確保vue-router使用的是hash模式。

以上就是從vue-router看前端路由的兩種實現(xiàn)的詳細內(nèi)容,更多關于vue前端路由的兩種實現(xiàn)的資料請關注腳本之家其它相關文章!

相關文章

  • vue屬性props默認類型的寫法介紹

    vue屬性props默認類型的寫法介紹

    這篇文章主要介紹了vue屬性props默認類型的寫法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue封裝第三方插件并發(fā)布到npm的方法

    vue封裝第三方插件并發(fā)布到npm的方法

    本篇文章主要介紹了vue封裝第三方插件并發(fā)布到npm的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • Vue 路由返回恢復頁面狀態(tài)的操作方法

    Vue 路由返回恢復頁面狀態(tài)的操作方法

    在使用 Vue 開發(fā)前端的時候遇到一個場景在首頁進行一些數(shù)據(jù)搜索,點擊搜索結(jié)果進入詳情頁面,瀏覽詳情頁后返回主頁,所以需要在返回后恢復跳轉(zhuǎn)前的頁面參數(shù)狀態(tài),今天通過本文給大家分享Vue 路由頁面狀態(tài)返回的操作方法,一起看看吧
    2021-07-07
  • VueCli3中兼容IE11配置的艱苦歷程

    VueCli3中兼容IE11配置的艱苦歷程

    這篇文章主要介紹了VueCli3中兼容IE11配置的艱苦歷程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Vue.js實戰(zhàn)之利用vue-router實現(xiàn)跳轉(zhuǎn)頁面

    Vue.js實戰(zhàn)之利用vue-router實現(xiàn)跳轉(zhuǎn)頁面

    對于單頁應用,官方提供了vue-router進行路由跳轉(zhuǎn)的處理,這篇文章主要給大家介紹了Vue.js實戰(zhàn)之利用vue-router實現(xiàn)跳轉(zhuǎn)頁面的相關資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-04-04
  • Vue如何調(diào)用接口請求頭增加參數(shù)

    Vue如何調(diào)用接口請求頭增加參數(shù)

    這篇文章主要介紹了Vue如何調(diào)用接口請求頭增加參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • vue iview多張圖片大圖預覽、縮放翻轉(zhuǎn)

    vue iview多張圖片大圖預覽、縮放翻轉(zhuǎn)

    這篇文章主要為大家詳細介紹了vue iview多張圖片大圖預覽、縮放翻轉(zhuǎn),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Vue.js中的computed工作原理

    Vue.js中的computed工作原理

    這篇文章,我們通過實現(xiàn)一個簡單版的和Vue中computed具有相同功能的函數(shù)來了解computed是如何工作的。對Vue.js中的computed工作原理感興趣的朋友跟隨腳本之家小編一起學習吧
    2018-03-03
  • 淺談vue 組件中的setInterval方法和window的不同

    淺談vue 組件中的setInterval方法和window的不同

    這篇文章主要介紹了淺談vue 組件中的setInterval方法和window的不同,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • Vue3+Element?Plus實現(xiàn)動態(tài)標簽頁以及右鍵菜單功能

    Vue3+Element?Plus實現(xiàn)動態(tài)標簽頁以及右鍵菜單功能

    這篇文章主要給大家介紹了關于Vue3+Element?Plus實現(xiàn)動態(tài)標簽頁以及右鍵菜單功能的相關資料,Vue?3和Element?Plus提供了一種簡單的方法來實現(xiàn)側(cè)邊菜單欄與標簽頁之間的聯(lián)動,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-09-09

最新評論