vue.js路由(vue-router)详解+案例

简介: 对于大多数单页面应用,都推荐使用官方支持的vue-router,其实简单的说路由就是跳转,和HTML<a>标签实现的效果是一样的,都是添加过路径后便可以跳转到相应位置,可能有人会说那还学vue-router干嘛直接用a标签实现不就可以了,这里就要提到vue的优点了,vue-router让构建单页面应用变得易如反掌,而如果使用a标签你需要写好多代码构造页面。(●ˇ∀ˇ●)

安装:
1、通过script标签直接引用

https://unpkg.com/vue-router@2.0.0/dist/vue-router.js

2、通过npm安装

npm install vue-router

使用方式:
<router-link> 是一个组件,该组件用于设置一个导航链接,切换不同 的 内容,to 属性后面加的是目标地址,<router-view>是路由的出口,路由显示的内容都在这里显示

HTML
<div id="app">
  <p>
    <router-link to="路径">内容</router-link>
    <router-link to="路径">内容</router-link>
  </p>
  <!-- 路由出口 -->
  <router-view></router-view>
</div>

const属性是定义路由和路由组件用的,和JavaScript的var属性类似,template属性内接的是路由输出的内容。
每个路由映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象(我们下面接触的都是组件对象)。

JavaScript
// 1. 定义(路由)组件。
const Foo = { template: '输出内容' }
const Bar = { template: '输出内容' }
 
// 2. 定义路由
const routes = [
  { path: '路径', component: Foo },
  { path: '路径r', component: Bar }
]
 
// 3. 创建 router 实例,然后传 `routes` 配置
const router = new VueRouter({
  routes // (缩写)相当于 routes: routes
})
const app = new Vue({
  el:"#app",
  router
})

下面案例包括vue-router的重定向和别名功能和利用加入exact属性实现默认匹配的效果:
案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="vue.js"></script>
		<script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js"></script>
	</head>
	<body>

		<div id="app">
		  <p>
		  
			<router-link to="/" exact>首页</router-link>
			<router-link to="/foo">Go to Foo</router-link>
		    <router-link to="/bar">Go to Bar</router-link>
			<router-link to="*">不存在</router-link>
		  </p>
		  <!-- 路由出口 -->
		  <router-view></router-view>
		</div>
		
		
		<script>
		const home = { template: '<div>欢迎回家</div>' }
		const Foo = { template: '<div>foo</div>' }
		const Bar = { template: '<div>bar</div>' }
	
		const routes = [
		  <!-- 设置根路径,需要将path设置为'/' -->
		  { path: '/', component: home },
		  { path: '/foo', component: Foo },
		  { path: '/bar', component: Bar },
		  { path: '*', redirect: "/"}
		]

		const router = new VueRouter({
		  routes 
		})
		const app = new Vue({
		  el:'#app',
		  router
		})
		
		</script>  
	</body>
</html>

嵌套
实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL中各段动态路径也按某种结构对应嵌套的各层组件。

/user/foo/profile                     /user/foo/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

上面可以了解到template标签后加的是输出的内容,所以在template标签后再加入路由,便可以实现嵌套功能,但需要注意的是:在router中构造的routes配置中,children属性里的path属性只设置为当前路径即不能加“/”。

命名路由:
命名路由的常见用途是替换router-link中的to属性,如果不使用命名路由,由router-link中的to属性需要设置全路径,不够灵活,且修改时较麻烦。使用命名路由,只需要使用包含name属性的对象即可
如果加入的是路径to前不需要加":",若是命名则需加。

<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

会把路由导航到 /user/123 路径。
命名视图:
有时,您需要同时显示多个视图而不是嵌套它们,例如,创建包含一个sidebar视图和一个main视图的布局。这是命名视图派上用场的地方。您可以在多个视图中命名一个,而不是在视图中显示一个视图。

