Vuejs(三):Vuejs路由

一:vue-cli2创建项目

F:\WWWROOT\vuepro>vue init webpack testrouter
F:\WWWROOT\vuepro>cd testrouter
F:\WWWROOT\vuepro\testrouter>npm run dev

Vuejs路由

二:前端路由

随着Ajax的出现, 有了前后端分离的开发模式。后端只提供API来返回数据, 前端通过Ajax获取数据, 并且可以通过JavaScript将数据渲染到页面中。这样做最大的优点就是前后端责任的清晰, 后端专注于数据上, 前端专注于交互和可视化上。并且当移动端(iOS/Android)出现后, 后端不需要进行任何处理, 依然使用之前的一套API即可。目前很多的网站依然采用这种模式开发。
单页面富应用阶段:其实SPA最主要的特点就是在前后端分离的基础上加了一层前端路由。也就是前端来维护一套路由规则。
前端路由的核心是什么呢?改变URL,但是页面不进行整体的刷新。

2.1 URL的hash

URL的hash
URL发生了改变,但是整个页面不会被刷新

2.2 HTML的history模式

history接口是HTML5新增的, 它有五种模式改变URL而不刷新页面
history
history.pushState()跳转后URL不能返回
history.replaceState()跳转后可以返回

三:vue-router

如果在使用脚手架创建项目时没有安装路由,那么使用下面的命令安装:

npm install vue-router --save

在src目录下创建router目录,然后在router目录创建index.js文件:

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
    // 这里写路由规则
]
const router = new VueRouter({
  routes
})
export default router

在main.js文件中导入router

import Vue from 'vue'
import App from './App'
import router from './router'	# 默认会找到/router/index.js文件
Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,						# 注册路由
  render: h => h(App)
})

3.1 使用vue-router

使用vue-router的步骤:

  • 第一步: 创建路由组件
  • 第二步: 配置路由映射: 组件和路径映射关系
  • 第三步: 使用路由: 通过router-link和router-view

首先在components目录下创建两个组件:Home.vue, About.vue,然后编写路由规则:

import Home from '../components/Home'
import About from '../components/About'

Vue.use(VueRouter)
const routes = [
    // 这里写路由规则
  {
    path: '/home',
    component: Home
  },
  {
    path: '/about',
    component: About
  }
]

在App.vue文件中通过router-link与router-view让其最终渲染到页面

<template>
  <div id="app">
    <router-link to="/home">首页</router-link>		# router-link默认最终会渲染成a标签
    <router-link to="/about">关于</router-link>
    <router-view></router-view>						# router-view的作用是让路由对应的组件显示在哪里,写在router-link下面,那么组件内容显示在下方,反之显示在上方
  </div>
</template>

router-link: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个a标签.
router-view: 该标签会根据当前的路径, 动态渲染出不同的组件.
网页的其他内容, 比如顶部的标题/导航, 或者底部的一些版权信息等会和router-view处于同一个等级.
在路由切换时, 切换的是router-view挂载的组件, 其他内容不会发生改变.
Vue-router

3.2 设置默认首页

const routes = [
  {
    path: '',			# 也可以写成:path:'/',
    redirect: '/home'	# 重定向到url /home
  },
  {
    path: '/home',
    component: Home
  },
  {
    path: '/about',
    component: About
  }
]

3.3 修改路由的显示方式

我们前面说过改变路径的方式有两种:

  • URL的hash(默认的路由方式)
  • HTML5的history

默认情况下, 路径的改变使用的URL的hash。如果希望使用HTML5的history模式, 非常简单, 进行如下配置即可

const router = new VueRouter({
  routes,
  mode: 'history'
})

Vuejs路由

3.4 router-link

在前面的router-link中, 我们只是使用了一个属性: to, 用于指定跳转的路径。
router-link还有一些其他属性:

  • tag: tag可以指定router-link之后渲染成什么组件, 比如下面的代码会被渲染成一个li元素, 而不是a
  • replace: replace不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中
  • active-class: 当router-link对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置active-class可以修改默认的名称.
    在进行高亮显示的导航菜单或者底部tabbar时, 会使用到该类.
    但是通常不会修改类的属性, 会直接使用默认的router-link-active即可.
