Vue Router

Vue Router

任何组件内通过 this.$router 访问路由器,可以通过 this.$route 访问当前路由

回退

1
2
3
goBack() {
window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/')
}

动态路由匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
{ path: '/user/:username/post/:post_id', component: User }
]
})

// 接受参数
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
this.$route.params.id
当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
1
2
3
4
5
6
7
8
9
10
watch: {
$route(to, from) {
// 对路由变化作出响应...
}
// 导航守卫
beforeRouteUpdate (to, from, next) {
// react to route changes...
// don't forget to call next()
}
}

捕获所有路由

1
2
3
4
5
6
7
8
{
// 会匹配所有路径
path: '*'
}
{
// 会匹配以 `/user-` 开头的任意路径
path: '/user-*'
}

当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:

1
2
3
4
5
6
// 给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// 给出一个路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'

路由嵌套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<div id="app">
<router-view></router-view>
</div>

const User = {
template: `
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view></router-view>
</div>`
}

const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
// 当 /user/:id 匹配成功,
// UserHome 会被渲染在 User 的 <router-view>
{ path: '', component: UserHome },

// ...其他子路由
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view>
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view>
path: 'posts',
component: UserPosts
}
]
}
]
})

编程式的导航

声明式 编程式
router-link :to=”…” router.push(…)
1
2
3
4
5
6
7
8
9
10
11
12
13
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
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

后退或前进

1
2
3
4
5
6
7
8
9
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

命名路由

1
2
3
4
5
6
7
8
9
10
11
12
13
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
}
]
})

<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

router.push({ name: 'user', params: { userId: 123 }})

命名视图

1
2
3
4
5
6
<div>
<h1>User Settings</h1>
<NavBar/>
<router-view/>
<router-view name="helper"/>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
path: '/settings',
// 你也可以在顶级路由就配置命名视图
component: UserSettings,
children: [{
path: 'emails',
component: UserEmailsSubscriptions
}, {
path: 'profile',
components: {
default: UserProfile,
helper: UserProfilePreview
}
}]
}

重定向和别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 重定向的 字符串路径/路径对象
}}
]
})

const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})

路由组件传参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  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 }
}
]
})

Vue Router 传参

params 传值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User, name:'user',}
]
})

// 传值
this.$router.push({
name:"'user'",//这个name就是你刚刚配置在router里边的name
params:{
userId:"10011"
}
})

// 取值
this.$route.params.userId

query 传值

1
2
3
4
5
6
<template>
<router-link
:to="{ path: '/log', query: { name1: 'haha', name2: 'enen' } }"
>
</router-link>
</tempalte>
1
2
3
4
5
6
7
8
9
10
11
//  传值
this.$router.push({
path:"/user",//这个path就是你在router/index.js里边配置的路径
query:{
userId:"10011"
}
})

// 取值
this.$router.currentRoute.query.userId
this.$route.query.userId

基础路径

1
2
3
4
5
6
7
8
9
10
//  base 基础路径
const router = new VueRouter({
mode: 'history', // 只有 history 模式下 base 才起作用
base: '/app', // 基础路径 默认为 /
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
{ path: '/user/:username/post/:post_id', component: User }
]
})

hase 模式下 base 不起作用,可以用路由嵌套的方式加上前缀


相关资料

vue Router
vue $router 路由传参的4种方法详解
vue router跳转方法
vite —— 一种尤雨溪开发的新的、更快地 web 开发工具
vite

Nuxt 从入门到实践

Nuxt 常用配置项

配置 IP 和端口

1
2
3
4
5
6
7
8
9
10
//  package.json
"scripts": {
// ...
},
"config":{
"nuxt":{
"host":"127.0.0.1",
"port":"1818"
}
},

配置全局CSS

1
2
3
4
5
6
7
//  nuxt.config.js
head: {
// ...
},
css: [
'~assets/css/normailze.css',
],

配置webpack的loader