请认真看下面案例,你将对这部分内容有更好的理解:
嵌套命名案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="vue.js"></script>
		<script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js"></script>
	</head>
	<body>
		<div id="app">
		  <p>
		    <router-link to="/" exact>home</router-link>
		    <router-link :to="{ name: 'foo' }">Go to Foo</router-link>
		    <router-link :to="{ name: 'bar' }">Go to Bar</router-link>
		  </p>
		  <!-- 如果 router-view 没有设置名字,那么默认为 default -->
		  <router-view></router-view>
		  <!-- <router-view name="side"></router-view> -->
		</div>
		<script>
			const home = { template: '<div>欢迎回家</div>' }
			const Foo = { template: `
			  <div>
			    <p>
			      <router-link :to="{ name: 'foo1' }" exact>to Foo1</router-link>
			      <router-link :to="{ name: 'foo2' }" >to Foo2</router-link>
			      <router-link :to="{ name: 'foo3' }" >to Foo3</router-link>  
			    </p>
			    <router-view></router-view>
			  </div>
			  ` }
			const Bar = { template: '<div>bar</div>' }
			const Foo1 = { template: '<div>Foo1</div>' }
			const Foo2 = { template: '<div>Foo2</div>' }
			const Foo3 = { template: '<div>Foo3</div>' }
			const Bar1 = { template: '<div>bar1</div>' }
			// 可以定义一个routes,然后在router中调用
			// 也可以直接将routes写在router中
			// const routes = [
			//   { path: '/', name:'home', component: home },
			//   // 注意:如果设置了默认子路由即path:' ',则不要在父级路由上设置name属性,且父机路由router-link :to="添加默认子路由的name"
			//   { path: '/foo',name:'foo', component: Foo ,children:[
			//     {path:'foo1',name:'foo1', component:Foo1},
			//     {path:'foo2',name:'foo2', component:Foo2},
			//     {path:'foo3',name:'foo3', component:Foo3},
			//   ]},
			//   // 多个视图就需要多个组件。确保正确使用components配置
			//   { path: '/bar', name:'bar', components:{
			// 	  default:Bar,
			// 	  side:Bar1
			//   }
			//     },
			// ]
            const router = new VueRouter({
               routes:[
			  { path: '/', name:'home', component: home },
			  // 注意:如果设置了默认子路由即path:' ',则不要在父级路由上设置name属性,且父机路由router-link :to="添加默认子路由的name"
			  { path: '/foo',name:'foo', component: Foo ,children:[
			    {path:'foo1',name:'foo1', component:Foo1},
			    {path:'foo2',name:'foo2', component:Foo2},
			    {path:'foo3',name:'foo3', component:Foo3},
			  ]},
			  // 多个视图就需要多个组件。确保正确使用components配置
			  { path: '/bar', name:'bar', components:{
				  default:Bar,
				  side:Bar1
			  }
			    },
			] 
            })
            const app = new Vue({
            	el:'#app',
            	router
            })
		</script>
	</body>
</html>

且通过上面案例可以看出,routes可以单独定义后在router中调用也可以直接在router中构造。

动态路径:
 我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。如果我们使用嵌套的方法哪有要知道每个用户的id,这样实现太过于麻烦,我们便可以在 vue-router 的路由路径中使用动态路径参数来达到这个效果。
 一个路径参数使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,可以更新 User 的模板,输出当前用户的 ID:

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

我们也可以在一个路由中设置多段『路径参数』,对应的值都会设置到 $route.params 中。

模式                   匹配路径           $route.params
/user/:username            /user/evan         { username: 'evan' }
/user/:username/post/:post_id   /user/evan/post/123   { username: 'evan', post_id: 123 }

动态路径案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="vue.js"></script>
		<script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js"></script>
	</head>
	<body>
		<div id="app">
		    
		  <p>
		    <router-link to="/" exact>home</router-link>
		    <router-link :to="{name:'user'}">User</router-link>
		    <router-link :to="{name:'bar'}">Go to Bar</router-link>
		  </p>
		  <router-view></router-view>
		</div>
		<!-- 一个路由中可以设置多段『路径参数』,对应的值都会设置到 $route.params 中 -->
		<!-- 模式                   匹配路径           $route.params
		/user/:username            /user/evan         { username: 'evan' }
		/user/:username/post/:post_id   /user/evan/post/123   { username: 'evan', post_id: 123 } -->
		<script type="text/javascript">
			const home = { template: '<div>欢迎回家</div>'};
			const bar = { template: '<div>bar</div>'};
			const user = 
			  {template: `<div>
			    <p>user</p>
			    <router-link style="margin: 0 10px" :to="'/user/' +item.type + '/'+ item.id" v-for="item in userList" key="item.id">{{item.username}}</router-link>  
			    <div v-if="$route.params.id">
			      <div>id:{{userInfo.id}};username:{{userInfo.username}} ;type:{{userInfo.type}};</div>
			    </div>
			</div>`,
			  data(){
			    return{
			      userList:[{id:1,type:'vip',username:'u1'},{id:2,type:'common',username:'u2'},{id:3,type:'vip',username:'u3'}],
			      userInfo:null,
			    }
			  },
			  methods:{
			    getData(){
			      let id = this.$route.params.id;
			      if(id){
			        this.userInfo = this.userList.filter((item)=>{
			          return item.id == id;
			        })[0]
			      }else{
			        this.userInfo = {};
			      }   
			    }
			  },
			  created(){
			    this.getData();
			  },
			  watch:{
			    $route(){
			      this.getData();
			    },
			  }
			};
			const app = new Vue({
			  el:'#app',
			  router:new VueRouter({
			    routes: [
				// path:'/user/:id?'表示有没有子路径都可以匹配
			      { path: '/', name:'home', component:home },
			      { path: '/user/:type?/:id?', name:'user', component:user},
			      { path: '/bar', name:'bar', component:bar},
			    ]
				
			  }), 
			})
		</script>
	</body>
