vue 路由进阶

vue 路由进阶

路由可向路由匹配的组件传递参数,不一样状况向组件传递不一样的参数,从而实现组件的复用。css

路由向组件传递参数

和路由匹配的组件能够在组件中使用 $route 获取路由上的参数:html

传参方式

:paramsqueryvue

:在路径传递参数

{
	path: "/argu/:id/book",
	name: "argu",
	component: () => import("@/views/ArguPage")
}
复制代码

路径中的一部分是参数,必须传递该参数:web

<!--路径跳转-->
<router-link to="/argu/123/book">path跳转</router-link>
<!--路由名跳转-->
<router-link :to="{name:'argu',params:{id:'test'}}" tag="button">name+params跳转</router-link>
<!--获取参数-->
<h1>{{$route.params.id}}</h1><!--params的名字路径中的的参数名一致-->
复制代码

此时 path+ parmas传递参数,params会被忽略。vue-router

params+name传递参数

路由:服务器

{
	path: "/argu",
	name: "argu",
	component: () => import("@/views/ArguPage")
}
复制代码

跳转方式是 name+params+(query),经过path跳转,params 会被忽略。异步

<router-link :to="{name:'argu', params:{name:'hangge'}}">
  跳转到 hello
</router-link>
// path + params ,params 会被忽略,由于路径中没有定义参数
<router-link :to="{path:'/argu', params:{name:'hangge'}}">
  跳转到 hello
</router-link>
复制代码

query 参数

query 参数参数,表现为查询字符串,和localtion.serach同样的。函数

不须要先在路径中先定义,可经过pathpath+query 或者 name + query 传递参数。flex

<router-link to="/argu?queryName=value">跳转到 hello</router-link>
<router-link :to="{path:'/argu',query:{queryName:value}}">跳转到 argu</router-link>
<router-link :to="{name:'argu',query:{queryName:value}}">跳转到 argu</router-link>
<h1>{{ $route.query.queryName }}</h1>
复制代码

函数传递 queryui

// 主要是 $router 不是 $route
go() {
	this.$router.push({
		name: 'argu',
		query: {
				queryName: "你好"
			}
		})
	}
}
复制代码

可是这样使得 $route 和组件耦合在一块儿,不方便组件的复用,若是能将路由中的参数传递到 组件的props 就行了,偏偏是能够这样设置的。

props 接收路由的 params

路由传参数的三种方式:

  1. 布尔模式
{
    path: '/user/:id', 
    component: User, 
    props: true //代表 将 id 做为 proos 传递到匹配的组件 User 中。
}
复制代码

User 中定义 props 接收 id:

export default {
	props:{
		id:{
			type:String,
			default:'jackzhou'//默认值
		}
	}
}
复制代码
  1. 对象模式

将路由的 props 属性设置一个对象,也可在组件中获取到该值,这种方式每每用于传递静态值,即 name 值不会变化。

路由对象:

{
	name: 'home',
	alias:'/home_page',
	path: '/',
	props:{name:'jack jack'},
	component: Home
}
复制代码

Home 组件:

props:{
	name:{
		type:String,
	}
}
复制代码
  1. 函数模式

以上两种方式,params 参数的名字必须和组件中的props 属性名字相同,若是想对 params 进行改造后传递到组件,就可将 props 设置成函数,在函数内获取路由中的 params 或者 query,或者其余属性值,对其进行处理后再传递给组件。

注意:这种方式函数必须返回一个对象。

路由:

{
	name: 'about',
	path: '/about/:years', //params 有一个参数 years
	props:(route) {
  		const now = new Date()
  		return {
		// 将 years 改形成 name
    	name: (now.getFullYear() + parseInt(route.params.years)) + '!'
        }
	    },
	component: () => import('@/views/AboutPage'),
}
复制代码

组件中的 props:

props: {
	name: {
		type: String
	}
}
复制代码

命名视图的路由,要为每一个命名视图添加 props

{
	path:'/name/:view',
	name:'name_view',
	components:{
		default:()=>import('@/views/ChildPage'),
		sister:()=>import('@/views/SisterPage'),
		brother:()=>import('@/views/BrotherPage'),
	},
	props:{
        default:true,
        sister:false,
        brother:(route)=>({view:route.params.view.toUpperCase()})
    }
}
复制代码

完整的例子

{% raw %}

See the Pen route 的 params 传递组件 by JackZhouMine (@JackZhouMine) on CodePen.

{% endraw %}

HTML5 History 模式

路由配置里有一个属性 mode ,默认值是 hash,以hash来模拟一个url,url改变时,页面不会从新加载。

先使用普通模式,可将 mode 设置成 history,这种模式会使用 history.pushSate 来完成url跳转而页面不会从新加载。这种模式须要服务器设置一下

使用 history 模式,由于web应用每每是单页应用,当用户访问一个不存在的路径时,须要提供一个后备页面。

在路由配置的最后增长一个404路由:

{
	path:'*',
	component:NotFoundPage// 前面没有匹配的路由,最后会匹配该路由。
}
复制代码

meta 元信息

可在路由对象中配置 meta 属性,meta 是一个对象。

好比,根据不一样页面显示不一样的 title。

{
	name: "about",
	path: "/about",
	meta: {
		title: "关于"
	},
   	component: () => import("@/views/AboutPage")	
}
复制代码

在路由配置文件中,设置各个页面的 title:

const router= new Router({
    routes
})
router.beforeEach((to,from,next)=>{
    //setTitle 函数用于设置页面标题
	to.meta&&setTitle(to.meta.title) //这是简化if语句的简写
	console.table(to)
	console.table(from)
	next()
})
export default router
复制代码

导航守卫