<router-link to='/home' tag='li' replace>	# 渲染成li标签

3.5 通过代码跳转路由

<template>
  <div id="app">
    <button @click="homeClick">首页</button>
    <button @click="aboutClick">关于</button>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App',
  methods: {
    homeClick() {
      // this.$router.push('/home')
      this.$router.replace('/home')
    },
    aboutClick() {
      this.$router.push('/about')
    }
  }
}
</script>

3.6 动态路由

在某些情况下,一个页面的path路径可能是不确定的,比如我们进入用户界面时,希望是如下的路径:

  • /user/aaaa或/user/bbbb
  • 除了有前面的/user之外,后面还跟上了用户的ID
  • 这种path和Component的匹配关系,我们称之为动态路由(也是路由传递数据的一种方式)。

App.vue路由展示:

<template>
  <div id="app">
    <router-link to="/home">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-link :to="'/user/' + username">User</router-link> # 动态绑定to属性,因为username是动态获取(假设)的数据
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: 'App',
  data() {
    return {
      username: 'lisi'
    }
  }
}
</script>

因为要传递参数,所以路由规则的写法如下 (router/index.js):

  {
    path: '/user/:username',
    component: User
  }

路由组件 user的内容如下:

<template>
  <div>
    <h2>User page</h2>
    <h2>{{username}}</h2>
    // <h2>{{$route.params.username}}</h2>
  </div>
</template>
<script>
  export default {
    name: "User",
    computed: {
      username() {
        // this.$route:哪个路由处于活跃状态,this.$route就是谁
        return this.$route.params.username	# 获取路由中的username参数
      }
    }
  }
</script>
$route和$router是有区别的
$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法
$route为当前router跳转对象里面可以获取name、path、query、params等 

3.7 路由的懒加载

官方解释:当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
官方在说什么呢?
首先, 我们知道路由中通常会定义很多不同的页面,这个页面最后被打包在哪里呢? 一般情况下, 是放在一个js文件中。但是, 页面这么多放在一个js文件中, 必然会造成这个页面非常的大。如果我们一次性从服务器请求下来这个页面, 可能需要花费一定的时间, 甚至用户的电脑上还出现了短暂空白的情况。那么如何避免这种情况呢? 使用路由懒加载就可以了。
路由懒加载做了什么?路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块。只有在这个路由被访问到的时候, 才加载对应的组件。
路由懒加载后的效果如下:
vuejs路由懒加载

const Home = () => import('../components/Home')
const About = () => import('../components/About')
const User = () => import('../components/User')

3.8 路由的嵌套

嵌套路由是一个很常见的功能:
比如在home页面中, 我们希望通过/home/news和/home/message访问一些内容.
一个路径映射一个组件, 访问这两个路径也会分别渲染两个组件.
路径和组件的关系如下:
Vuejs路由的嵌套
实现嵌套路由有两个步骤:

  • 创建对应的子组件, 并且在路由映射中配置对应的子路由.
  • 在组件内部使用router-view标签.

路由规则如下:

{
    path: '/home',
    component: Home,
    children: [
      {
        path: '',
        redirect: 'news'
      },
      {
        path: 'news',			# 前面不需要加/,vuejs会自动拼接
        component: HomeNews,
      },
      {
        path: 'message',
        component: HomeMessage
      }
    ]
  },

因为是Home路由下的子路由,所以两个子组件都在Home组件下展示:

<template>
  <div>
    <h2>Home</h2>
    <router-link to="/home/news">News</router-link>			# 这里必须要写全路径
    <router-link to="/home/message">Message</router-link>
    <router-view></router-view>
  </div>
</template>

展示效果如下图:
Vuejs路由嵌套

3.9 路由传参

传递参数主要有两种类型: params和query
params的类型:

  • 配置路由格式: /router/:id
  • 传递的方式: 在path后面跟上对应的值
  • 传递后形成的路径: /router/123, /router/abc

