震惊! vue路由竟有如此不为人知的一面!

使用vue-cli安装不需要另外安装路由,只需要在安装时候选择Manually select features,然后选到router按下空格就行

路由配置

  • Router
  • Views
//main.js
import router from "./router"
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

初始化路由

在路由模块的入口文件index.js配合router

//引入vue
import Vue from 'vue';
//引入router
import VueRouter from 'vue-router'
//引入组件
import Home from "../xxx/Home.vue";
import About from "../xxx/About.vue"

//全局配置路由
Vue.use(VueRouter)

//集成路由
const routes = [
	{
        //路径
        path:"/",
        //路由名称
        name:"home",
        //路由加载的组件
        component:Home
    },
    {
        path:"/about",
        name:"about",
        component:About,
    }
]
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

嵌套路由

嵌套路由用到了children属性,实现嵌套

//引入vue
import Vue from 'vue';
//引入router
import VueRouter from 'vue-router'
//引入组件
import Home from "../xxx/Home.vue";
import Hot from "../views/Hot.vue";

//全局配置路由
Vue.use(VueRouter)

//集成路由
const routes = [
	{
        //路径
        path:"/",
        //路由名称
        name:"home",
        //路由加载的组件
        component:Home,
        //嵌套路由
        children:[
            {
                path: "/hot",
        		name: "hot",
        		component: Hot
            }
        ]
    },
]
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

编程式导航

  • 在vue实力内部,你可以通过 r o u t e r 访 问 路 由 实 例 , 因 此 你 可 以 调 用 t h i s . router访问路由实例,因此你可以调用this. router访this.router.push跳转,这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
  • this.$router.push有两种跳转方式,一个是path+query,另一个是name+params

path+query

this.$router.push({
      path:'/hello',
      query:{
          name:'word',
          age:'11'
     }
})

name+params

this.$router.push({
      name:'hello',
      params:{
          name:'word',
          age:'11'
     }
})

一般推荐使用path+query进行路由传参

  • 使用params带参数,需要对应使用name来指明路径,query带参数,则path,name都可以
  • params带参数跳转,在跳转后页面再进行跳转或刷新都有可能导致数据丢失,建议使用query带参数
  • query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会再地址栏中显示
  • params是路由的一部分,必须要有。query是拼接在url后面的参数,没有也没关系
  • params一旦设置在路由,params就是路由的一部分,如果这个路由有params传参,但是在跳转的时候没有传递这个参数,会导致跳转失败或者页面没有内容,比如跳转router1/:id
<router-link :to="{name:'router1',params:{id:staus}}">正确</router-link>
<router-link :to="{name:'router1',params:{id2:staus}}">错误</router-link>

命名视图

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

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

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

const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

在这个默认路由下面,

第一个非未命名视图显示Foo组件

第二个name名为a的视图显示Bar组件

name名为b的视图显示Baz组件

下面这个是一个示例

<template>
  <div class="hello">
    <ul class="nav">
      <li><router-link to="/list1">list1</router-link></li>
      <li><router-link to="/list2">list2</router-link></li>
      <li><router-link to="/list3">list3</router-link></li>
    </ul>
    <h6>默认视图</h6>
    <div class="view">
      <router-view></router-view>
    </div>
    <h6>a视图</h6>
    <div class="view">
      <router-view name="a"></router-view>
    </div>
    <h6>b视图</h6>
    <div class="view">
      <router-view name="b"></router-view>
    </div>
  </div>
</template>

router配置:

routes: [
  {
    path: '/',
    name: 'HelloWorld',
    component: HelloWorld,
    children:[
      {
        path:'',
        components:{
          default:List1,
          a:List2,
          b:List3
        }
      },
      {
        path:'list1',
        components:{
          default:List1,
          a:List2,
          b:List3
        }
       },
       {
        path:'list2',
        components:{
          default:List2,
          a:List1,
          b:List3
        }
      },
      {
        path:'list3',
        components:{
          default:List3,
          a:List1,
          b:List2
        }
      }
    ]
  }
]

嵌套命名视图

我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 router-view 组件

{
  path: '/',
  // 你也可以在顶级路由就配置命名视图
  component: name,
      //嵌套路由
  children: [{
    path: '/emails',
    component: UserEmailsSubscriptions
  },
  {
    path: 'profile',
      //命名视图
    components: {
      default: UserProfile,
      helper: UserProfilePreview
    }
  }]
}

重定向

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

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 重定向的 字符串路径/路径对象
 }}
 ]
})

代码示例:

{ path: '/dynamic-redirect/:id?',
 redirect: to => {
 	const { hash, params, query } = to
 	if (query.to === 'foo') {
  		return { path: '/foo', query: null }
 	}
 	if (hash === '#baz') {
  		return { name: 'baz', hash: '' }
 	}
 	if (params.id) {
  			return '/with-params/:id'
 		} else {
  			return '/bar'
 		}
 	}
}

导航守卫

vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
全局前置守卫beforeEach
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之

前一直处于 等待中

你可以使用 router.beforeEach 注册一个全局前置守卫:

//模拟登录状态
let loginStatus = false

const router = [
  {
    path: '/',
    name: 'Home',
    component: Home,
      //设置meta前往路由是否需要通过守卫
    meta: {
      isLogin: false
    }
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue'),
    meta: {
      isLogin: false
    }
  },
  {
    path: "/mine",
    name: "mine",
    component: () => import("../views/Mine.vue"),
    meta: {
      isLogin: true
    }
  }
]

路由独享守卫beforeEnter

let loginStatus = false
const routes = [
  {
    path: "/shoppinglist",
    name: "shoppinglist",
    component: ShoppingList,
    // 设置路由独享守卫
    beforeEnter: (to, from, next) => {
      // 判断登录状态
      if (loginStatus === false) {
        next("/login")
      } else {
        next()
      }
    }
  }
]

组件内守卫beforeRouteLeave

<script>
export default {
  // 设置组件内守卫beforeRouteLeave
  beforeRouteLeave (to, from, next) {
    window.console.log(to)
    window.console.log(from)
    window.alert("真的要离开吗")
    next()
  }
}
</script>

每个守卫方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象
  • from: Route: 当前导航正要离开的路由
  • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
    • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
    • next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
    • next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: truename: 'home' 之类的选项以及任何用在 router-linkto proprouter.push 中的选项。
    • next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

**确保要调用 next 方法,否则钩子就不会被 resolved。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值