vue的路由-vue router(一)


一、路由的基本使用

Vue + Vue Router 创建单页应用非常简单:通过 Vue.js,我们已经用组件组成了我们的应用。当加入 Vue Router 时,需要做的就是将我们的组件映射到路由上,让 Vue Router 知道在哪里渲染它们。

HTML

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!--使用 router-link 组件进行导航 -->
    <!--通过传递 `to` 来指定链接,相当于 `href` -->
    <!-- <router-link> 将呈现一个带有正确 `href` 属性的 <a> 标签 -->
    <router-link to="/">首页</router-link>
    <router-link to="/about">About组件</router-link>
  </p>
  
  <!-- 路由出口:路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>

router-link

没有使用常规的 a 标签,而是使用一个自定义组件 router-link 来创建链接。这使得 Vue Router 可以在不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码。

router-view

将显示与 url 对应的组件。可以把它放在任何地方,以适应你的布局。

JavaScript

index.js:

import Vue from 'vue'
// 1.引入vue-router
import Router from 'vue-router'
// 2.定义或引入路由组件
const Home = { template: '<div>首页</div>' }
import About from '@/pages/About'

Vue.use(Router)

// 3. 创建路由实例并传递 routes 配置
export default new Router({
  // 4.定义路由:每个路由都需要映射到一个组件
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    }, {
      path: '/about',
      name: 'About',
      component: About
    }
  ]
})

main.js:

// 5.创建并挂载根实例
import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

可以在任意组件中以 this.$ router 的形式访问路由实例,以 this.$ route 的形式访问当前路由。
About.vue:

export default {
  computed: {
    username() {
      // 获取当前路由参数params
      return this.$route.params.username
    },
  },
  methods: {
    goToIndex() {
      // 跳转到首页
      this.$router.push('/');
    },
  },
}

二、带参数的动态路由匹配

很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但用户 ID 不同。在 Vue Router 中,我们可以在 路径 中使用一个 动态字段 来实现,我们称之为 路径参数

import User from '@/pages/User'

export default new Router({
  // 4.定义路由:每个路由都需要映射到一个组件
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    }, {
     // 动态字段以冒号开始
      path: '/user/:id',
      name: User,
      component: User
    }
  ]
})

现在像 /users/123/users/456 这样的 URL 都可以访问到 User 组件。
路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params 的形式暴露出来。因此,我们可以通过更新 User 的模板来呈现当前的用户 ID。

User.vue:

<template>
  <div>
    <span>用户ID{{$route.params.id}}</span>
  </div>
</template>

也可以在同一个路由中设置 多个路径参数,它们都会映射到 this.$route.params 上的相应字段。例如:

匹配模式匹配路径$route.params
/users/:username/users/hl{ username: ‘hl’ }
/users/:username/posts/:postId/users/hl/posts/123{ username: ‘hl’, postId: ‘123’ }

三、嵌套路由

一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,通过 Vue Router,可以使用嵌套路由配置来表达这种关系。

router/index.js:使用 children 来配置嵌套路由

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

import HelloSon1 from '@/components/hello/HelloSon1'
import HelloSon2 from '@/components/hello/HelloSon2'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      // 配置嵌套路由:
      children: [{
       // 当 /#/hello1 匹配成功
       // Hello1 将被渲染到 HelloWorld1 的 <router-view> 内部
        path: 'hello1',
        name: 'HelloSon1',
        component: HelloSon1
      }, {
       // 当 /#/hello2 匹配成功
       // Hello2 将被渲染到 HelloWorld2 的 <router-view> 内部
        path: 'hello2',
        name: 'HelloSon2',
        component: HelloSon2
      }]
    }
  ]
})

App.vue 还是保持不变:

<div id="app">
	<img src="./assets/logo.png">
	<router-view/>
</div>

上面的 < router-view />是一个顶层的 router-view。它渲染 顶层 路由匹配的组件。同样地,组件中也可以包含自己嵌套的 < router-view />。例如我们在 HelloWorld 组件的模板内添加一个 < router-view />:

