<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 安裝 ### [#](https://router.vuejs.org/zh/installation.html#%E7%9B%B4%E6%8E%A5%E4%B8%8B%E8%BD%BD-cdn)直接下載 / CDN [https://unpkg.com/vue-router/dist/vue-router.js](https://unpkg.com/vue-router/dist/vue-router.js) [Unpkg.com](https://unpkg.com/)?提供了基于 NPM 的 CDN 鏈接。上面的鏈接會一直指向在 NPM 發布的最新版本。你也可以像?`https://unpkg.com/vue-router@2.0.0/dist/vue-router.js`?這樣指定 版本號 或者 Tag。 在 Vue 后面加載?`vue-router`,它會自動安裝的: ~~~ <script src="/path/to/vue.js"></script> <script src="/path/to/vue-router.js"></script> ~~~ ### [#](https://router.vuejs.org/zh/installation.html#npm)NPM ~~~ npm install vue-router ~~~ 如果在一個模塊化工程中使用它,必須要通過?`Vue.use()`?明確地安裝路由功能: ~~~ import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) ~~~ 如果使用全局的 script 標簽,則無須如此 (手動安裝)。 ### [#](https://router.vuejs.org/zh/installation.html#%E6%9E%84%E5%BB%BA%E5%BC%80%E5%8F%91%E7%89%88)構建開發版 如果你想使用最新的開發版,就得從 GitHub 上直接 clone,然后自己 build 一個?`vue-router`。 ~~~ git clone https://github.com/vuejs/vue-router.git node_modules/vue-router cd node_modules/vue-router npm install npm run build ~~~ # 介紹 [This project is sponsored by?![bit](https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/bit-wide.png)](https://www.bitsrc.io/?utm_source=vue&utm_medium=vue&utm_campaign=vue&utm_term=vue&utm_content=vue) 版本說明 對于 TypeScript 用戶來說,`vue-router@3.0+`?依賴?`vue@2.5+`,反之亦然。 Vue Router 是?[Vue.js](http://cn.vuejs.org/)?官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面應用變得易如反掌。包含的功能有: * 嵌套的路由/視圖表 * 模塊化的、基于組件的路由配置 * 路由參數、查詢、通配符 * 基于 Vue.js 過渡系統的視圖過渡效果 * 細粒度的導航控制 * 帶有自動激活的 CSS class 的鏈接 * HTML5 歷史模式或 hash 模式,在 IE9 中自動降級 * 自定義的滾動條行為 現在開始[起步](https://router.vuejs.org/zh/guide/)或嘗試一下我們的[示例](https://github.com/vuejs/vue-router/tree/dev/examples)吧 (查看倉庫的?[`README.md`](https://github.com/vuejs/vue-router/)?來運行它們)。 # 起步 [This project is sponsored by?![bit](https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/bit-wide.png)](https://www.bitsrc.io/?utm_source=vue&utm_medium=vue&utm_campaign=vue&utm_term=vue&utm_content=vue) 注意 教程中的案例代碼將使用?[ES2015](https://github.com/lukehoban/es6features)?來編寫。 同時,所有的例子都將使用完整版的 Vue 以解析模板。更多細節請[移步這里](https://cn.vuejs.org/v2/guide/installation.html#%E8%BF%90%E8%A1%8C%E6%97%B6-%E7%BC%96%E8%AF%91%E5%99%A8-vs-%E5%8F%AA%E5%8C%85%E5%90%AB%E8%BF%90%E8%A1%8C%E6%97%B6)。 用 Vue.js + Vue Router 創建單頁應用,是非常簡單的。使用 Vue.js ,我們已經可以通過組合組件來組成應用程序,當你要把 Vue Router 添加進來,我們需要做的是,將組件 (components) 映射到路由 (routes),然后告訴 Vue Router 在哪里渲染它們。下面是個基本例子: ## [#](https://router.vuejs.org/zh/guide/#html)HTML ~~~ <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <div id="app"> <h1>Hello App!</h1> <p> <!-- 使用 router-link 組件來導航. --> <!-- 通過傳入 `to` 屬性指定鏈接. --> <!-- <router-link> 默認會被渲染成一個 `<a>` 標簽 --> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <!-- 路由出口 --> <!-- 路由匹配到的組件將渲染在這里 --> <router-view></router-view> </div> ~~~ ## [#](https://router.vuejs.org/zh/guide/#javascript)JavaScript ~~~ // 0\. 如果使用模塊化機制編程,導入Vue和VueRouter,要調用 Vue.use(VueRouter) // 1\. 定義 (路由) 組件。 // 可以從其他文件 import 進來 const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } // 2\. 定義路由 // 每個路由應該映射一個組件。 其中"component" 可以是 // 通過 Vue.extend() 創建的組件構造器, // 或者,只是一個組件配置對象。 // 我們晚點再討論嵌套路由。 const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] // 3\. 創建 router 實例,然后傳 `routes` 配置 // 你還可以傳別的配置參數, 不過先這么簡單著吧。 const router = new VueRouter({ routes // (縮寫) 相當于 routes: routes }) // 4\. 創建和掛載根實例。 // 記得要通過 router 配置參數注入路由, // 從而讓整個應用都有路由功能 const app = new Vue({ router }).$mount('#app') // 現在,應用已經啟動了! ~~~ 通過注入路由器,我們可以在任何組件內通過?`this.$router`?訪問路由器,也可以通過?`this.$route`?訪問當前路由: ~~~ // Home.vue export default { computed: { username () { // 我們很快就會看到 `params` 是什么 return this.$route.params.username } }, methods: { goBack () { window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/') } } } ~~~ 該文檔通篇都常使用?`router`?實例。留意一下?`this.$router`?和?`router`?使用起來完全一樣。我們使用?`this.$router`?的原因是我們并不想在每個獨立需要封裝路由的組件中都導入路由。 你可以看看這個[在線的](https://jsfiddle.net/yyx990803/xgrjzsup/)例子。 要注意,當?`<router-link>`?對應的路由匹配成功,將自動設置 class 屬性值?`.router-link-active`。查看?[API 文檔](https://router.vuejs.org/zh/api/#router-link)?學習更多相關內容。 # 動態路由匹配 我們經常需要把某種模式匹配到的所有路由,全都映射到同個組件。例如,我們有一個?`User`?組件,對于所有 ID 各不相同的用戶,都要使用這個組件來渲染。那么,我們可以在?`vue-router`?的路由路徑中使用“動態路徑參數”(dynamic segment) 來達到這個效果: ~~~ const User = { template: '<div>User</div>' } const router = new VueRouter({ routes: [ // 動態路徑參數 以冒號開頭 { path: '/user/:id', component: User } ] }) ~~~ 現在呢,像?`/user/foo`?和?`/user/bar`?都將映射到相同的路由。 一個“路徑參數”使用冒號?`:`?標記。當匹配到一個路由時,參數值會被設置到?`this.$route.params`,可以在每個組件內使用。于是,我們可以更新?`User`?的模板,輸出當前用戶的 ID: ~~~ const User = { template: '<div>User {{ $route.params.id }}</div>' } ~~~ 你可以看看這個[在線例子](https://jsfiddle.net/yyx990803/4xfa2f19/)。 你可以在一個路由中設置多段“路徑參數”,對應的值都會設置到?`$route.params`?中。例如: | 模式 | 匹配路徑 | $route.params | | --- | --- | --- | | /user/:username | /user/evan | `{ username: 'evan' }` | | /user/:username/post/:post_id | /user/evan/post/123 | `{ username: 'evan', post_id: 123 }` | 除了?`$route.params`?外,`$route`?對象還提供了其它有用的信息,例如,`$route.query`?(如果 URL 中有查詢參數)、`$route.hash`?等等。你可以查看?[API 文檔](https://router.vuejs.org/zh/api/#%E8%B7%AF%E7%94%B1%E5%AF%B9%E8%B1%A1)?的詳細說明。 ## [#](https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#%E5%93%8D%E5%BA%94%E8%B7%AF%E7%94%B1%E5%8F%82%E6%95%B0%E7%9A%84%E5%8F%98%E5%8C%96)響應路由參數的變化 提醒一下,當使用路由參數時,例如從?`/user/foo`?導航到?`/user/bar`,原來的組件實例會被復用。因為兩個路由都渲染同個組件,比起銷毀再創建,復用則顯得更加高效。不過,這也意味著組件的生命周期鉤子不會再被調用。 復用組件時,想對路由參數的變化作出響應的話,你可以簡單地 watch (監測變化)?`$route`?對象: ~~~ const User = { template: '...', watch: { '$route' (to, from) { // 對路由變化作出響應... } } } ~~~ 或者使用 2.2 中引入的?`beforeRouteUpdate`?[導航守衛](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html): ~~~ const User = { template: '...', beforeRouteUpdate (to, from, next) { // react to route changes... // don't forget to call next() } } ~~~ ## [#](https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#%E9%AB%98%E7%BA%A7%E5%8C%B9%E9%85%8D%E6%A8%A1%E5%BC%8F)高級匹配模式 `vue-router`?使用?[path-to-regexp](https://github.com/pillarjs/path-to-regexp)?作為路徑匹配引擎,所以支持很多高級的匹配模式,例如:可選的動態路徑參數、匹配零個或多個、一個或多個,甚至是自定義正則匹配。查看它的?[文檔](https://github.com/pillarjs/path-to-regexp#parameters)?學習高階的路徑匹配,還有?[這個例子?](https://github.com/vuejs/vue-router/blob/next/examples/route-matching/app.js)?展示?`vue-router`?怎么使用這類匹配。 ## [#](https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#%E5%8C%B9%E9%85%8D%E4%BC%98%E5%85%88%E7%BA%A7)匹配優先級 有時候,同一個路徑可以匹配多個路由,此時,匹配的優先級就按照路由的定義順序:誰先定義的,誰的優先級就最高。 # 嵌套路由 實際生活中的應用界面,通常由多層嵌套的組件組合而成。同樣地,URL 中各段動態路徑也按某種結構對應嵌套的各層組件,例如: ~~~ /user/foo/profile /user/foo/posts +------------------+ +-----------------+ | User | | User | | +--------------+ | | +-------------+ | | | Profile | | +------------> | | Posts | | | | | | | | | | | +--------------+ | | +-------------+ | +------------------+ +-----------------+ ~~~ 借助?`vue-router`,使用嵌套路由配置,就可以很簡單地表達這種關系。 接著上節創建的 app: ~~~ <div id="app"> <router-view></router-view> </div> ~~~ ~~~ const User = { template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] }) ~~~ 這里的?`<router-view>`?是最頂層的出口,渲染最高級路由匹配到的組件。同樣地,一個被渲染組件同樣可以包含自己的嵌套?`<router-view>`。例如,在?`User`?組件的模板添加一個?`<router-view>`: ~~~ const User = { template: ` <div class="user"> <h2>User {{ $route.params.id }}</h2> <router-view></router-view> </div> ` } ~~~ 要在嵌套的出口中渲染組件,需要在?`VueRouter`?的參數中使用?`children`?配置: ~~~ const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, children: [ { // 當 /user/:id/profile 匹配成功, // UserProfile 會被渲染在 User 的 <router-view> 中 path: 'profile', component: UserProfile }, { // 當 /user/:id/posts 匹配成功 // UserPosts 會被渲染在 User 的 <router-view> 中 path: 'posts', component: UserPosts } ] } ] }) ~~~ 要注意,以?`/`?開頭的嵌套路徑會被當作根路徑。 這讓你充分的使用嵌套組件而無須設置嵌套的路徑。 你會發現,`children`?配置就是像?`routes`?配置一樣的路由配置數組,所以呢,你可以嵌套多層路由。 此時,基于上面的配置,當你訪問?`/user/foo`?時,`User`?的出口是不會渲染任何東西,這是因為沒有匹配到合適的子路由。如果你想要渲染點什么,可以提供一個 空的 子路由: ~~~ const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, children: [ // 當 /user/:id 匹配成功, // UserHome 會被渲染在 User 的 <router-view> 中 { path: '', component: UserHome }, // ...其他子路由 ] } ] }) ~~~ 提供以上案例的可運行代碼請[移步這里](https://jsfiddle.net/yyx990803/L7hscd8h/)。 # 編程式的導航 除了使用?`<router-link>`?創建 a 標簽來定義導航鏈接,我們還可以借助 router 的實例方法,通過編寫代碼來實現。 ## [#](https://router.vuejs.org/zh/guide/essentials/navigation.html#router-push-location-oncomplete-onabort)`router.push(location, onComplete?, onAbort?)` 注意:在 Vue 實例內部,你可以通過?`$router`?訪問路由實例。因此你可以調用?`this.$router.push`。 想要導航到不同的 URL,則使用?`router.push`?方法。這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器后退按鈕時,則回到之前的 URL。 當你點擊?`<router-link>`?時,這個方法會在內部調用,所以說,點擊?`<router-link :to="...">`?等同于調用?`router.push(...)`。 | 聲明式 | 編程式 | | --- | --- | | `<router-link :to="...">` | `router.push(...)` | 該方法的參數可以是一個字符串路徑,或者一個描述地址的對象。例如: ~~~ // 字符串 router.push('home') // 對象 router.push({ path: 'home' }) // 命名的路由 router.push({ name: 'user', params: { userId: 123 }}) // 帶查詢參數,變成 /register?plan=private router.push({ path: 'register', query: { plan: 'private' }}) ~~~ 注意:如果提供了?`path`,`params`?會被忽略,上述例子中的?`query`?并不屬于這種情況。取而代之的是下面例子的做法,你需要提供路由的?`name`?或手寫完整的帶有參數的?`path`: ~~~ const userId = 123 router.push({ name: 'user', params: { userId }}) // -> /user/123 router.push({ path: `/user/${userId}` }) // -> /user/123 // 這里的 params 不生效 router.push({ path: '/user', params: { userId }}) // -> /user ~~~ 同樣的規則也適用于?`router-link`?組件的?`to`?屬性。 在 2.2.0+,可選的在?`router.push`?或?`router.replace`?中提供?`onComplete`?和?`onAbort`?回調作為第二個和第三個參數。這些回調將會在導航成功完成 (在所有的異步鉤子被解析之后) 或終止 (導航到相同的路由、或在當前導航完成之前導航到另一個不同的路由) 的時候進行相應的調用。 **注意:**如果目的地和當前路由相同,只有參數發生了改變 (比如從一個用戶資料到另一個?`/users/1`?->?`/users/2`),你需要使用?[`beforeRouteUpdate`](https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#%E5%93%8D%E5%BA%94%E8%B7%AF%E7%94%B1%E5%8F%82%E6%95%B0%E7%9A%84%E5%8F%98%E5%8C%96)?來響應這個變化 (比如抓取用戶信息)。 ## [#](https://router.vuejs.org/zh/guide/essentials/navigation.html#router-replace-location-oncomplete-onabort)`router.replace(location, onComplete?, onAbort?)` 跟?`router.push`?很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄。 | 聲明式 | 編程式 | | --- | --- | | `<router-link :to="..." replace>` | `router.replace(...)` | ## [#](https://router.vuejs.org/zh/guide/essentials/navigation.html#router-go-n)`router.go(n)` 這個方法的參數是一個整數,意思是在 history 記錄中向前或者后退多少步,類似?`window.history.go(n)`。 例子 ~~~ // 在瀏覽器記錄中前進一步,等同于 history.forward() router.go(1) // 后退一步記錄,等同于 history.back() router.go(-1) // 前進 3 步記錄 router.go(3) // 如果 history 記錄不夠用,那就默默地失敗唄 router.go(-100) router.go(100) ~~~ ## [#](https://router.vuejs.org/zh/guide/essentials/navigation.html#%E6%93%8D%E4%BD%9C-history)操作 History 你也許注意到?`router.push`、?`router.replace`?和?`router.go`?跟?[`window.history.pushState`、?`window.history.replaceState`?和?`window.history.go`](https://developer.mozilla.org/en-US/docs/Web/API/History)好像, 實際上它們確實是效仿?`window.history`API 的。 因此,如果你已經熟悉?[Browser History APIs](https://developer.mozilla.org/en-US/docs/Web/API/History_API),那么在 Vue Router 中操作 history 就是超級簡單的。 還有值得提及的,Vue Router 的導航方法 (`push`、?`replace`、?`go`) 在各類路由模式 (`history`、?`hash`?和?`abstract`) 下表現一致。 # 命名路由 有時候,通過一個名稱來標識一個路由顯得更方便一些,特別是在鏈接一個路由,或者是執行一些跳轉的時候。你可以在創建 Router 實例的時候,在?`routes`?配置中給某個路由設置名稱。 ~~~ const router = new VueRouter({ routes: [ { path: '/user/:userId', name: 'user', component: User } ] }) ~~~ 要鏈接到一個命名路由,可以給?`router-link`?的?`to`?屬性傳一個對象: ~~~ <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link> ~~~ 這跟代碼調用?`router.push()`?是一回事: ~~~ router.push({ name: 'user', params: { userId: 123 }}) ~~~ 這兩種方式都會把路由導航到?`/user/123`?路徑。 完整的例子請[移步這里](https://github.com/vuejs/vue-router/blob/next/examples/named-routes/app.js)。 # 命名視圖 有時候想同時 (同級) 展示多個視圖,而不是嵌套展示,例如創建一個布局,有?`sidebar`?(側導航) 和?`main`?(主內容) 兩個視圖,這個時候命名視圖就派上用場了。你可以在界面中擁有多個單獨命名的視圖,而不是只有一個單獨的出口。如果?`router-view`?沒有設置名字,那么默認為?`default`。 ~~~ <router-view class="view one"></router-view> <router-view class="view two" name="a"></router-view> <router-view class="view three" name="b"></router-view> ~~~ 一個視圖使用一個組件渲染,因此對于同個路由,多個視圖就需要多個組件。確保正確使用?`components`配置 (帶上 s): ~~~ const router = new VueRouter({ routes: [ { path: '/', components: { default: Foo, a: Bar, b: Baz } } ] }) ~~~ 以上案例相關的可運行代碼請[移步這里](https://jsfiddle.net/posva/6du90epg/)。 ## [#](https://router.vuejs.org/zh/guide/essentials/named-views.html#%E5%B5%8C%E5%A5%97%E5%91%BD%E5%90%8D%E8%A7%86%E5%9B%BE)嵌套命名視圖 我們也有可能使用命名視圖創建嵌套視圖的復雜布局。這時你也需要命名用到的嵌套?`router-view`?組件。我們以一個設置面板為例: ~~~ /settings/emails /settings/profile +-----------------------------------+ +------------------------------+ | UserSettings | | UserSettings | | +-----+-------------------------+ | | +-----+--------------------+ | | | Nav | UserEmailsSubscriptions | | +------------> | | Nav | UserProfile | | | | +-------------------------+ | | | +--------------------+ | | | | | | | | | UserProfilePreview | | | +-----+-------------------------+ | | +-----+--------------------+ | +-----------------------------------+ +------------------------------+ ~~~ * `Nav`?只是一個常規組件。 * `UserSettings`?是一個視圖組件。 * `UserEmailsSubscriptions`、`UserProfile`、`UserProfilePreview`?是嵌套的視圖組件。 注意:*我們先忘記 HTML/CSS 具體的布局的樣子,只專注在用到的組件上* `UserSettings`?組件的?`<template>`?部分應該是類似下面的這段代碼: ~~~ <!-- UserSettings.vue --> <div> <h1>User Settings</h1> <NavBar/> <router-view/> <router-view name="helper"/> </div> ~~~ *嵌套的視圖組件在此已經被忽略了,但是你可以在[這里](https://jsfiddle.net/posva/22wgksa3/)找到完整的源代碼* 然后你可以用這個路由配置完成該布局: ~~~ { path: '/settings', // 你也可以在頂級路由就配置命名視圖 component: UserSettings, children: [{ path: 'emails', component: UserEmailsSubscriptions }, { path: 'profile', components: { default: UserProfile, helper: UserProfilePreview } }] } ~~~ 一個可以工作的示例的 demo 在[這里](https://jsfiddle.net/posva/22wgksa3/)。 # 重定向和別名 ## [#](https://router.vuejs.org/zh/guide/essentials/redirect-and-alias.html#%E9%87%8D%E5%AE%9A%E5%90%91)重定向 重定向也是通過?`routes`?配置來完成,下面例子是從?`/a`?重定向到?`/b`: ~~~ const router = new VueRouter({ routes: [ { path: '/a', redirect: '/b' } ] }) ~~~ 重定向的目標也可以是一個命名的路由: ~~~ const router = new VueRouter({ routes: [ { path: '/a', redirect: { name: 'foo' }} ] }) ~~~ 甚至是一個方法,動態返回重定向目標: ~~~ const router = new VueRouter({ routes: [ { path: '/a', redirect: to => { // 方法接收 目標路由 作為參數 // return 重定向的 字符串路徑/路徑對象 }} ] }) ~~~ 注意[導航守衛](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html)并沒有應用在跳轉路由上,而僅僅應用在其目標上。在下面這個例子中,為?`/a`?路由添加一個?`beforeEach`?或?`beforeLeave`?守衛并不會有任何效果。 其它高級用法,請參考[例子](https://github.com/vuejs/vue-router/blob/next/examples/redirect/app.js)。 ## [#](https://router.vuejs.org/zh/guide/essentials/redirect-and-alias.html#%E5%88%AB%E5%90%8D)別名 “重定向”的意思是,當用戶訪問?`/a`時,URL 將會被替換成?`/b`,然后匹配路由為?`/b`,那么“別名”又是什么呢? `/a`?的別名是?`/b`,意味著,當用戶訪問?`/b`?時,URL 會保持為?`/b`,但是路由匹配則為?`/a`,就像用戶訪問?`/a`?一樣。 上面對應的路由配置為: ~~~ const router = new VueRouter({ routes: [ { path: '/a', component: A, alias: '/b' } ] }) ~~~ “別名”的功能讓你可以自由地將 UI 結構映射到任意的 URL,而不是受限于配置的嵌套路由結構。 更多高級用法,請查看[例子](https://github.com/vuejs/vue-router/blob/next/examples/route-alias/app.js)。 # 路由組件傳參 在組件中使用?`$route`?會使之與其對應路由形成高度耦合,從而使組件只能在某些特定的 URL 上使用,限制了其靈活性。 使用?`props`?將組件和路由解耦: 取代與?`$route`?的耦合 ~~~ const User = { template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] }) ~~~ 通過?`props`?解耦 ~~~ const User = { props: ['id'], template: '<div>User {{ id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, props: true }, // 對于包含命名視圖的路由,你必須分別為每個命名視圖添加 `props` 選項: { path: '/user/:id', components: { default: User, sidebar: Sidebar }, props: { default: true, sidebar: false } } ] }) ~~~ 這樣你便可以在任何地方使用該組件,使得該組件更易于重用和測試。 ## [#](https://router.vuejs.org/zh/guide/essentials/passing-props.html#%E5%B8%83%E5%B0%94%E6%A8%A1%E5%BC%8F)布爾模式 如果?`props`?被設置為?`true`,`route.params`?將會被設置為組件屬性。 ## [#](https://router.vuejs.org/zh/guide/essentials/passing-props.html#%E5%AF%B9%E8%B1%A1%E6%A8%A1%E5%BC%8F)對象模式 如果?`props`?是一個對象,它會被按原樣設置為組件屬性。當?`props`?是靜態的時候有用。 ~~~ const router = new VueRouter({ routes: [ { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } } ] }) ~~~ ## [#](https://router.vuejs.org/zh/guide/essentials/passing-props.html#%E5%87%BD%E6%95%B0%E6%A8%A1%E5%BC%8F)函數模式 你可以創建一個函數返回?`props`。這樣你便可以將參數轉換成另一種類型,將靜態值與基于路由的值結合等等。 ~~~ const router = new VueRouter({ routes: [ { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) } ] }) ~~~ URL?`/search?q=vue`?會將?`{query: 'vue'}`?作為屬性傳遞給?`SearchUser`?組件。 請盡可能保持?`props`?函數為無狀態的,因為它只會在路由發生變化時起作用。如果你需要狀態來定義?`props`,請使用包裝組件,這樣 Vue 才可以對狀態變化做出反應。 更多高級用法,請查看[例子](https://github.com/vuejs/vue-router/blob/dev/examples/route-props/app.js)。 # HTML5 History 模式 `vue-router`?默認 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,于是當 URL 改變時,頁面不會重新加載。 如果不想要很丑的 hash,我們可以用路由的?history 模式,這種模式充分利用?`history.pushState`?API 來完成 URL 跳轉而無須重新加載頁面。 ~~~ const router = new VueRouter({ mode: 'history', routes: [...] }) ~~~ 當你使用 history 模式時,URL 就像正常的 url,例如?`http://yoursite.com/user/id`,也好看! 不過這種模式要玩好,還需要后臺配置支持。因為我們的應用是個單頁客戶端應用,如果后臺沒有正確的配置,當用戶在瀏覽器直接訪問?`http://oursite.com/user/id`?就會返回 404,這就不好看了。 所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個?`index.html`?頁面,這個頁面就是你 app 依賴的頁面。 ## [#](https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90)后端配置例子 #### [#](https://router.vuejs.org/zh/guide/essentials/history-mode.html#apache)Apache ~~~ <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] </IfModule> ~~~ 除了?`mod_rewrite`,你也可以使用?[`FallbackResource`](https://httpd.apache.org/docs/2.2/mod/mod_dir.html#fallbackresource)。 #### [#](https://router.vuejs.org/zh/guide/essentials/history-mode.html#nginx)nginx ~~~ location / { try_files $uri $uri/ /index.html; } ~~~ #### [#](https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%8E%9F%E7%94%9F-node-js)原生 Node.js ~~~ const http = require('http') const fs = require('fs') const httpPort = 80 http.createServer((req, res) => { fs.readFile('index.htm', 'utf-8', (err, content) => { if (err) { console.log('We cannot open "index.htm" file.') } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }) res.end(content) }) }).listen(httpPort, () => { console.log('Server listening on: http://localhost:%s', httpPort) }) ~~~ #### [#](https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%9F%BA%E4%BA%8E-node-js-%E7%9A%84-express)基于 Node.js 的 Express 對于 Node.js/Express,請考慮使用?[connect-history-api-fallback 中間件](https://github.com/bripkens/connect-history-api-fallback)。 #### [#](https://router.vuejs.org/zh/guide/essentials/history-mode.html#internet-information-services-iis)Internet Information Services (IIS) 1. 安裝?[IIS UrlRewrite](https://www.iis.net/downloads/microsoft/url-rewrite) 2. 在你的網站根目錄中創建一個?`web.config`?文件,內容如下: ~~~ <?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="Handle History Mode and custom 404/500" stopProcessing="true"> <match url="(.*)" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <action type="Rewrite" url="/" /> </rule> </rules> </rewrite> </system.webServer> </configuration> ~~~ #### [#](https://router.vuejs.org/zh/guide/essentials/history-mode.html#caddy)Caddy ~~~ rewrite { regexp .* to {path} / } ~~~ #### [#](https://router.vuejs.org/zh/guide/essentials/history-mode.html#firebase-%E4%B8%BB%E6%9C%BA)Firebase 主機 在你的?`firebase.json`?中加入: ~~~ { "hosting": { "public": "dist", "rewrites": [ { "source": "**", "destination": "/index.html" } ] } } ~~~ ## [#](https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E8%AD%A6%E5%91%8A)警告 給個警告,因為這么做以后,你的服務器就不再返回 404 錯誤頁面,因為對于所有路徑都會返回?`index.html`?文件。為了避免這種情況,你應該在 Vue 應用里面覆蓋所有的路由情況,然后在給出一個 404 頁面。 ~~~ const router = new VueRouter({ mode: 'history', routes: [ { path: '*', component: NotFoundComponent } ] }) ~~~ 或者,如果你使用 Node.js 服務器,你可以用服務端路由匹配到來的 URL,并在沒有匹配到路由的時候返回 404,以實現回退。更多詳情請查閱?[Vue 服務端渲染文檔](https://ssr.vuejs.org/zh/)。 # 導航守衛 譯者注 “導航”表示路由正在發生改變。 正如其名,`vue-router`?提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程中:全局的, 單個路由獨享的, 或者組件級的。 記住參數或查詢的改變并不會觸發進入/離開的導航守衛。你可以通過[觀察?`$route`?對象](https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#%E5%93%8D%E5%BA%94%E8%B7%AF%E7%94%B1%E5%8F%82%E6%95%B0%E7%9A%84%E5%8F%98%E5%8C%96)來應對這些變化,或使用?`beforeRouteUpdate`?的組件內守衛。 ## [#](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%AE%88%E5%8D%AB)全局守衛 你可以使用?`router.beforeEach`?注冊一個全局前置守衛: ~~~ const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... }) ~~~ 當一個導航觸發時,全局前置守衛按照創建順序調用。守衛是異步解析執行,此時導航在所有守衛 resolve 完之前一直處于?等待中。 每個守衛方法接收三個參數: * `to: Route`: 即將要進入的目標?[路由對象](https://router.vuejs.org/zh/api/#%E8%B7%AF%E7%94%B1%E5%AF%B9%E8%B1%A1) * `from: Route`: 當前導航正要離開的路由 * `next: Function`: 一定要調用該方法來?resolve?這個鉤子。執行效果依賴?`next`?方法的調用參數。 * `next()`: 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是?confirmed?(確認的)。 * `next(false)`: 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到?`from`?路由對應的地址。 * `next('/')`?或者?`next({ path: '/' })`: 跳轉到一個不同的地址。當前的導航被中斷,然后進行一個新的導航。你可以向?`next`?傳遞任意位置對象,且允許設置諸如?`replace: true`、`name: 'home'`?之類的選項以及任何用在?[`router-link`?的?`to`?prop](https://router.vuejs.org/zh/api/#to)?或?[`router.push`](https://router.vuejs.org/zh/api/#router-push)?中的選項。 * `next(error)`: (2.4.0+) 如果傳入?`next`?的參數是一個?`Error`?實例,則導航會被終止且該錯誤會被傳遞給?[`router.onError()`](https://router.vuejs.org/zh/api/#router-onerror)?注冊過的回調。 確保要調用?`next`?方法,否則鉤子就不會被 resolved。 ## [#](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E8%A7%A3%E6%9E%90%E5%AE%88%E5%8D%AB)全局解析守衛 > 2.5.0 新增 在 2.5.0+ 你可以用?`router.beforeResolve`?注冊一個全局守衛。這和?`router.beforeEach`?類似,區別是在導航被確認之前,同時在所有組件內守衛和異步路由組件被解析之后,解析守衛就被調用。 ## [#](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%90%8E%E7%BD%AE%E9%92%A9%E5%AD%90)全局后置鉤子 你也可以注冊全局后置鉤子,然而和守衛不同的是,這些鉤子不會接受?`next`?函數也不會改變導航本身: ~~~ router.afterEach((to, from) => { // ... }) ~~~ ## [#](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E8%B7%AF%E7%94%B1%E7%8B%AC%E4%BA%AB%E7%9A%84%E5%AE%88%E5%8D%AB)路由獨享的守衛 你可以在路由配置上直接定義?`beforeEnter`?守衛: ~~~ const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] }) ~~~ 這些守衛與全局前置守衛的方法參數是一樣的。 ## [#](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E7%BB%84%E4%BB%B6%E5%86%85%E7%9A%84%E5%AE%88%E5%8D%AB)組件內的守衛 最后,你可以在路由組件內直接定義以下路由導航守衛: * `beforeRouteEnter` * `beforeRouteUpdate`?(2.2 新增) * `beforeRouteLeave` ~~~ const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染該組件的對應路由被 confirm 前調用 // 不!能!獲取組件實例 `this` // 因為當守衛執行前,組件實例還沒被創建 }, beforeRouteUpdate (to, from, next) { // 在當前路由改變,但是該組件被復用時調用 // 舉例來說,對于一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候, // 由于會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。 // 可以訪問組件實例 `this` }, beforeRouteLeave (to, from, next) { // 導航離開該組件的對應路由時調用 // 可以訪問組件實例 `this` } } ~~~ `beforeRouteEnter`?守衛?不能?訪問?`this`,因為守衛在導航確認前被調用,因此即將登場的新組件還沒被創建。 不過,你可以通過傳一個回調給?`next`來訪問組件實例。在導航被確認的時候執行回調,并且把組件實例作為回調方法的參數。 ~~~ beforeRouteEnter (to, from, next) { next(vm => { // 通過 `vm` 訪問組件實例 }) } ~~~ 注意?`beforeRouteEnter`?是支持給?`next`?傳遞回調的唯一守衛。對于?`beforeRouteUpdate`?和?`beforeRouteLeave`?來說,`this`?已經可用了,所以不支持傳遞回調,因為沒有必要了。 ~~~ beforeRouteUpdate (to, from, next) { // just use `this` this.name = to.params.name next() } ~~~ 這個離開守衛通常用來禁止用戶在還未保存修改前突然離開。該導航可以通過?`next(false)`?來取消。 ~~~ beforeRouteLeave (to, from , next) { const answer = window.confirm('Do you really want to leave? you have unsaved changes!') if (answer) { next() } else { next(false) } } ~~~ ## [#](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%AE%8C%E6%95%B4%E7%9A%84%E5%AF%BC%E8%88%AA%E8%A7%A3%E6%9E%90%E6%B5%81%E7%A8%8B)完整的導航解析流程 1. 導航被觸發。 2. 在失活的組件里調用離開守衛。 3. 調用全局的?`beforeEach`?守衛。 4. 在重用的組件里調用?`beforeRouteUpdate`?守衛 (2.2+)。 5. 在路由配置里調用?`beforeEnter`。 6. 解析異步路由組件。 7. 在被激活的組件里調用?`beforeRouteEnter`。 8. 調用全局的?`beforeResolve`?守衛 (2.5+)。 9. 導航被確認。 10. 調用全局的?`afterEach`?鉤子。 11. 觸發 DOM 更新。 12. 用創建好的實例調用?`beforeRouteEnter`?守衛中傳給?`next`?的回調函數。 # 路由元信息 定義路由的時候可以配置?`meta`?字段: ~~~ const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, children: [ { path: 'bar', component: Bar, // a meta field meta: { requiresAuth: true } } ] } ] }) ~~~ 那么如何訪問這個?`meta`?字段呢? 首先,我們稱呼?`routes`?配置中的每個路由對象為?路由記錄。路由記錄可以是嵌套的,因此,當一個路由匹配成功后,他可能匹配多個路由記錄 例如,根據上面的路由配置,`/foo/bar`?這個 URL 將會匹配父路由記錄以及子路由記錄。 一個路由匹配到的所有路由記錄會暴露為?`$route`?對象 (還有在導航守衛中的路由對象) 的?`$route.matched`?數組。因此,我們需要遍歷?`$route.matched`?來檢查路由記錄中的?`meta`?字段。 下面例子展示在全局導航守衛中檢查元字段: ~~~ router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { // this route requires auth, check if logged in // if not, redirect to login page. if (!auth.loggedIn()) { next({ path: '/login', query: { redirect: to.fullPath } }) } else { next() } } else { next() // 確保一定要調用 next() } }) ~~~ `<span class="token punctuation" style="color: rgb(204, 204, 204);"></span>` # 過渡動效 `<router-view>`?是基本的動態組件,所以我們可以用?`<transition>`?組件給它添加一些過渡效果: ~~~ <transition> <router-view></router-view> </transition> ~~~ [Transition 的所有功能](https://cn.vuejs.org/guide/transitions.html)?在這里同樣適用。 ## [#](https://router.vuejs.org/zh/guide/advanced/transitions.html#%E5%8D%95%E4%B8%AA%E8%B7%AF%E7%94%B1%E7%9A%84%E8%BF%87%E6%B8%A1)單個路由的過渡 上面的用法會給所有路由設置一樣的過渡效果,如果你想讓每個路由組件有各自的過渡效果,可以在各路由組件內使用?`<transition>`?并設置不同的 name。 ~~~ const Foo = { template: ` <transition name="slide"> <div class="foo">...</div> </transition> ` } const Bar = { template: ` <transition name="fade"> <div class="bar">...</div> </transition> ` } ~~~ ## [#](https://router.vuejs.org/zh/guide/advanced/transitions.html#%E5%9F%BA%E4%BA%8E%E8%B7%AF%E7%94%B1%E7%9A%84%E5%8A%A8%E6%80%81%E8%BF%87%E6%B8%A1)基于路由的動態過渡 還可以基于當前路由與目標路由的變化關系,動態設置過渡效果: ~~~ <!-- 使用動態的 transition name --> <transition :name="transitionName"> <router-view></router-view> </transition> ~~~ ~~~ // 接著在父組件內 // watch $route 決定使用哪種過渡 watch: { '$route' (to, from) { const toDepth = to.path.split('/').length const fromDepth = from.path.split('/').length this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left' } } ~~~ 查看完整例子請[移步這里](https://github.com/vuejs/vue-router/blob/next/examples/transitions/app.js)。 # 數據獲取 有時候,進入某個路由后,需要從服務器獲取數據。例如,在渲染用戶信息時,你需要從服務器獲取用戶的數據。我們可以通過兩種方式來實現: * 導航完成之后獲取:先完成導航,然后在接下來的組件生命周期鉤子中獲取數據。在數據獲取期間顯示“加載中”之類的指示。 * 導航完成之前獲取:導航完成前,在路由進入的守衛中獲取數據,在數據獲取成功后執行導航。 從技術角度講,兩種方式都不錯 —— 就看你想要的用戶體驗是哪種。 ## [#](https://router.vuejs.org/zh/guide/advanced/data-fetching.html#%E5%AF%BC%E8%88%AA%E5%AE%8C%E6%88%90%E5%90%8E%E8%8E%B7%E5%8F%96%E6%95%B0%E6%8D%AE)導航完成后獲取數據 當你使用這種方式時,我們會馬上導航和渲染組件,然后在組件的?`created`?鉤子中獲取數據。這讓我們有機會在數據獲取期間展示一個 loading 狀態,還可以在不同視圖間展示不同的 loading 狀態。 假設我們有一個?`Post`?組件,需要基于?`$route.params.id`?獲取文章數據: ~~~ <template> <div class="post"> <div class="loading" v-if="loading"> Loading... </div> <div v-if="error" class="error"> {{ error }} </div> <div v-if="post" class="content"> <h2>{{ post.title }}</h2> <p>{{ post.body }}</p> </div> </div> </template> ~~~ ~~~ export default { data () { return { loading: false, post: null, error: null } }, created () { // 組件創建完后獲取數據, // 此時 data 已經被 observed 了 this.fetchData() }, watch: { // 如果路由有變化,會再次執行該方法 '$route': 'fetchData' }, methods: { fetchData () { this.error = this.post = null this.loading = true // replace getPost with your data fetching util / API wrapper getPost(this.$route.params.id, (err, post) => { this.loading = false if (err) { this.error = err.toString() } else { this.post = post } }) } } } ~~~ ## [#](https://router.vuejs.org/zh/guide/advanced/data-fetching.html#%E5%9C%A8%E5%AF%BC%E8%88%AA%E5%AE%8C%E6%88%90%E5%89%8D%E8%8E%B7%E5%8F%96%E6%95%B0%E6%8D%AE)在導航完成前獲取數據 通過這種方式,我們在導航轉入新的路由前獲取數據。我們可以在接下來的組件的?`beforeRouteEnter`?守衛中獲取數據,當數據獲取成功后只調用?`next`?方法。 ~~~ export default { data () { return { post: null, error: null } }, beforeRouteEnter (to, from, next) { getPost(to.params.id, (err, post) => { next(vm => vm.setData(err, post)) }) }, // 路由改變前,組件就已經渲染完了 // 邏輯稍稍不同 beforeRouteUpdate (to, from, next) { this.post = null getPost(to.params.id, (err, post) => { this.setData(err, post) next() }) }, methods: { setData (err, post) { if (err) { this.error = err.toString() } else { this.post = post } } } } ~~~ 在為后面的視圖獲取數據時,用戶會停留在當前的界面,因此建議在數據獲取期間,顯示一些進度條或者別的指示。如果數據獲取失敗,同樣有必要展示一些全局的錯誤提醒。 # 滾動行為 使用前端路由,當切換到新路由時,想要頁面滾到頂部,或者是保持原先的滾動位置,就像重新加載頁面那樣。?`vue-router`?能做到,而且更好,它讓你可以自定義路由切換時頁面如何滾動。 注意: 這個功能只在支持?`history.pushState`?的瀏覽器中可用。 當創建一個 Router 實例,你可以提供一個?`scrollBehavior`?方法: ~~~ const router = new VueRouter({ routes: [...], scrollBehavior (to, from, savedPosition) { // return 期望滾動到哪個的位置 } }) ~~~ `scrollBehavior`?方法接收?`to`?和?`from`?路由對象。第三個參數?`savedPosition`?當且僅當?`popstate`導航 (通過瀏覽器的 前進/后退 按鈕觸發) 時才可用。 這個方法返回滾動位置的對象信息,長這樣: * `{ x: number, y: number }` * `{ selector: string, offset? : { x: number, y: number }}`?(offset 只在 2.6.0+ 支持) 如果返回一個 falsy (譯者注:falsy 不是?`false`,[參考這里](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy))的值,或者是一個空對象,那么不會發生滾動。 舉例: ~~~ scrollBehavior (to, from, savedPosition) { return { x: 0, y: 0 } } ~~~ 對于所有路由導航,簡單地讓頁面滾動到頂部。 返回?`savedPosition`,在按下 后退/前進 按鈕時,就會像瀏覽器的原生表現那樣: ~~~ scrollBehavior (to, from, savedPosition) { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } } } ~~~ 如果你要模擬“滾動到錨點”的行為: ~~~ scrollBehavior (to, from, savedPosition) { if (to.hash) { return { selector: to.hash } } } ~~~ 我們還可以利用[路由元信息](https://router.vuejs.org/zh/guide/advanced/meta.html)更細顆粒度地控制滾動。查看完整例子請[移步這里](https://github.com/vuejs/vue-router/blob/next/examples/scroll-behavior/app.js)。 ## [#](https://router.vuejs.org/zh/guide/advanced/scroll-behavior.html#%E5%BC%82%E6%AD%A5%E6%BB%9A%E5%8A%A8)異步滾動 > 2.8.0 新增 你也可以返回一個 Promise 來得出預期的位置描述: ~~~ scrollBehavior (to, from, savedPosition) { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ x: 0, y: 0 }) }, 500) }) } ~~~ 將其掛載到從頁面級別的過渡組件的事件上,令其滾動行為和頁面過渡一起良好運行是可能的。但是考慮到用例的多樣性和復雜性,我們僅提供這個原始的接口,以支持不同用戶場景的具體實現。 # 路由懶加載 當打包構建應用時,Javascript 包會變得非常大,影響頁面加載。如果我們能把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應組件,這樣就更加高效了。 結合 Vue 的[異步組件](https://cn.vuejs.org/v2/guide/components-dynamic-async.html#%E5%BC%82%E6%AD%A5%E7%BB%84%E4%BB%B6)和 Webpack 的[代碼分割功能](https://doc.webpack-china.org/guides/code-splitting-async/#require-ensure-/),輕松實現路由組件的懶加載。 首先,可以將異步組件定義為返回一個 Promise 的工廠函數 (該函數返回的 Promise 應該 resolve 組件本身): ~~~ const Foo = () => Promise.resolve({ /* 組件定義對象 */ }) ~~~ 第二,在 Webpack 2 中,我們可以使用[動態 import](https://github.com/tc39/proposal-dynamic-import)語法來定義代碼分塊點 (split point): ~~~ import('./Foo.vue') // 返回 Promise ~~~ 注意 如果您使用的是 Babel,你將需要添加?[`syntax-dynamic-import`](https://babeljs.io/docs/plugins/syntax-dynamic-import/)?插件,才能使 Babel 可以正確地解析語法。 結合這兩者,這就是如何定義一個能夠被 Webpack 自動代碼分割的異步組件。 ~~~ const Foo = () => import('./Foo.vue') ~~~ 在路由配置中什么都不需要改變,只需要像往常一樣使用?`Foo`: ~~~ const router = new VueRouter({ routes: [ { path: '/foo', component: Foo } ] }) ~~~ ## [#](https://router.vuejs.org/zh/guide/advanced/lazy-loading.html#%E6%8A%8A%E7%BB%84%E4%BB%B6%E6%8C%89%E7%BB%84%E5%88%86%E5%9D%97)把組件按組分塊 有時候我們想把某個路由下的所有組件都打包在同個異步塊 (chunk) 中。只需要使用?[命名 chunk](https://webpack.js.org/guides/code-splitting-require/#chunkname),一個特殊的注釋語法來提供 chunk name (需要 Webpack > 2.4)。 ~~~ const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue') const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue') const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue') ~~~ Webpack 會將任何一個異步模塊與相同的塊名稱組合到相同的異步塊中。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看