擁抱開源,發揮更多Vue3的可能性,給本身多一個選擇

爲何另一個路由庫

Vue 社區已經有一個官方的路由庫了,爲何須要另一個?前端

怎麼說呢,對於 API 的喜愛每一個人都會不同吧。我是一個比較追求極致體驗的人,在以前使用 React 進行開發的時候,我就是一個癡迷於一切皆組件的理念的人,我曾經喪心病狂地嘗試封裝<Axios>組件,經過傳遞 props 來獲取數據,沒有嘗試過的同窗可能不能領會這種近乎於偏執的追求。其實在 React 生態這種嘗試很是常見,你任何能想象到的前端技術大概都能找到組件。vue

因此在後來用 Vue 的時候,就很是不習慣各類:ios

  • mixins
  • 原型鏈上掛方法(說實話這是很是差的開發方式)
  • SFC

可是 Vue3 的 composition API 讓我看到了但願,曾經幾乎只能經過 mixin 來擴展的功能,如今有了更好的解決方案。並且我也終於能夠擺脫this了(我真的很是討厭this)。我從 19 年接觸 Vue3 開始就在研究 JSX 開發方式,在 Vue3 中一切皆組件的目的並不比 React 難,可是社區並無不少人追求這個方向,那麼,我就本身作吧。git

因此,就有了 BestVue3 Router 這個庫,看完介紹相信大家就能體會到一些這種感覺吧。github

視頻教程編程

更多:api

Star、Issue和PR都是對開源最好的支持!markdown

介紹

BestVue3 Router 的核心是route的概念。路由表明着一個你應用中的"頁面" 。BestVue3 Router 表明着內部包含 URLs 的路由器,也叫作"locations"。BestVue3 Router 讓你定義用戶訪問路由渲染的 VNodes。app

一個簡單的有兩個頁面的網頁應用,"home"和"about"可能看起來相似這樣:async

import { createApp } from 'vue'
import { BrowserRouter as Router, Routes, Route } from '@bv3/router'

function App() {
    return (
        <div> <h1>Welcome</h1> <Routes> <Route path="/" element={<Home />} /> <Route path="about" element={<About />} /> </Routes> </div>
    )
}

createApp(() => (
    <Router> <App /> </Router>
)).mount('#aa')
複製代碼

<Router> element提供當前[location]../api-reference.md#location)的信息給剩餘的後代。這個例子使用<BrowserRouter>。你應該只渲染一個惟一的<Router>在你的根組件附近。

<Routes> element是你用來定義有哪些路由以及當路由匹配當前路徑時這個<Route> element應該渲染什麼內容。

在這篇教程的接下去的例子中咱們預設你已經引入來 Vue3 而且在<Router>內渲染<App>節點,因此咱們簡明地只展現須要的<Routes>內容。

導航

BestVue3 Router 提供了一個 Link 組件你能夠用來讓你的用戶在不一樣的頁面之間[導航]../api-reference.md#navigation)

import { Routes, Route, Link } from '@bv3/router'

function Home() {
    return (
        <div> <h1>Home</h1> <nav> <Link to="/">Home</Link> | <Link to="about">About</Link> </nav> </div>
    )
}

function About() {
    return <h1>About</h1>
}

function App() {
    return (
        <div> <h1>Welcome</h1> <Routes> <Route path="/" element={<Home />} /> <Route path="about" element={<About />} /> </Routes> </div>
    )
}
複製代碼

讀取路徑參數

你能夠在你的<Route path> 使用動態的:id-相似部分來提取值用來請求數據或者渲染一些內容。useParams hook返回一個Ref對象,其value是一個包含路徑參數的對象。

import { Routes, Route, useParams } from '@bv3/router'

const Invoice = defineComponent({
    setup() {
        const paramsRef = useParams()
        return () => <h1>Invoice {paramsRef.value.invoiceId}</h1>
    },
})

function App() {
    return (
        <Routes> <Route path="invoices/:invoiceId" element={<Invoice />} /> </Routes>
    )
}
複製代碼