<div class="hello">
	<span>{{msg}}</span>
    <p>
      <router-link to="/hello1">hello1</router-link>
      <router-link to="/hello2">hello2</router-link>
    </p>
    <-- 对应在在路由中配置的 children -->
    <router-view />
</div>    

首页:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

如上所示,children 配置只是另一个路由数组,就像 routes 本身一样。因此,可以根据需要,不断地嵌套视图。

四. 编程式导航

除了使用 < router-link > 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

导航到不同的位置

this.$router.push(...);

当你点击 < router-link > 时,内部会调用这个方法,所以点击 < router-link :to=“…'”> 相当于调用 this.$router.push(…) 。

声明式编程式
< router-link :to=“…” >router.push(…)

该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

// 字符串路径
router.push('/helloworld')

// 带有路径的对象
router.push({ path: '/user/123' })

// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { id: 123 } })

// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })

// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })

注意:name 配合 params 一起使用, path 和 query 一起使用; params 和 path 不能一起使用

替换当前位置

this.$router.replace(...);

它的作用类似于 this.$router.push,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。

也可以直接在传递给 router.push 的 routeLocation 中增加一个属性 replace: true

this.$router.push({path: '/helloworld', replace: true})
// 相当于
this.$router.replace({path: '/helloworld'})

横跨历史

该方法采用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于 window.history.go(n)

// 向前移动一条记录,与 router.forward() 相同
this.$router.go(1)

// 返回一条记录,与 router.back() 相同
this.$router.go(-1)

// 前进 3 条记录
this.$router.go(3)

// 如果没有那么多记录,静默失败
this.$router.go(-100)
this.$router.go(100)

篡改历史

router.push、router.replace 和 router.go 是 window.history.pushState、window.history.replaceState 和 window.history.go 的翻版,它们确实模仿了 window.history 的 API。

值得一提的是,无论在创建路由器实例时传递什么样的 history 配置,Vue Router 的导航方法( push、replace、go )都能始终正常工作。

五. 命名路由

除了 path 之外,还可以为任何路由提供 name,有以下优点:

  • 没有硬编码的 URL;
  • params 的自动编码/解码;
  • 防止在 url 中出现打字错误;
  • 绕过路径排序(如显示一个)。

要链接到一个命名的路由,可以向 router-link 组件的 to 属性传递一个对象:

<router-link :to="{ name: 'User', params: { username: 'hl' }}">
  User
</router-link>

这跟代码调用 router.push() 是一回事:

this.$router.push({ name: 'User', params: { username: 'hl' } })

在这两种情况下,路由将导航到路径 /user/hl

六. 命名视图

有时候想同时展示多个视图,而不是嵌套展示。
例如:创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。
如果 router-view 没有设置名字,那么默认为 default

<router-view class="view left-sidebar" name="LeftSidebar"></router-view>
<router-view class="view content"></router-view>
<router-view class="view right-sidebar" name="RightSidebar"></router-view>

一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件,使用 components 配置( 带上 s ):

export default new Router({
  routes: [
    {
      path: '/',
      // 多个视图
      components: {
        default: Content,
        // LeftSidebar: LeftSidebar 的缩写
        // 与 `<router-view>` 上的 `name` 属性匹配
        LeftSidebar,
        RightSidebar,
      }
    }
  ]
})

嵌套命名视图

我们也有可能使用命名视图创建 嵌套视图 的复杂布局。

UserSettings.vue :

<div>
  <h1>User Settings</h1>
  <NavBar />
  <router-view />
  <router-view name="helper" />
</div>

那么就可以通过下面的路由配置来实现上面的布局:

{
  path: '/settings',
  component: UserSettings,
  children: [{
    path: 'emails',
    component: UserEmailsSubscriptions
  }, {
    path: 'profile',
    // 多个视图
    components: {
      default: UserProfile,
      helper: UserProfilePreview
    }
  }]
}

七. 重定向和别名

重定向

重定向也是通过 routes 配置来完成,下面例子是从 / 重定向到 /user

export default new Router({
  routes: [
    {
      path: '/',
      redirect: '/user'
    } 
  ]
})