</html>

提示:path:’/user/:id?'表示有没有子路径都可以匹配, watch是用于检测 $route 对象的变化的
且有时同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高
若想更加详细的了解可以点击这里

过渡动效:
是基本的动态组件,所以可以用 组件给它添加一些过渡效果

<transition>
        <router-view></router-view>
    </transition>

简单案例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="vue.js"></script>
		<script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js"></script>
	</head>
	<style>
		  .router-link-active{background:pink;}
		  .v-enter,.v-leave-to{
		    opacity:0;
		  }
		  .v-enter-active,.v-leave-active{
		    transition:opacity .5s;
		  }
	</style>
	<body>
		<!-- 通过前进、后退按钮进行切换时,保持坐标位置 -->
		<div id="app">
			<p>
				<!-- 如果加入的是路径to前不需要加":",若是命名则需加。
				exact为默认页 -->
				<router-link  to="/" exact>首页</router-link>
				<router-link :to="{name: 'root' }">内容1</router-link>
				<router-link :to="{name: 'root1' }">内容2</router-link>
			
			</p>
			<transition>
				<router-view></router-view> 
			</transition>
			<router-view name="side"></router-view>
		</div>
		
		<script>
			const home={template:'<div>欢迎回家</div>'}
			const Root={template:'<div>内容1</div>'}
			const new1={template:'<div>信息页1</div>'}
			const new2={template:'<div>信息页2</div>'}
		
			const routes=[
				{path:'/',name:'home',component:home},
				{path:'/root',name:'root',component:Root},
				{path:'/root1',name:'root1',components:{
					default:new1,
					side:new2
				}
				},
			]
			const router=new VueRouter({
				
				  routes 
				
			})
			const app=new Vue({
				el:"#app",
				router
			})	
		</script>
	</body>
</html>

导航钩子:
可以使用 router.beforeEach 注册一个全局的 before 钩子
构造方式:

router.beforeEach((to, from, next) => {
			  if(to.meta.login){
			    next('/login');
			  }
			  if(to.meta.login2){
			    next('/login2');
			  }
			  next();
			});

也可以使用 router.afterEach 注册一个全局的 after钩子,构造方式和构造before 钩子一样。

这里是next()函数传递不同参数的情况:

  • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
  • next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
  • next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。

案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>导航钩子</title>
		<script src="vue.js"></script>
		<script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js"></script>
	</head>
	<div id="app">
		<p>
			<router-link  to="/" exact>首页</router-link>
			<router-link :to="{name: 'foo' }">内容1</router-link>
			<router-link :to="{name: 'bar' }">内容2</router-link>
		</p>
		<router-view></router-view>
	</div>
	<body>
		<script type="text/javascript">
			const Home = { template: '<div>home</div>' }
			const Foo = { template: '<div>Foo</div>'}
			const Bar = { template: '<div>bar</div>' }
			const Login = { template: '<div>请登录</div>' }
			const Login2 = { template: '<div>请返回</div>' }
			const routes = [
			  { path: '/', name:'home', component: Home,meta:{index:0}},
			  { path: '/foo', name:'foo', component:Foo,meta:{index:1,login:true}},
			  { path: '/bar', name:'bar', component:Bar,meta:{index:2,login2:true}},
			  { path: '/login', name:'login', component:Login,},
			  { path: '/login2', name:'login2', component:Login2,},
			]
			const router = new VueRouter({
			  routes ,
			})
			router.beforeEach((to, from, next) => {
			  if(to.meta.login){
			    next('/login');
			  }
			  if(to.meta.login2){
			    next('/login2');
			  }
			  next();
			});
			router.afterEach((to, from)=>{
			  document.title = to.name;
			})
			const app = new Vue({
			  el:'#app',
			  router,
			})
		</script>
	</body>
</html>

结果可以看到:
在这里插入图片描述
点击第一下内容人1出现请登录,再次点击将出现foo,点击第一下内容人2出现请返回,再次点击将出现bar。这种效果我们在项目中也特别常见,利用这种情况我们可以更加简单的实现不同点击次数实现不同的效果的功能。

总结:上面所介绍的功能是我感觉我们在项目中常用的一些,当然vue-router还有一些功能,这里我没有介绍,如果想对于其他功能进行下了解可以到vue-router官网,官网介绍还是比较详细的,但是不能进行实例演示,我感觉剩下没介绍的功能可以简单了解下便可以了(个人感觉),看着官网介绍写点小案例就可以了。

对于这部分不懂得或者比较理解的可以在评论区评论下,大家互相学习下。👨🏻‍💻👨🏻‍💻👨🏻‍💻👨🏻‍💻👩🏻‍💻👩🏻‍💻👩🏻‍💻(●ˇ∀ˇ●)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值