Skip to content

Add [Zh-TW] Translation docs Traditional Chinese #1854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/zh-tw/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% include "./SUMMARY.md" %}
42 changes: 42 additions & 0 deletions docs/zh-tw/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

# vue-router 2
<!--email_off-->
> 注意: [email protected] 只適用於 Vue 2.x。0.7.x 版本的文檔請[移步這裡](https://github.com/vuejs/vue-router/tree/1.0/docs/zh-tw)。
<!--/email_off-->
**[版本說明](https://github.com/vuejs/vue-router/releases)**

- [安裝](installation.md)
- 基礎
- [開始](essentials/getting-started.md)
- [動態路由匹配](essentials/dynamic-matching.md)
- [嵌套路由](essentials/nested-routes.md)
- [編程式導航](essentials/navigation.md)
- [命名路由](essentials/named-routes.md)
- [命名視圖](essentials/named-views.md)
- [重定向 和 別名](essentials/redirect-and-alias.md)
- [向路由組件傳遞 props](essentials/passing-props.md)
- [HTML5 History 模式](essentials/history-mode.md)
- 進階
- [導航守衛](advanced/navigation-guards.md)
- [路由元信息](advanced/meta.md)
- [過渡動效](advanced/transitions.md)
- [數據獲取](advanced/data-fetching.md)
- [滾動行為](advanced/scroll-behavior.md)
- [懶加載](advanced/lazy-loading.md)
- API 文檔
- [Router 構造配置](api/options.md)
- [routes](api/options.md#routes)
- [mode](api/options.md#mode)
- [base](api/options.md#base)
- [linkActiveClass](api/options.md#linkactiveclass)
- [linkExactActiveClass](api/options.md#linkexactactiveclass)
- [scrollBehavior](api/options.md#scrollbehavior)
- [parseQuery / stringifyQuery](api/options.md#parsequery--stringifyquery)
- [fallback](api/options.md#fallback)
- [Router 實例](api/router-instance.md)
- [Properties](api/router-instance.md#properties)
- [Methods](api/router-instance.md#methods)
- [路由信息對象](api/route-object.md)
- [對組件注入](api/component-injections.md)
- [router-link](api/router-link.md)
- [router-view](api/router-view.md)
112 changes: 112 additions & 0 deletions docs/zh-tw/advanced/data-fetching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@

# 數據獲取

有時候,進入某個路由後,需要從服務器獲取數據。例如,在渲染用戶信息時,你需要從服務器獲取用戶的數據。我們可以通過兩種方式來實現:

- **導航完成之後獲取**:先完成導航,然後在接下來的組件生命週期鈎子中獲取數據。在數據獲取期間顯示『加載中』之類的指示。

- **導航完成之前獲取**:導航完成前,在路由進入的守衛中獲取數據,在數據獲取成功後執行導航。

從技術角度講,兩種方式都不錯 —— 就看你想要的用戶體驗是哪種。

## 導航完成後獲取數據

當你使用這種方式時,我們會馬上導航和渲染組件,然後在組件的 `created` 鈎子中獲取數據。這讓我們有機會在數據獲取期間展示一個 loading 狀態,還可以在不同視圖間展示不同的 loading 狀態。

假設我們有一個 `Post` 組件,需要基於 `$route.params.id` 獲取文章數據:

``` html
<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>
```

``` js
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
}
})
}
}
}
```

## 在導航完成前獲取數據

通過這種方式,我們在導航轉入新的路由前獲取數據。我們可以在接下來的組件的 `beforeRouteEnter` 守衛中獲取數據,當數據獲取成功後只調用 `next` 方法。

``` js
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
}
}
}
}
```

在為後面的視圖獲取數據時,用戶會停留在當前的界面,因此建議在數據獲取期間,顯示一些進度條或者別的指示。如果數據獲取失敗,同樣有必要展示一些全局的錯誤提醒。

49 changes: 49 additions & 0 deletions docs/zh-tw/advanced/lazy-loading.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

# 路由懶加載

當打包構建應用時,Javascript 包會變得非常大,影響頁面加載。如果我們能把不同路由對應的組件分割成不同的代碼塊,然後當路由被訪問的時候才加載對應組件,這樣就更加高效了。

結合 Vue 的[非同步組件](https://cn.vuejs.org/guide/components.html#非同步組件)和 Webpack 的[代碼分割功能](https://doc.webpack-china.org/guides/code-splitting-async/#require-ensure-/),輕鬆實現路由組件的懶加載。

首先,可以將非同步組件定義為返回一個 Promise 的工廠函數 (該函數返回的 Promise 應該 resolve 組件本身):

``` js
const Foo = () => Promise.resolve({ /* 組件定義對象 */ })
```

第二,在 Webpack 2 中,我們可以使用[動態 import](https://github.com/tc39/proposal-dynamic-import)語法來定義代碼分塊點 (split point):

``` js
import('./Foo.vue') // 返回 Promise
```

> 注意:如果您使用的是 Babel,你將需要添加 [`syntax-dynamic-import`](https://babeljs.io/docs/plugins/syntax-dynamic-import/) 插件,才能使 Babel 可以正確地解析語法。

結合這兩者,這就是如何定義一個能夠被 Webpack 自動代碼分割的非同步組件。

``` js
const Foo = () => import('./Foo.vue')
```

在路由配置中什麼都不需要改變,只需要像往常一樣使用 `Foo`:

``` js
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
```

### 把組件按組分塊

有時候我們想把某個路由下的所有組件都打包在同個非同步塊 (chunk) 中。只需要使用 [命名 chunk](https://webpack.js.org/guides/code-splitting-require/#chunkname),一個特殊的註釋語法來提供 chunk name (需要 Webpack > 2.4)。

``` js
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 會將任何一個非同步模組與相同的塊名稱組合到相同的非同步塊中。

53 changes: 53 additions & 0 deletions docs/zh-tw/advanced/meta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@

# 路由元信息

定義路由的時候可以配置 `meta` 欄位:

``` js
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` 欄位。

下面例子展示在全局導航守衛中檢查元欄位:

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

135 changes: 135 additions & 0 deletions docs/zh-tw/advanced/navigation-guards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@

# 導航守衛

>(譯者:『導航』表示路由正在發生改變。)

正如其名,`vue-router` 提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程中:全局的, 單個路由獨享的, 或者組件級的。

記住**參數或查詢的改變並不會觸發進入/離開的導航守衛**。你可以通過[觀察 `$route` 對象](../essentials/dynamic-matching.md#響應路由參數的變化)來應對這些變化,或使用 `beforeRouteUpdate` 的組件內守衛。

### 全局守衛

你可以使用 `router.beforeEach` 註冊一個全局前置守衛:

``` js
const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
// ...
})
```

當一個導航觸發時,全局前置守衛按照創建順序調用。守衛是非同步解析執行,此時導航在所有守衛 resolve 完之前一直處於 **等待中**。

每個守衛方法接收三個參數:

- **`to: Route`**: 即將要進入的目標 [路由對象](../api/route-object.md)

- **`from: Route`**: 當前導航正要離開的路由

- **`next: Function`**: 一定要調用該方法來 **resolve** 這個鈎子。執行效果依賴 `next` 方法的調用參數。

- **`next()`**: 進行管道中的下一個鈎子。如果全部鈎子執行完了,則導航的狀態就是 **confirmed** (確認的)。

- **`next(false)`**: 中斷當前的導航。如果瀏覽器的 URL 改變了(可能是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 `from` 路由對應的地址。

- **`next('/')` 或者 `next({ path: '/' })`**: 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。

- **`next(error)`**: (2.4.0+) 如果傳入 `next` 的參數是一個 `Error` 實例,則導航會被終止且該錯誤會被傳遞給 `router.onError()` 註冊過的回調。

**確保要調用 `next` 方法,否則鈎子就不會被 resolved。**

### 全局解析守衛

> 2.5.0 新增

在 2.5.0+ 你可以用 `router.beforeResolve` 註冊一個全局守衛。這和 `router.beforeEach` 類似,區別是在導航被確認之前,**同時在所有組件內守衛和非同步路由組件被解析之後**,解析守衛就被調用。

### 全局後置鈎子

你也可以註冊全局後置鈎子,然而和守衛不同的是,這些鈎子不會接受 `next` 函數也不會改變導航本身:

``` js
router.afterEach((to, from) => {
// ...
})
```

### 路由獨享的守衛

你可以在路由配置上直接定義 `beforeEnter` 守衛:

``` js
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
```

這些守衛與全局前置守衛的方法參數是一樣的。

### 組件內的守衛

最後,你可以在路由組件內直接定義以下路由導航守衛:

- `beforeRouteEnter`
- `beforeRouteUpdate` (2.2 新增)
- `beforeRouteLeave`

``` js
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`來訪問組件實例。在導航被確認的時候執行回調,並且把組件實例作為回調方法的參數。

``` js
beforeRouteEnter (to, from, next) {
next(vm => {
// 通過 `vm` 訪問組件實例
})
}
```

你可以 在 `beforeRouteLeave` 中直接訪問 `this`。這個離開守衛通常用來禁止用戶在還未保存修改前突然離開。可以通過 `next(false)` 來取消導航。

### 完整的導航解析流程

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` 的回調函數。

Loading