重定向的目标也可以是一个命名的路由:

export default new Router({
  routes: [
    {
      path: '/',
      redirect: { name: 'User' }
    } 
  ]
})

甚至是一个方法,动态返回重定向目标:

export default new Router({
  routes: [
    {
      path: '/',
      redirect: to => {
      // 方法接收目标路由作为参数
      // return 重定向的字符串路径/路径对象
      return 'user';
      return { path: '/user', query: { username: 'hl' } }
    },
    } 
  ]
})

注意:在写 redirect 的时候,可以省略 component 配置,因为它从来没有被直接访问过,所以没有组件要渲染。唯一的例外是 嵌套路由 :如果一个路由记录有 childrenredirect 属性,它也应该有 component 属性。

别名

重定向 是指当用户访问 / 时,URL 会被 /user 替换,然后匹配成 /user。那么什么是别名呢?

/ 别名为 /user,意味着当用户访问 /user 时,URL 仍然是 /,但会被匹配为用户正在访问 /user

export default new Router({
  routes: [
    {
      path: '/',
      component: Helloworld, 
      // 别名
      alias: '/user'
    } 
  ]
})

路径为 /user,但是访问的是 / ,对应 HelloWorld.vue :
在这里插入图片描述

通过 别名 ,可以自由地将 UI 结构映射到一个任意的 URL,且不受配置的嵌套结构的限制。使别名以 / 开头,以使嵌套路径中的路径成为绝对路径。甚至可以将两者结合起来,用一个数组提供多个别名:

const routes = [
  {
    path: '/user',
    component: User,
    children: [
      // 为这 3 个 URL 呈现 User
      // - /user
      // - /view
      // - /user/index
      { path: '', component: Content, alias: ['/view', 'index'] },
    ],
  },
]

如果路由有参数,请确保在任何绝对别名中包含它们:

const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      // 为这 3 个 URL 呈现 UserDetails
      // - /user/24
      // - /user/24/profile
      // - /24
      { path: 'profile', component: UserDetails, alias: ['/:id', ''] },
    ],
  },
]

八. 将 props 传递给路由组件

在组件中可以使用 $route 获取传递的参数,但它只能用于特定的 URL,所以限制了组件的灵活性,另一种方式我们可以通过 props 配置来解除这种行为:

使用 $route 获取传递的参数:

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

const routes = [{ path: '/user/:id', component: User }]

通过 props 获取参数:

const User = {
  // 请确保添加一个与路由参数完全相同的 prop 名
  props: ['id'],
  template: '<div>User {{ id }}</div>'
}

// 设置 props
const routes = [{ path: '/user/:id', component: User, props: true }]

布尔模式

上面例子即为 布尔模式 。
props 设置为 true 时,$route.params 将被设置为组件的 props

对象模式

props 是一个 对象 时,它将原样设置为组件 props
props 是静态的时候很有用,例如弹窗的显隐:

const User = {
  props: ['userPopup1', 'userPopup2'],
  template: '<div>
  	<p v-if='userPopup1'>弹窗1</p>
  	<p v-if='userPopup2'>弹窗2</p>
  </div>'
}

const routes = [
  {
    path: '/user',
    component: User,
    props: { userPopup1: false, userPopUp2: true }
  }
]

函数模式

创建一个返回 props 的函数,可以将参数转换为其他类型,将静态值与基于路由的值相结合等等。

const Search = {
  template: '<div>{{ id }}</div>'
  props: ['id']
}

const routes = [
  {
    path: '/search',
    component: Search,
    props: route => ({ id: route.query.id })
  }
]

URL /search?id=123 将传递 {id: 123} 作为 props 传给 Search 组件。

九. 不同的历史模式

vue-router 分为 hashhistory 模式。
前者为其默认模式,url 的表现形式为:http://yoursite.com#home,比较难看。
后者的 url 表现形式为:http://yoursite.com/home,比较美观。
但如果要使用history模式,我们需要在后端进行额外配置

export default new Router({
 // history模式的配置方法
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    }
  ]
})

服务器配置请参考官方链接:服务器配置示例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值