中文文档: https://router.vuejs.org/zh/
vue Router 是 vue.js 官方的路由管理器. 它和 Vue.JS 的核心深度集成, 让构建单页面应用变得易如反掌. 路由实际上就是可以理解为指向, 就是我在页面上点击一个按钮需要跳转到对应的页面, 这就是路由跳转;
首先我们来学习三个单词 (route,routes,router):
route: 首先它是个单数, 译为路由, 即我们可以理解为单个路由或者某一个路由;
routes: 它是个复数, 表示多个的集合才能为复数; 即我们可以理解为多个路由的集合, JS 中表示多种不同状态的集合的形式只有数组和对象两种, 事实上官方定义 routes 是一个数组; 所以我们记住了, routes 表示多个数组的集合;
router: 译为路由器, 上面都是路由, 这个是路由器, 我们可以理解为一个容器包含上述两个或者说它是一个管理者, 负责管理上述两个; 举个常见的场景的例子: 当用户在页面上点击按钮的时候, 这个时候 router 就会去 routes 中去查找 route, 就是说路由器会去路由集合中找对应的路由;
我们结合一个小 demo 来看 (文章有点长, 耐心慢慢看, 学得慢才能进步的快, 当然可以跟着一起敲):
首先需要安装 vue-cli 来构建一个 vue 的开发环境 (怎么安装这里不讲, 自己百度去, 如果这种问题自己都解决不了的话, 后面的知识可能对你来说收益不大)
安装完 vue-cli 之后, 我们的项目目录结构如下:
然后我们在命令行中输入 NPM install vue-router -g 来安装 vue-router, 安装完之后我们可以打开 package.JSON 文件, 在 package.JSON 文件中可以看到 vue-router 的版本号;
到这一步我们的准备工作就完成了, 要进行写 demo 了;
我们在 src 目录下新建三个文件, 分别为 page1.vue 和 page2.vue 以及 router.JS:
- page1.vue:
- <template>
- <div>
- <h1>page1</h1>
- <p>{{msg}}</p>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- msg: "我是 page1 组件"
- }
- }
- }
- </script>
- page2.vue:
- <template>
- <div>
- <h1>page2</h1>
- <p>{{msg}}</p>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- msg: "我是 page2 组件"
- }
- }
- }
- </script>
router.JS
- // 引入 vue
- import Vue from 'vue';
- // 引入 vue-router
- import VueRouter from 'vue-router';
- // 第三方库需要 use 一下才能用
- Vue.use(VueRouter)
- // 引用 page1 页面
- import page1 from './page1.vue';
- // 引用 page2 页面
- import page2 from './page2.vue';
- // 定义 routes 路由的集合, 数组类型
- const routes=[
- // 单个路由均为对象类型, path 代表的是路径, component 代表组件
- {path:'/page1',component:page1},
- {path:"/page2",component:page2}
- ]
- // 实例化 VueRouter 并将 routes 添加进去
- const router=new VueRouter({
- //ES6 简写, 等于 routes:routes
- routes
- });
- // 抛出这个这个实例对象方便外部读取以及访问
- export default router
这里我们再修改一下 main.JS
- import Vue from 'vue'
- import App from './App'
- // 引用 router.JS
- import router from './router.js'
- Vue.config.productionTip = false
- /* eslint-disable no-new */
- new Vue({
- el: '#app',
- // 一定要注入到 vue 的实例对象上
- router,
- components: { App },
- template: '<App/>'
- })
修改 App.vue
- <template>
- <div id="app">
- <img src="./assets/logo.png">
- <div>
- //router-link 定义页面中点击触发部分
- <router-link to="/page1">Page1</router-link>
- <router-link to="/page2">Page2</router-link>
- </div>
- //router-view 定义页面中显示部分
- <router-view></router-view>
- </div>
- </template>
- <script>
- export default {
- name: 'App'
- }
- </script>
- <style>
- #App {
- font-family: 'Avenir', Helvetica, Arial, sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-OS X-font-smoothing: grayscale;
- text-align: center;
- color: #2c3e50;
- margin-top: 60px;
- }
- </style>
就这样, 我们的页面就可以进行路由跳转和切换了, 路由的基本使用就完成了; 但是有个问题就是我们第一次进去是看不到路由页面的, 这是因为我们没有设置默认值, 我们首次进入的时候路径是为空的, 那么我们可以这么解决:
router.JS
- import Vue from 'vue';
- import VueRouter from 'vue-router';
- Vue.use(VueRouter)
- import page1 from './page1.vue';
- import page2 from './page2.vue';
- import user from './user.vue'
- const routes=[
- {path:'/page1',component:page1},
- {path:"/page2",component:page2},
- // 可以配置重定向
- {path:'',redirect:"page1"}
- // 或者重新写个路径为空的路由
- {path:"",component:page1}
- ]
- const router=new VueRouter({
- routes
- });
- export default router
上面的两种解决方案都是可以解决的, 配置重定向的意思就是当匹配到路径为空的时候, 就会重定向到 page1, 执行 page1 的路由; 或者我们也可以重新配置个路由, 路径为空的时候 router-view 展示 page1 的页面;
用重定向和单独配置路由的区别:
重定向实际上是当匹配到路径符合条件的时候去执行对应的路由, 当然这个时候的 url 上面的地址显示的是对应的路由, 页面也是对应的路由页面;
重新配置路由是当匹配到路径符合条件的时候, router-view 页面展示部分负责拿符合条件路由的页面来展示, 实际上 url 是没有发生变化的;
那么还有些复杂情况, 是基本路由实现不了的; 我们来接着往下看
动态路由匹配:
其实我们的生活中有很多这样的例子, 不知道大家留意没有? 比如一个网站或者后台管理系统中, 在我们登录之后, 是不是通常会有一个欢迎回来, XXX 之类的提示语, 这个我们就可以通过动态路由来实现这个效果;
首先在 src 目录下新建一个 user.vue 文件:
- <template>
- <div>
- <h1>user</h1>
- // 这里可以通过 $route.params.name 来获取路由的参数
- <p > 欢迎回来,{{$route.params.name}}</p>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- msg: "我是 page1 组件"
- }
- }
- }
- </script>
然后我们修改 App.vue 文件的代码:
- <template>
- <div id="app">
- <img src="./assets/logo.png">
- <div>
- <router-link to="/page1">Page1</router-link>
- <router-link to="/page2">Page2</router-link>
- </div>
- // 添加两个 router-link 标签
- <div>
- <router-link to="/user/xianyu"> 动态路由咸鱼 </router-link>
- <router-link to="/user/mengxiang"> 动态路由梦想 </router-link>
- </div>
- <router-view></router-view>
- </div>
- </template>
- <script>
- export default {
- name: 'App'
- }
- </script>
- <style>
- #App {
- font-family: 'Avenir', Helvetica, Arial, sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-OS X-font-smoothing: grayscale;
- text-align: center;
- color: #2c3e50;
- margin-top: 60px;
- }
- </style>
修改我们的 router.JS
- import Vue from 'vue';
- import VueRouter from 'vue-router';
- Vue.use(VueRouter)
- import page1 from './page1.vue';
- import page2 from './page2.vue';
- import user from './user.vue'
- const routes=[
- {path:'/page1',component:page1},
- {path:"/page2",component:page2},
- // {path:'',redirect:"page1"}
- {path:"",component:page1},
- // 使用冒号标记, 当匹配到的时候, 参数值会被设置到 this.$route.params 中
- {path:"/user/:name",component:user}
- ]
- const router=new VueRouter({
- routes
- });
- export default router
配置好了, 不出意外是能正常运行的, 我们来看一下效果:
动态路由匹配给我们提供了方便, 使得我们通过配置一个路由来实现页面局部修改的效果, 给用户造成一种多个页面的感觉, 是不是很酷!!!
酷的同时也会给我们带来一些问题, 因为使用路由参数时, 从 / user/xianyu 导航到 / user/mengxiang, 原来的组件实例会被复用, 两个路由都渲染同个组件, 比起销毁再创建, 显示复用显得效率更高, 带来的的只管问题就是生命周期钩子函数不会再被调用, 也就是不会再被触发; 但是办法总比问题多, 我们可以通过监听 $route 对象来实现;
修改 user.vue 的代码
- <template>
- <div>
- <h1>user</h1>
- <p > 欢迎回来,{{msg}}</p>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- // msg: "我是 page1 组件"
- msg:""
- }
- },
- watch:{
- //to 表示即将要进入的那个组件, from 表示从哪个组件过来的
- $route(to,from){
- this.msg=to.params.name;
- console.log(111);
- }
- }
- }
- </script>
效果图如下:
我们可以很明显的看到我们监听的 $route 对象被触发了, 控制台也输出了;
下面我们来一起看一下嵌套路由:
嵌套路由:
很多时候我们的页面结构决定了我们可能需要嵌套路由, 比如当我们进入主页之后有分类, 然后当选择其中一个分类之后进入对应的详情, 这个时候我们就可以用到嵌套路由; 官方文档中给我们提供了一个 children 属性, 这个属性是一个数组类型, 里面实际放着一组路由; 这个时候父子关系结构就出来了, 所以 children 属性里面的是路由相对来说是 children 属性外部路由的子路由;
好记性不如烂代码, 让我们通过代码来看一看:
首先在我们的 src 目录下新建两个 vue 文件, 分别是 phone.vue 和 computer.vue
phone.vue
- <template>
- <div>
- <p>{{msg}}</p>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- msg: "嵌套手机组件"
- }
- }
- }
- </script>
computer.vue
- <template>
- <div>
- <p>{{msg}}</p>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- msg: "嵌套电脑组件"
- }
- }
- }
- </script>
然后我们再修改我们的 App.vue 文件:
- <template>
- <div id="app">
- <img src="./assets/logo.png">
- <div>
- <router-link to="/page1">Page1</router-link>
- </div>
- <router-view></router-view>
- </div>
- </template>
- <script>
- export default {
- name: 'App'
- }
- </script>
- <style>
- #App {
- font-family: 'Avenir', Helvetica, Arial, sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-OS X-font-smoothing: grayscale;
- text-align: center;
- color: #2c3e50;
- margin-top: 60px;
- }
- </style>
通过上面的 App.vue 文件我们可以看到, 我们此时页面只有一个 page1 的标签了;
我们再来修改 router.JS
- import Vue from 'vue';
- import VueRouter from 'vue-router';
- Vue.use(VueRouter)
- import page1 from './page1.vue';
- import page2 from './page2.vue';
- import user from './user.vue';
- import phone from './phone.vue';
- import computer from './computer.vue'
- const routes=[
- {
- path:'/page1',
- component:page1,
- children: [
- {
- path: "phone",
- component: phone
- },
- {
- path: "computer",
- component: computer
- },
- ]
- },
- // {path:"/page2",component:page2},
- // // {path:'',redirect:"page1"}
- // {path:"",component:page1},
- // {path:"/user/:name",component:user}
- ]
- const router=new VueRouter({
- routes
- });
- export default router
为了大家看的直观点, 其他路由全部注释了, 页面只剩下 / page1 这一个路由了;
上面说到了, children 属性其实就是一个子路由集合, 数组结构里面放着子路由;
效果图如下:
路由导航两种方式:
标签导航: 标签导航 < router-link><router-link > 是通过转义为 < a></a > 标签进行跳转, 其中 router-link 标签中的 to 属性会被转义为 a 标签中的 href 属性;
- // 跳转到名为 user 路由, 并传递参数 userId
- <router-link :to="{ name:'user', params: { userId: 123 }}">User</router-link>
编程式导航: 我们可以通过 this.$router.push() 这个方法来实现编程式导航, 当然也可以实现参数传递, 这种编程式导航一般是用于按钮点击之后跳转
router.push({ name: 'user', params: { userId: 123 }})
这两者都会把路由导航到 user/123 路径
命名路由:
有的时候, 通过一个名称来标识一个路由显得更方便一些, 所以官方为了方便我们偷懒, 又给我们在路由中添加了一个 name 属性, 命名这个属性之后我们访问这个属性就等于直接访问到路由;
普通路由:
router.push({ path: '/user/:userId', params: { userId: 123 }})
命名路由:
router.push({ name: 'user', params: { userId: 123 }})
其实两者并没有什么区别, 只是提供了两种方式来访问路由, 可以通过路径来匹配也可以通过别名来匹配;
今天的文章就到这里, 下篇我们一起来学习 Vue 路由守卫!!!
加油!!
来源: https://www.cnblogs.com/dengyao-blogs/p/11562257.html