query的类型:

  • 配置路由格式: /router, 也就是普通配置
  • 传递的方式: 对象中使用query的key作为传递方式
  • 传递后形成的路径: /router?id=123, /router?id=abc

如何使用它们呢? 也有两种方式: router-link的方式和JavaScript代码方式Vuejs路由传参
传递参数方式一: router-link
路由规则:

{
    path: '/profile',
    component: Profile
  }

路由展示:

<template>
  <div id="app">
    <router-link to="/home">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-link :to="{path: '/profile', query: {name: 'andy', age: 18}}">Profile</router-link>
    <router-view></router-view>
  </div>

接收参数:

<template>
  <div>
    <h2>Profile page</h2>
    <h2>{{$route.query.name}}</h2>
    <h2>{{$route.query.age}}</h2>
  </div>
</template>

传递参数方式二: JavaScript代码

# App.vue
<template>
  <div id="app">
    <router-link to="/home">Home</router-link>
    <router-link to="/about">About</router-link>
<!--    <router-link :to="{path: '/profile', query: {name: 'andy', age: 18}}">Profile</router-link>-->
    <button @click="profileClick">档案</button>
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: 'App',
  data() {
    return {
      username: 'lisi'
    }
  },
  methods: {
    profileClick() {
      this.$router.push({
        path: '/profile',
        query: {
          name: 'Andy',
          age: 17
        }
      })
    }
  }
}
</script>

3.10 导航守卫

我们来考虑一个需求: 在一个SPA应用中, 如何改变网页的标题呢?
网页标题是通过title来显示的, 但是SPA只有一个固定的HTML, 切换不同的页面时, 标题并不会改变。但是我们可以通过JavaScript来修改title的内容.window.document.title = ‘新的标题’。
那么在Vue项目中, 在哪里修改? 什么时候修改比较合适呢?
普通的修改方式:
我们比较容易想到的修改标题的位置是每一个路由对应的组件.vue文件中,通过mounted声明周期函数, 执行对应的代码进行修改即可。但是当页面比较多时, 这种方式不容易维护(因为需要在多个页面执行类似的代码).
有没有更好的办法呢? 使用导航守卫即可.
什么是导航守卫?
vue-router提供的导航守卫主要用来监听路由的进入和离开的.
vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发。

Vue.use(VueRouter)
const routes = [
  {
    path: '',
    redirect: '/home'
  },
  {
    path: '/home',
    component: Home,
    meta: {				# meta元数据,描述数据的数据
      title: '首页'
    },
    children: [
      {
        path: '',
        redirect: 'news'
      },
      {
        path: 'news',
        component: HomeNews,
      },
      {
        path: 'message',
        component: HomeMessage
      }
    ]
  },
  {
    path: '/about',
    component: About,
    meta: {
      title: '关于我们'
    },
  },
  {
    path: '/profile',
    component: Profile,
    meta: {
      title: '人个中心'
    },
  }
]
const router = new VueRouter({
  routes,
  mode: 'history'
})
router.beforeEach((to, from, next) => {
  document.title = to.matched[0].meta.title
  console.log(to);
  next()		# next函数必须要调用
})
export default router

导航钩子的三个参数解析:

  • to: 即将要进入的目标的路由对象.
  • from: 当前导航即将要离开的路由对象.
  • next: 调用该方法后, 才能进入下一个钩子.

补充一:如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数.
补充二:上面我们使用的导航守卫, 被称之为全局守卫.
- 路由独享的守卫.
- 组件内的守卫.

3.11 keep-alive

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
它们有两个非常重要的属性:

  • include - 字符串或正则表达,只有匹配的组件会被缓存
  • exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
<template>
  <div id="app">
    <router-link to="/home">Home</router-link>
    <router-link to="/about">About</router-link>
    <button @click="profileClick">档案</button>
    <keep-alive>
      <router-view></router-view>
    </keep-alive>
  </div>
</template>
发布了45 篇原创文章 · 获赞 3 · 访问量 1532

猜你喜欢

转载自blog.csdn.net/pcn01/article/details/103015533