模糊路徑和打分

當肯定哪一個路由來渲染的時候,Routes節點選擇和當前位置最匹配的路徑,一般是哪些更明確的路徑。

好比,path="invoices/sent"只會匹配/invoices/sent,因此他比path="invoices/:invoiceId"在匹配以/invoices (/invoices/123, /invoices/cupcakes, 等)開頭的 URL 時更加明確。你能夠根據你的喜愛按照任意順序組織你的代碼。

import { Routes, Route, useParams } from '@bv3/router'

function Invoice() {
    const { invoiceId } = useParams()
    return () => <h1>Invoice {invoiceId}</h1>
}

function SentInvoices() {
    return <h1>Sent Invoices</h1>
}

function App() {
    return (
        <Routes> <Route path="invoices/:invoiceId" element={<Invoice />} /> <Route path="invoices/sent" element={<SentInvoices />} /> </Routes>
    )
}
複製代碼

嵌套路由

Routes may be nested inside one another, and their paths will nest too. Components that are used higher in the route hierarchy may render an <Outlet> element to render their child routes.

路由能夠是嵌套的,他們的路徑也會是嵌套的。高層級的路由渲染的組件須要渲染一個 <Outlet> 節點來讓他們的子路由能夠被渲染。

import { Routes, Route, Outlet } from '@bv3/router'

function Invoices() {
    return (
        <div>
            <h1>Invoices</h1>

            {/*
                這個節點渲染他的子路由,在這個例子中多是 <SentInvoices> 或者 <IndividualInvoice>
            */}
            <Outlet />
        </div>
    )
}

const IndividualInvoice = defineComponent({
    setup() {
        const paramseRef = useParams()
        return () => <h1>Invoice {paramseRef.value.invoiceId}</h1>
    },
})

function SentInvoices() {
    return <h1>Sent Invoices</h1>
}

function App() {
    return (
        <Routes>
            <Route path="invoices" element={<Invoices />}>
                <Route path=":invoiceId" element={<IndividualInvoice />} />
                <Route path="sent" element={<SentInvoices />} />
            </Route>
        </Routes>
    )
}
複製代碼

注意在上面這個例子中路由是如何嵌套在父路由中的。這個嵌套的行爲在建立導航和容器不變子內容根據路由變化的佈局的時候很是有用。

import { Routes, Route, Link, Outlet } from '@bv3/router'

function Layout() {
    return (
        <div> <h1>Welcome to the app!</h1> <nav> <Link to="invoices">Invoices</Link> |{' '} <Link to="dashboard">Dashboard</Link> </nav> <div className="content"> <Outlet /> </div> </div>
    )
}

function Invoices() {
    return <h1>Invoices</h1>
}

function Dashboard() {
    return <h1>Dashboard</h1>
}

function App() {
    return (
        <Routes> <Route path="/" element={<Layout />}> <Route path="invoices" element={<Invoices />} /> <Route path="dashboard" element={<Dashboard />} /> </Route> </Routes>
    )
}
複製代碼

相對的連接

相對的<Link to>值(不以/開始) 是相對於渲染他們的路由的路徑的。下面的兩個連接指向/dashboard/invoices/dashboard/team由於他們都是在<Dashboard>下渲染的。這在你修改父路徑或者從新安排你的組件結構的時候很是好用由於全部你的連接自動會更新。

import { Routes, Route, Link, Outlet } from '@bv3/router'

function Home() {
    return <h1>Home</h1>
}

function Dashboard() {
    return (
        <div> <h1>Dashboard</h1> <nav> <Link to="invoices">Invoices</Link> <Link to="team">Team</Link> </nav> <hr /> <Outlet /> </div>
    )
}

function Invoices() {
    return <h1>Invoices</h1>
}

function Team() {
    return <h1>Team</h1>
}