全局守卫

  1. 全局前置守卫
const router = new Router({
    {
        path:"/",
        name:"heom_page"
        component:Home,
        //路由独享守卫
        beforeEnter:(to,from,next)=>{
            //处理逻辑
            next()
        }
    }
})
//每次路由进入都会调用
router.beforeEach((to,from,next)=>{
    //处理逻辑,好比登陆判断,可跳转到任意页面
    //不要忘记调用 next,不调用 next,页面不会跳转
})
复制代码
  1. 后置钩子
//路由跳转以后作一些操做,好比去掉登陆样式
router.afterEach((to,form)=>{
    //逻辑处理
})
复制代码
  1. 路由独享守卫 只在匹配某个路由时执行。

  2. 组件内守卫

beforeRouteEnter, 组件建立以前调用,组件不具有thisbeforeRouteUpdate,路由更新,而组件被复用时调用,可以使用thisbeforeRouteLeave,离开路由时调用,可以使用this

export default{
    name:'Home',
    data(){
        return {}
    },
	/** * 组件内路由守卫 * 1. 该函数在路由进入时执行 * 2. 此时 组件还未渲染,不可用 this,当可在 next 中用 vm * 3. next 晚于 mounted 执行,next 以前的代码,早于beforeCreate * 执行 * 4. 最后须要调用 next 使得路由跳转 */
	beforeRouteEnter(to, from, next) {
		console.log("①,home 组件内路由守卫,beforeRouteEnter");
		// next 晚于 mounted 执行,next 以前的代码,早于beforeCreate 执行
		next((vm)=>{
			console.log('vm')
			console.log(vm)//有值
			console.log('this')
			console.log(this)// undefined
			console.log('②,home 组件内路由守卫,beforeRouteEnter');
		});
	},
	/** * 组件内路由守卫 * 1. 该函数在路由离开时执行,最早调用,而后在调用全局守卫,再调用 * beforeDestroy * 2. 此时,该路由守卫所在组件已渲染,可用 this * 3. 最后须要调用 next 使得路由跳转 */
	beforeRouteLeave(to, from, next) {
		console.log("①,home 组件内路由守卫,beforeRouteLeave");
		let leave = confirm("你肯定要离开 home 页吗?");
		if (leave) {
		// console.log(to.name, from.name);
		// console.log(this);
		next(() => {
			console.log('②,home 组件内路由守卫,beforeRouteLeave');
			}); //给 next 传递 false ,路由不会跳转
		} else {
			next(false);
		}
	},
	/* * 当路由发生变化,而组件被复用时调用 * 1. 此时该复用组件已被渲染,可用 this * 2. 须要调用 next,组件才能渲染 */
	beforeRouteUpdate(to, from, next) {
		console.log('①,argu,组件内路由守卫,beforeRouteUpdate');
		next(() => {
			console.log('next,argu,组件内路由守卫,beforeRouteUpdate');
		});
	},
	beforeCreate() {
		console.log('beforeCreate')
	},
	created() {
		console.log('created')
	},
	beforeMount() {
		console.log('beforeMount')
	},
	mounted() {
		console.log('mounted')
	},
	beforeUpdate() {
		console.log('beforeUpdate')
	},
	updated() {
		console.log('updated')
	},
	beforeDestroy() {
		console.log('beforeDestroy')
	},
	destroyed() {
		console.log('destroyed')
	}
}
复制代码

路由全过程:

  1. 导航被触发
  2. 离开页面(失活的组件)里调用离开守卫 beforeRouteLeave
  3. 调用全局前置守卫 beforeEach
  4. 在重用的组件里调用 beforeRouteUpdate (非重用组件,没有这个步骤)
  5. 调用路由独享守卫 beforeEnter
  6. 解析异步路由组件
  7. 在进入页面(激活组件)调用 beforeRouteEnter
  8. 调用全局解析守卫 beforeResolve (导航被确认以前,组件内守卫和异步路由组件被解析以后,调用 beforeResolve)
  9. 导航被确认(何时被确认,所有钩子执行完了,是被确认的)
  10. 调用全局后置守卫 afterEach
  11. 触发 DOM 更新
  12. 在 vue 实例中(此时页面解析完毕了吗?是的)调用 beforeRouterEnter 守卫里传给 next 的回调。nextmounted以后被调用。

过渡效果

能够给路由匹配的组件设置过渡效果,让页面平滑地显示,提高用户体验。 须要用到 transition 标签,若是有多个视图须要过渡,则用 transition-group

<transition-group name='router-view'>
<!-- 视图渲染组件,该组件内不须要房子任何内容,可写成只闭合标签-->
	<router-view key='default'/>
	<!-- 有多个路由视图须要匹配,则用命名视图 -->
	<router-view key='sister' name="sister"></router-view>
	<router-view key='brother' name="brother"></router-view>
</transition-group>
复制代码

css 过渡效果:

.router-view-enter{
		opacity: 0;
	}
	.router-view-enter-active{
		transition: opacity 1s ease;
	}

	.router-view-enter-to{
		opacity: 1;
	}
	.router-view-leave{
		opacity: 1;
	}
	.router-view-leave-active{
		transition: opacity 1s ease;
	}

	.router-view-leave-to{
		opacity: 0;
	}
复制代码

这些设置,每一个页面的效果都是同样的,要为不一样的页面设置不一样的效果,可用路由传递相应的参数来,让动态绑定到 transition 的 name 属性上。

或者监听路由变化:

watch: {
	'$route'(to){
		console.log(to);
		to.params&&to.params.view&&(this.effect = to.params.view)
	},
}
复制代码

参考

Vue.js - 路由 vue-router 的使用详解2(参数传递)

相关文章
相关标签/搜索