在nuxt.config.js里是可以对webpack的基本配置进行覆盖的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//  nuxt.config.js
build: {
loaders:[
{
test:/\.(png|jpe?g|gif|svg)$/,
loader:"url-loader",
query:{
limit:10000,
name:'img/[name].[hash].[ext]'
}
}
],

/*
** Run ESLint on save
*/
extend (config, { isDev, isClient }) {
if (isDev && isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
}
}

Nuxt 路由

Nuxt.js 路由会根据 pages 目录中提供的Vue文件自动为您生成配置。

路由跳转传参

1
2
3
4
5
6
7
<template>
<!--路由跳转传参-->
<nuxt-link :to="{name:'news',params:{newsId:3306}}">NEWS</nuxt-link>

<!--路由接收参数-->
<p>NewsID:{{$route.params.newsId}}</p>
</template>

动态路由跳转传参

以下画线为前缀的Vue文件就是动态路由,然后在文件里边有 $route.params.id来接收参数

1
2
3
<template>
<nuxt-link :to="{name:'news-id',params:{id:123}}">News-1</nuxt-link>
</template>

动态参数校验

1
2
3
4
5
6
7
8
<script>
export default {
validate ({ params }) {
// Must be a number
return /^\d+$/.test(params.id)
}
}
</script>

路由切换动画

全局动画

1
2
3
4
5
6
7
/* assets/css/main.css */
.page-enter-active, .page-leave-active {
transition: opacity 2s;
}
.page-enter, .page-leave-active {
opacity: 0;
}
1
2
// nuxt.config.js
css:['assets/css/main.css'],

单页动画

1
2
3
4
5
6
7
8
9
/* assets/css/main.css */
.test-enter-active, .test-leave-active {
transition: all 2s;
font-size:12px;
}
.test-enter, .test-leave-active {
opacity: 0;
font-size:40px;
}
1
2
3
4
5
<script>
export default {
transition:'test'
}
</script>

Views 布局

默认模板

根目录下创建一个 app.html 就可实现

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<!-- 读取的是nuxt.config.js里的信息 -->
{{ HEAD }}
</head>
<body>
<p>jspang.com 技术胖的博客</p>
<!-- pages文件夹下的主体页面 -->
{{ APP }}
</body>
</html>

默认布局

1
2
3
4
5
6
7
<!-- layouts/default.vue -->
<template>
<div>
<p>JSPang.com 技术胖的博客</p>
<nuxt/>
</div>
</template>

自定义布局

例如:创建博客布局 在layouts 新建一个 blog.vue。

1
2
3
4
5
6
7
<!--layouts/blog.vue-->
<template>
<div>
<div>My blog navigation bar here</div>
<Nuxt />
</div>
</template>

使用博客布局

1
2
3
4
5
6
7
8
9
10
<!--pages/posts.vue-->
<template>
<!-- Your template -->
</template>
<script>
export default {
layout: 'blog'
// page component definitions
}
</script>

自定义错误页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--layouts/error.vue-->
<template>
<div>
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>An error occurred</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>

<script>
export default {
props: ['error'],
layout: 'error' // you can set a custom layout for the error page
}
</script>

SEO meta、title

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script>
export default {
data(){
return{
title:this.$route.params.title,
}
},
// 独立设置 head 信息
head(){
return{
title:this.title,
meta:[
{hid:'description',name:'news',content:'This is news page'}
]
}
}
}
</script>
注意:为了避免子组件中的meta标签不能正确覆盖父组件中相同的标签而产生重复的现象,建议利用 hid 键为meta标签配一个唯一的标识编号。

数据请求

安装 Axios

1
npm install axios --save
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<div>
<h1>姓名:{{info.name}}</h1>
<h2>年龄:{{info.age}}</h2>
<h2>兴趣:{{info.interest}}</h2>
</div>
</template>
<script>
import axios from 'axios'
export default {
data(){
return {
name:'hello World',
}
},
// promise
asyncData(){
return axios.get('https://api.myjson.com/bins/8gdmr')
.then((res)=>{
console.log(res)
return {info:res.data}
})
}
// await
async asyncData(){
let {data}=await axios.get('https://api.myjson.com/bins/8gdmr')
return {info: data}
}
}
</script>

静态资源的引入及打包

直接引入图片

1
2
3
<template>
<div><img src="~static/logo.png" /></div>
</template>

css 图片的引入

1
2
3
4
5
6
7
<style>
.diss{
width: 300px;
height: 100px;
background-image: url('~static/logo.png')
}
</style>

打包静态HTML并运行

1
npm run generate

live-server 可以查看打包后的文件


相关资料
[代码沙盒]路由
[代码沙盒]Views布局使用
技术胖Nuxt.js教程开启SSR渲染
[视频]技术胖Nuxt.js免费视频教程 开启SSR渲染

You need to set client_id and slot_id to show this AD unit. Please set it in _config.yml.