function App() {
    return (
        <Routes> <Route path="/" element={<Home />} /> <Route path="dashboard" element={<Dashboard />}> <Route path="invoices" element={<Invoices />} /> <Route path="team" element={<Team />} /> </Route> </Routes>
    )
}
複製代碼

主路由

Nested routes may use path="/" to indicate they should render at the path of the parent component. You can think about these routes like index pages for the rest of the child routes.

嵌套路由可使用path="/"來代表他們應該在他的父路由的路徑下渲染。你能夠認爲這些路由就像其餘子路由的主頁。

function App() {
    return (
        <Routes> <Route path="/" element={<Home />} /> <Route path="dashboard" element={<Dashboard />}> <Route path="/" element={<DashboardHome />} /> <Route path="invoices" element={<DashboardInvoices />} /> </Route> </Routes>
    )
}
複製代碼

"Not Found" 路由

When no other route matches the URL, you can render a "not found" route using path="*". This route will match any URL, but will have the weakest precedence so the router will only pick it if no other routes match.

當沒有其餘路由匹配的時候,你可使用path="*"渲染一個"not found"路由。這個路由會匹配任何 URL,但也會具備最弱的優先級,因此路由器只會在找不到其餘匹配的路由的狀況下選擇他。

function App() {
    return (
        <Routes> <Route path="/" element={<Home />} /> <Route path="dashboard" element={<Dashboard />} /> <Route path="*" element={<NotFound />} /> </Routes>
    )
}
複製代碼

多組路由

雖然在你的應用中應該只有一個<Router>,你能夠根據須要有多個<Routes>。每一個<Routes>獨立地選擇子路由進行渲染。

function App() {
    return (
        <div> <Sidebar> <Routes> <Route path="/" element={<MainNav />} /> <Route path="dashboard" element={<DashboardNav />} /> </Routes> </Sidebar> <MainContent> <Routes> <Route path="/" element={<Home />}> <Route path="about" element={<About />} /> <Route path="support" element={<Support />} /> </Route> <Route path="dashboard" element={<Dashboard />}> <Route path="invoices" element={<Invoices />} /> <Route path="team" element={<Team />} /> </Route> <Route path="*" element={<NotFound />} /> </Routes> </MainContent> </div>
    )
}
複製代碼

後輩路由集合

你能夠在任何你須要的地方渲染<Routes> 節點,包括在其餘<Routes>的子樹中。除了他們會自動在渲染他們的路由的基礎上構建路徑以外,他們跟其餘<Routes>同樣正常工做。若是你須要這麼作,請確保在父路由的路徑最後放上*。否則的話父路由不會匹配比他路徑長的 URL,你的後輩<Routes>永遠不會展現。

function Dashboard() {
    return (
        <div> <p>Look, more routes!</p> <Routes> <Route path="/" element={<DashboardGraphs />} /> <Route path="invoices" element={<InvoiceList />} /> </Routes> </div>
    )
}

function App() {
    return (
        <Routes> <Route path="/" element={<Home />} /> <Route path="dashboard/*" element={<Dashboard />} /> </Routes>
    )
}
複製代碼

編程式的導航

If you need to navigate programmatically (like after the user submits a form), use the useNavigate hook to get a function you can use to navigate.

若是你須要編程式地導航(好比在用戶提交表單以後),使用useNavigate 鉤子來獲取一個函數幫你進行導航。

import { useNavigate } from '@bv3/router'

const Invoices = defineComponent({
    setup() {
        const navigate = useNavigate()
        return () => (
            <div> <NewInvoiceForm onSubmit={async event => { const newInvoice = await createInvoice(event.target) navigate(`/invoices/${newInvoice.id}`) }} /> </div>
        )
    },
})
複製代碼

以上!這裏咱們尚未覆蓋全部的 API,可是這些絕對是最通用的場景。若是你想要再深刻學習,你能夠查看完整的 API 文檔

對於咱們正在作的事情感興趣,或者但願可以學到更多更優質的Vue3知識,能夠搜索公衆號 BestVue3 關注,提供更優質的Vue3內容。

相關文章
相關標籤/搜索