Skip to content

Commit 3f5a7dc

Browse files
Merge pull request #72 from dear-lizhihua/gitlocalize-117
zh/routing.md
2 parents 07f4240 + 8b76694 commit 3f5a7dc

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

zh/routing.md

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# 路由和代码分割
2+
3+
## 使用 `vue-router` 的路由
4+
5+
你可能已经注意到,我们的服务器代码使用了一个 `*` 处理程序,它接受任意 URL。这允许我们将访问的 URL 传递到我们的 Vue 应用程序中,然后对客户端和服务器复用相同的路由配置!
6+
7+
为此,建议使用官方提供的 `vue-router`。我们首先创建一个文件,在其中创建 router。注意,类似于 `createApp`,我们也需要给每个请求一个新的 router 实例,所以文件导出一个 `createRouter` 函数:
8+
9+
```js
10+
// router.js
11+
import Vue from 'vue'
12+
import Router from 'vue-router'
13+
Vue.use(Router)
14+
export function createRouter () {
15+
return new Router({
16+
mode: 'history',
17+
routes: [
18+
// ...
19+
]
20+
})
21+
}
22+
```
23+
24+
然后更新 `app.js`:
25+
26+
```js
27+
// app.js
28+
import Vue from 'vue'
29+
import App from './App.vue'
30+
import { createRouter } from './router'
31+
export function createApp () {
32+
// 创建 router 实例
33+
const router = createRouter()
34+
const app = new Vue({
35+
// 注入 router 到根 Vue 实例
36+
router,
37+
render: h => h(App)
38+
})
39+
// 注入 router 到根 Vue 实例
40+
return { app, router }
41+
}
42+
```
43+
44+
现在我们需要在 `entry-server.js` 中实现服务器端路由逻辑(server-side routing logic):
45+
46+
```js
47+
// entry-server.js
48+
import { createApp } from './app'
49+
export default context => {
50+
// 因为有可能会是异步路由钩子函数或组件,所以我们将返回一个 Promise,
51+
// 以便服务器能够等待所有的内容在渲染前,
52+
// 就已经准备就绪。
53+
return new Promise((resolve, reject) => {
54+
const { app, router } = createApp()
55+
// 设置服务器端 router 的位置
56+
router.push(context.url)
57+
// 等到 router 将可能的异步组件和钩子函数解析完
58+
router.onReady(() => {
59+
const matchedComponents = router.getMatchedComponents()
60+
// 匹配不到的路由,执行 reject 函数,并返回 404
61+
if (!matchedComponents.length) {
62+
return reject({ code: 404 })
63+
}
64+
// Promise 应该 resolve 应用程序实例,以便它可以渲染
65+
resolve(app)
66+
}, reject)
67+
})
68+
}
69+
```
70+
71+
假设服务器 bundle 已经完成构建(请再次忽略现在的构建设置),服务器用法看起来如下:
72+
73+
```js
74+
// server.js
75+
const createApp = require('/path/to/built-server-bundle.js')
76+
server.get('*', (req, res) => {
77+
const context = { url: req.url }
78+
createApp(context).then(app => {
79+
renderer.renderToString(app, (err, html) => {
80+
if (err) {
81+
if (err.code === 404) {
82+
res.status(404).end('Page not found')
83+
} else {
84+
res.status(500).end('Internal Server Error')
85+
}
86+
} else {
87+
res.end(html)
88+
}
89+
})
90+
})
91+
})
92+
```
93+
94+
## 代码分割
95+
96+
应用程序的代码分割或惰性加载,有助于减少浏览器在初始渲染中下载的资源体积,可以极大地改善大体积 bundle 的可交互时间(TTI - time-to-interactive)。这里的关键在于,对初始首屏而言,"只加载所需"。
97+
98+
Vue 提供异步组件作为第一类的概念,将其与 [webpack 2 所支持的使用动态导入作为代码分割点](https://webpack.js.org/guides/code-splitting-async/)相结合,你需要做的是:
99+
100+
```js
101+
// 这里进行修改……
102+
import Foo from './Foo.vue'
103+
// 改为这样:
104+
const Foo = () => import('./Foo.vue')
105+
```
106+
107+
如果你正在构建纯客户端 Vue 应用程序,这将在任何情况下运行。但是,在 SSR 中使用时有一些限制。首先,你需要在启动渲染之前先在服务器上解析所有的异步组件,否则你将在标记中获得一个空的占位符。在客户端,你还需要在开始混合之前执行此操作,否则客户端将遇到内容不匹配错误。
108+
109+
这使得在应用程序中的任意位置使用异步组件变得有点棘手(我们将来可能会改进这一点)。但是,**如果你在路由级别完成以上,可以实现无缝运行**(即在路由配置中使用异步组件),因为在解析路由时,`vue-router` 将自动解析匹配的异步组件。你需要做的是确保在服务器和客户端上都使用 `router.onReady`。我们已经在我们的服务器入口(server entry)中实现过了,现在我们只需要更新客户端入口(client entry):
110+
111+
```js
112+
// entry-client.js
113+
import { createApp } from './app'
114+
const { app, router } = createApp()
115+
router.onReady(() => {
116+
app.$mount('#app')
117+
})
118+
```
119+
120+
异步路由组件的路由配置示例:
121+
122+
```js
123+
// router.js
124+
import Vue from 'vue'
125+
import Router from 'vue-router'
126+
Vue.use(Router)
127+
export function createRouter () {
128+
return new Router({
129+
mode: 'history',
130+
routes: [
131+
{ path: '/', component: () => import('./components/Home.vue') },
132+
{ path: '/item/:id', component: () => import('./components/Item.vue') }
133+
]
134+
})
135+
}
136+
```

0 commit comments

Comments
 (0)