Javascript - Vue - 路由
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Javascript - Vue - 路由,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含17651字,纯文字阅读大概需要26分钟。
内容图文
![Javascript - Vue - 路由](/upload/InfoBanner/zyjiaocheng/621/a742597b6a4549159040ad91948576e7.jpg)
vue router.js
小拉达下载:vue-router.js,
该文件依赖于vue.js
<script?src="Scripts/vue-2.4.0.js"></script>???<script?src="/Scripts/vue-router.js"></script>
路由的作用
大比鸟使用路由后,当前页面的url地址就会多出一个#号,这个#号与html页面的锚点类似,在route.js中它表示根据路由对象里的路由配置在页面中切换不同的路由组件以便展示在客户端显示。路由发起的请求会交给router对象进行处理后返回请求的资源而不是直接向服务端发起资源请求,使用路由的好处在于发起一个路由请求后浏览器地址栏的刷新按钮并不会动,而常规的超链接请求会使页面刷新。虽然两者都是向服务端发起请求,但router的路由机制可以将客户端请求所需要的vue组件静态加载(不刷新地址栏)到当前页面上显示。
创建路由对象
<template?id="loginTem">????<div>登录区域</div>
</template>
<template?id="registerTem">
????<div>注册区域</div>
</template>
<script>
????//客户端路由总是与组件有关,所以首先创建组件
????var?loginCom={
????????template:"#loginTem"
????}
????var?registerCom={
????????template:"#registerTem"
????}
????var?router?=?new?VueRouter({
????????//路由对象的routes属性是一个集合,用于设定路由模板
????????routes:?[????????????
????????????{?path:?"/login",?component:?loginCom?},?//路由模板,用于匹配客户端路由请求,component在此处是外部的组件被注册在路由中,称为路由组件
????????????{?path:?"/register",?component:?registerCom?}?//不同的路由模板对不同的路由请求进行匹配
????????]
????});
</script>
路由的运作过程
比比鸟当在vue对象所监视的html中的超链接、按钮等元素的点击事件上发起一个客户端路由请求后,这个请求会通过vue转发到路由对象上(路由对象会在vue中注册),路由对象根据routes集合里的路由模板对路由地址请求进行路由匹配,匹配成功后就将注册在路由模板里的组件发送到客户端显示在html文档上。
路由标签
组件切换可以使用component标签,通过指定它的is属性来切动态换组件,而路由组件的切换则是通过vue-router提供两个html标签来实现
router-view
这个标签是路由组件的容器,路由匹配的过程是:一旦浏览器发起路由请求,那么vue对象就会截获这个请求,再将请求转交给路由模板进行匹配,匹配成功后会将对应的路由组件插入到router-view容器里。所以,如果仅仅是发起了路由请求,但没有设置router-view,那么路由组件是不会显示出来的。
<div?id="box">????<a?href="#/login">login</a>
????<a?href="#/register">register</a>
????<router-view></router-view>?//组件已经被注册为路由组件,此处不再以组件标签名而是使用路由标签来插入html文档,vue的整个路由机制就是围绕这个标签做文章,针对不同的路由匹配展示不同的路由组件到这个router-view里面去。
</div>
<template?id="loginTem">
????<div>登录区域</div>
</template>
<template?id="registerTem">
????<div>注册区域</div>
</template>
<script>
????//客户端路由总是与组件有关,所以首先创建组件
????var?loginCom={
????????template:"#loginTem"
????}
????var?registerCom={
????????template:"#registerTem"
????}
????var?router?=?new?VueRouter({
????????//路由对象的routes属性是一个集合,用于设定路由模板
????????routes:?[????????????
????????????{?path:?"/login",?component:?loginCom?},?//路由模板,用于匹配客户端路由请求
????????????{?path:?"/register",?component:?registerCom?}?//不同的路由模板对不同的路由请求进行匹配
????????]
????});
????var?vm?=?new?Vue({
????????el:?"#box",
????????router:?router?//将路由对象注册到vue对象的router属性中,使vue对象可以监听到它内部所包含的html元素的url请求的路由变化,然后调用路由对象对路由请求进行匹配
????});
</script>
router-link
波波可以替代a标签,属性to指向目标路由地址。其作用是发起路由请求,有三种方式可以发起路由请求,1.点击router-link或a标签,2.直接在浏览器地址栏输入路由地址,3.通过手动写js程序发起路由请求。 <div?id="box">????<router-link?to="/login"?>登录</router-link>?//可以添加tag属性,如tag="div",这样会把router-link渲染成div,且依然可以点击
????<router-link?to="/register">注册</router-link>? ?
????<router-view></router-view>
</div>
控制<router-link>的css
var?router?=?new?VueRouter({????routes:?[
? ? ? ……
????],
????linkActiveClass:?"link-active"
}); .link-active?{
????background:?#ffd800;
????color:?#fff;
}
手动定向路由 redirect
routes:?[????{path:"/",redirect:"/login"},?//当首次显示主页时直接定向到登录区域,或直接{path:"/",component:"loginCom"}使请求主页时直接显示登录区域
????{?path:?"/login",?component:?loginCom?},?
????{?path:?"/register",?component:?registerCom?}
]
路由命名 name
{path:"/index/productList",component:productList,name:"productList"}手动发起路由请求 $router.push()
使用$router.push()方法,注意不是$route而是$router,给路由命名后,可以通过点击事件手动发起路由请求并传递url路由查询字符串
<div?@click="redirect"?>?商品购买</div?> methods:?{????redirect:?function()?{
????????this.$router.push({?name:?"productList",params:productID?}); ? ? ? ?//或
????????this.$router.push("/index/productList"+productID); ? ? ?? //或
????????this.$router.push({path:"/index/productList"+productID});
????}
}
路由匹配中的查询字符
非严格匹配 $route.query
路由地址的后面跟上查询字符串能够被识别有效路由。比如请求的路由为#/login,路由模板也可以匹配#/login?id=100&name=sam。可以在组件对象的内部通过组件创建完成之后触发的事件、使用$route.query获取查询字符串的值
<router-link?to="/login?id=100&name=sam">登录</router-link> //当前组件被初始化时打印路由地址中的查询字符 var?login={????template:?"#loginTem",
????created:?function?()?{
????????console.log(this.$route.query.id);
????}
}
严格匹配 $route.params
在路由模板里可以定义查询字符的匹配规则,如果在路由模板里定义了查询字符的匹配的规则,那么就必须包括查询字符在内的路由地址得完全符合路由模板的规则,否则不会被匹配。比如在路由模板中指定了查询字符,此时#/login地址与#/login/100/sam两个地址只有后一个会被匹配成功。可以在组件对象的内部通过组件创建完成之后触发的事件、使用$route.params获取查询字符串的值
<router-link?to="/login/100/sam"?>登录</router-link> var?router?=?new?VueRouter({? ?????routes:?[? ? ? ?
????????{?path:?"/login/:id/:name",?component:?loginCom?},??//这个路由模板只绝对匹配/login/id/name的路由请求,/login/100/sam/leo将不会被匹配
????]
});
????template:?"#loginTem",
????created:?function?()?{
????????console.log(this.$route.params.id);
????}
}
获取路由地址 $route.path
$route.path获取的地址不包括查询字符串
methods:?{????btnClick:?function?()?{
????????console.log(this.$route.path);
????}
}
监听路由
参考watch:vue-watch
子路由组件
下图中的账户是一个路由组件,而账户路由组件里面又插入了登录和注册路由组件。
????<router-link?to="/account">账户</router-link>
????<router-view></router-view>?//切换账户模块和其它模块的路由组件容器
</div>
<template?id="tem">
????<div?class="module-box">
????????<p>账户模块</p>
????????<router-link?to="/account/login">登录</router-link>
????????<router-link?to="/account/register">注册</router-link>
????????<router-view></router-view>?//切换账户模块下的登录和注册模块的子路由组件容器
????</div>
</template>
<template?id="login">
????<div?class="form-group">
????????<label>
????????????用户:<input?type="text"?class="form-control"?/>
????????</label>
????????<label>
????????????密码:<input?type="text"?class="form-control"?/>
????????</label>
????????<button?class="btn?btn-primary">OK</button>
????</div>
</template>
<template?id="register">
????<div?class="form-group">
????????<label>
????????????用户:<input?type="text"?class="form-control"?/>
????????</label>
????????<label>
????????????密码:<input?type="text"?class="form-control"?/>
????????</label>
????????<label>
????????????电邮:<input?type="text"?class="form-control"?/>
????????</label>
????????<button?class="btn?btn-primary">OK</button>
????</div>
</template>
</body>
</html>
<script>
????var?router?=?new?VueRouter({
????????routes:?[
????????????{
????????????????path:?"/account",
????????????????component:?{?template:?"#tem"?},
????????????????//在路由模板里添加子路由模板
????????????????children:?[
????????????????????{?path:?"login",?component:?{?template:?"#login"?}?},
????????????????????{?path:?"register",?component:?{?template:?"#register"?}?}
????????????????]
????????????}
????????]
????});
????var?vm?=?new?Vue({
????????el:?"#box",
????????data:?{
????????????msg:"hello"
????????},
????????router:router
????});
</script>
大针蜂注意如果一个路由组件里嵌套了其它的路由组件,那么必须在路由匹配规则的父规则里使用children指定嵌套在父路由里的子路由,那么这种关系必须使用children指定,如果你把子路由匹配规则放在父路由规则的外面,那么当你点击router-link发起子路由请求后,父路由组件会被切换掉,看不见。也即你想在切换路由的时候父路由必须显示出来,就必须指定children。只有指定了children属性才使嵌套的路由组件成为父子关系。
如果要让页面一加载就显示其中某个子路由,可以利用redirect实现
{????path:?"/account",
????component:?{?template:?"#tem"?},
????redirect:?"/account/login",
????children:?[
????????{?path:?"login",?component:?{?template:?"#login"?}?},
????????{?path:?"register",?component:?{?template:?"#register"?}?}
????]
}
//带查询字符串的默认子路由
{
????path:?"/index",
????component:?{?template:?"#tem"?},
????redirect:?"/index/product/1",
????children:?[
????????{?path:?"product/:id",?component:?{?template:?"#product"?}?},
????????{?path:?"photo",?component:?{?template:?"#photo"?}?}
????]
}
子路由是在router-view中嵌套了另一个router-view且它需要注册到路由对象里某个路由匹配规则中的children属性中,通过点击按钮或超链接可以让父路由所包含的子路由显示出来且不会把父路由组件给切换掉。
关于路由的总结
通常情况下,一个页面上只能有一个router-view,但可以有多个router-link,无论在同一个页面上的哪一个router-link发起了路由请求、待路由匹配成功后都是将对应的路由组件插入到这个页面上的那个唯一的router-view容器中。
路由组件和普通组件的结合使用
经典的top、left、right的css布局中把页面分成了顶部、侧边栏和内容区域,如果用路由来实现,那么当访问根页面的时候就需要render一个普通组件(index.vue)到index.html中,index.vue中把top直接做成一个固定的顶部banner,侧边栏则可以使用普通组件(left.vue)作为index.vue组件的普通子组件插入,然后右边的内容区域(content)则通过left.vue的router-link的点击发起路由请求进行切换不同的内容。由于在index页面上所有的路由链接发起的请求都是将对应的路由组件加载到同一个router-view(右边content区域),这就符合一个页面上只能有一个router-view的定义。如果你把left区域做成一个路由组件,那么index.vue中就会出现两个router-view,这样就违背了一个页面上只能有一个router-view的原则,这两个router-view(即侧边栏和右边内容区域)由于它们各自都代表了一个路由请求,而一个浏览器地址栏却只能发起一个路由请求,不可能同时发起两个路由请求,所以很多时候我们可能都需要用路由组件去结合普通组件达到目的。
index.html
<!DOCTYPE?html><html>
<head>
????<meta?charset="utf-8"?/>
????<title></title>???
</head>
<body>
????<div?class="box"></div>
</body>
</html>
<script?src="/bundle.js"></script>
index.vue
将侧边栏注册为index.vue的普通子组件
<template>????<div?class="index-box">
????????<div?class="header-box"></div>
????????<div?class="bottom-box">
????????????<left></left>????
????????????<router-view></router-view>
????????</div>
????</div>
</template>
<script>
????import?left?from?"./left.vue";
????export?default?{
????????components:?{
????????????left:?left???????????
????????}
????}
</script>
right1.vue
<template>????<div?class="right-box">
????????<h1>卡俄斯</h1>
????</div>
</template>
<script>
????export?default?{?}
</script>
right2.vue
<template>????<div?class="right-box">
????????<h1>普罗米修斯</h1>
????</div>
</template>
<script>
????export?default?{ }
</script>
main.js
main.js将index.vue渲染到index.html
import?Vue?from?"vue";import?"./css/style.css";
import?router?from?"./js/router";
import?index?from?"./components/index.vue";
var?vm?=?new?Vue({
????el:?".box",????
????router:?router,
????render:?(c)?=>?{?return?c(index);?}?//注意render方法并不会通过路由请求得到index.vue,而是直接渲染了index.vue组件到index.html
});
router模板
import?Vue?from?"vue";import?VueRouter?from?"vue-router";
import?right1?from?"../components/right1.vue";
import?right2?from?"../components/right2.vue";
Vue.use(VueRouter);
const?router?=?new?VueRouter({??
????routes:?[
????????{?path:?"/",?redirect:"/index/right1"?},
????????{?path:?"/index/right1",?component:?right1?},
????????{?path:?"/index/right2",?component:?right2?}
????]
});
export?default?router;
路由组件组
一个页面只能有一个唯一的router-view,如果想实现一个路由请求能渲染多个路由组件,则可以为router-view指定name属性,然后在路由模板里使用components(注意是复数)指定多个路由组件匹配同一个路由请求。这样过程是:客户端发起路由请求,路由对象开始匹配这个路由地址,它首先匹配浏览器的路由地址,然后进入匹配成功的路由模板,接着发现有components路由组件组的定义,它会根据conponents中定义的路由匹配名称找到对应的多个路由组件一并返回给客户端,也就是说router-view一旦定义了name,那么整个路由匹配就会先匹配浏览器的路由地址,成功后再匹配components里的路由组件,最后再返回给客户端。所以,路由组件组的意思就是匹配一个路由地址返回多个路由组件。
<div?id="box">????<router-view></router-view>??//没有指定name属性的router-view在路由匹配成功后会把对应的组件插入这个路由组件
????<router-view?name="left"?class="left"></router-view>?//指定name属性,让路由对象在components中查找对应的路由组件
????<router-view?name="right"?class="right"></router-view>
</div>
<script>
????var?header?=?{
????????template:"<h5>header</h5>"
????}
????var?left?=?{
????????template:?"<h5>left</h5>"
????}
????var?right?=?{
????????template:?"<h5>right</h5>"
????}
????var?router?=?new?VueRouter({
????????routes:?[
????????????{
????????????????path:?"/",?components:?{?//当路由请求的是根目录时,路由匹配成功后不再返回某个单一的组件,而是返回多个由components指定的且与router-view的name相匹配的路由组件
????????????????????default:?header,?//default默认返回header组件
????????????????????left:?left,?//自定义指向left组件
????????????????????right:?right?//自定义指向right组件
????????????????}
????????????},
????????]
????});
????var?vm?=?new?Vue({
????????el:?"#box",
????????data:?{
????????????msg:"hello"
????????},
????????router:router
????});
</script>
子路由组件、子路由组件组的结合使用
但以上写法无法切换右边内容区域,考虑改造,参考如下代码来深入理解路由组件的嵌套规则,先看下图
铁壳蛹图片展示了路由组件嵌套后的效果,整个页面分为top和bottom,top是header元素,它是固定的一个div。bottom是一个路由组件,它匹配对根目录的路由请求。bottom分为侧边栏和右边内容区域,侧边栏是一个普通的组件,将它注册为bottom路由组件的子组件,当页面一加载就会显示header和bottom,由于侧边栏不是路由组件,所以它也会随同bottom路由组件一起显示出来。接下来就是右边内容区域,很明显它是一个随着导航链接进行切换的路由组件,所以可以在bottom路由组件里定义left侧边栏和一个右边内容区域的router-view,右边内容区域是属于嵌套在bottom里的子路由组件,所以再路由匹配中还需要使用children属性来指定。现在思考一下,当点击register后(看上图),右边内容区域并不是只显示一个路由组件,而是显示了两个,一个是register1,另一个则是register2,这就需要两个router-view才行,其中一个不需要设置name,将它用来展示默认的email和register1两个路由组件,它们可以随着email和register两个超链接的点击而自动切换,而剩下一个register2怎么办呢?可以把它放在默认的router-view的后面,给它指定一个name,由于register1和register2隶属于一个相同的路由地址,所以我们可以在路由模板中设置components对它们进行匹配。
index.html
<!DOCTYPE?html><html>
<head>
????<meta?charset="utf-8"?/>
????<title></title>???
????<style>
????</style>
</head>
<body>
????<div?class="box">
????????<div?class="header-box"></div>
????????<router-view></router-view>?//用于显示bottom路由组件
????</div>
</body>
</html>
<script?src="/bundle.js"></script>
main.js
import?Vue?from?"vue";import?router?from?"./js/router";
var?vm?=?new?Vue({
????el:?".box",????
????router:?router???
});
bottom.vue
<template>????<div?class="bottom-box">
????????<left?class="left-box"></left>
????????<div?class="right-box">
????????????<router-view></router-view>?//email、register1路由组件会插入这个容器
????????????<router-view?name="register"></router-view>?//register2路由组件会插入这个容器
????????</div>
????</div>
</template>
<script>
????import?left?from?"../components/left.vue";
????export?default?{
????????components:?{
????????????left:?left
????????}
????}
</script>
left.vue
left作为bottom路由组件的普通子组件
<template>????<div?class="left-box">
????????<ul>
????????????<li><router-link?to="/index/email">email</router-link></li>
????????????<li><router-link?to="/index/register">register</router-link></li>
????????</ul>
????</div>
</template>
<script>
????export?default?{?}
</script>
email.vue
bottom的子路由组件email.vue会根据路由请求显示在bottom路由组件里默认的router-view里边
<template>????<div?class="right-content0">
????????<h1>email</h1>
????</div>
</template>
<script>
????export?default?{?}
</script>
register1.vue
bottom的子路由组件register1.vue会根据路由请求显示在bottom路由组件里默认的router-view里边
<template>????<div?class="right-content1">
????????<h1>register1</h1>
????</div>
</template>
<script>
????export?default?{}
</script>
register2.vue
bottom的子路由组件register2.vue会根据路由请求显示在bottom路由组件里命名的router-view里边
<template>????<div?class="right-content2">
????????<h1>register2</h1>
????</div>
</template>
<script>
????export?default?{}
</script>
router模板
import?Vue?from?"vue";import?VueRouter?from?"vue-router";
import?bottom?from?"../components/bottom.vue";
import?email?from?"../components/email.vue";
import?register1?from?"../components/register1.vue";
import?register2?from?"../components/register2.vue";
Vue.use(VueRouter);
const?router?=?new?VueRouter({??
????routes:?[
????????{
????????????path:?"/",
????????????component:?bottom,?//路由根请求返回bottom组件插入到index.html的router-view里面
????????????redirect:"/index/email",
????????????children:?[
????????????????{?path:?"/index/email",?component:?email?},?//右边内容区域默认显示email组件
????????????????{
????????????????????path:?"/index/register",?//请求这个路由时返回两个子路由组件
????????????????????components:?{
????????????????????????default:?register1,?//default:插入未命名的router-view中
????????????????????????register:?register2??//插入命名的router-view中
????????????????????}
????????????????}
????????????]
????????}
????]
});
export?default?router;
路由组件的动画
独角虫与组件动画是一样的设置方式,但唯一不同点是不需要一个布尔值来控制显示与隐藏,这个工作路是对象自动根据匹配的路由显示相应的组件而隐藏了不需要的组件。 <transition?mode="out-in">????????<router-view></router-view>?
</transition> .v-enter,.v-leave-to{
????opacity:0;
????transform:translateX(150px);
}
.v-enter-active,?.v-leave-active?{
????transition:all?0.5s?ease;
}
内容总结
以上是互联网集市为您收集整理的Javascript - Vue - 路由全部内容,希望文章能够帮你解决Javascript - Vue - 路由所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。