@vuerouter,指引前进的方向
纲要
- 什么是路由
- VueRouter的两种使用方式
- 基于Vue-cli(脚手架)的vuerouterj简单实例
路由的概念
说到什么是路由,我们就得把前端路由和后台路由区分开来。后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源,这个对应关系就是后端中的路由。前端路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;这种通过hash改变来切换页面的方式,称作前端路由。
使用Vue构建的单页面应用程序,需要路由来显示组间的相互跳转。
VueRouter的两种使用方式
- 声明式使用
使用标签创建连接,to属性中传入路径,然后在指定显示的位置使用标签接收显示,link默认解析为a标签,但可以使用tag属性进行更改。声明式使用的基本流程如下:
html中键入代码
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- 使用 router-link 组件来导航. -->
<!-- 通过传入 `to` 属性指定链接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
-----摘录自官方网站
-编程式使用
除了使用 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。在 Vue 实例内部,你可以通过
r
o
u
t
e
r
访
问
路
由
实
例
。
因
此
你
可
以
调
用
t
h
i
s
.
router 访问路由实例。因此你可以调用 this.
router访问路由实例。因此你可以调用this.router.push or replace or go。想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。当你点击 时,这个方法会在内部调用,所以说,点击 等同于调用 router.push(…)
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
------摘录自官方网站
replace方法类似,go(n)方法表示回退n步,replace和push的区别在于push每次操作记录会存入记录栈中,而replace会重新创建一个记录栈,英文好的同学甚至可以从它们的英文释义中找到这个区别。
基于Vue-cli的VueRouter简单实例
-
构建步骤
1 明确路由组件有哪些 并将路由组件在views文件中定义出来
2 在routers文件中配置映射所有路由组件并向外暴露配置对象
3 在mian.js中配置路由器
4 在相应位置写标签router-link,router-view使用路由 -
实例说明
About和Home为同级路由
home可跳转到News显示4个新闻,也可跳转到messages显示四条消息,同时四条消息都有详细的内容,点击每一条消息可以跳转显示每一条消息的详细内容,那么问题来了,用户的操作是不规律的,如何确定用户点击的是哪一条消息从而实现指定消息的跳转呢?这就是路由的动态匹配,我可以使用路径参数达成目标,你可以在一个路由中设置多段“路径参数”,对应的值都会设置到 $route.params 中。例如:
模式 | 匹配路径 | $route.params |
---|---|---|
/user/:username | /user/evan | { username: ‘evan’ } |
/user/:username/post/:post_id | /user/evan/post/123 | { username: ‘evan’, post_id: ‘123’ } |
$route表示当前路由,$router表示当前组件,两者都可以通过this引用
- 目录结构
实例代码
About.vue
<template>
<div>
About
</div>
</template>
<script>
export default {
name: 'About'
}
</script>
<style>
</style>
Home.vue
<template>
<div>
<h1>Home</h1>
<router-link to="/home/news">News</router-link>
<router-link to="/home/messages">Messages</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'Home'
}
</script>
<style>
</style>
News.vue
<template>
<div>
<h1>News</h1>
<ul>
<!--按照规范,这里应该使用new来表示每一个消息的,但可惜new是保留字,不行-->
<li v-for="(n,index) in news" :key="index">{{n}}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'News',
data(){
return{
news:['我是消息1','我是消息2','我是消息3']
}
}
}
</script>
<style>
</style>
Messages.vue
<template>
<div>
<ul>
<li v-for="message in messages" :key="messages.id">
<router-link :to="`/home/messages/detail/${message.id}`">{{message.title}}</router-link>
<button @click="pushShow(message.id)">push查看</button>
<button @click="replaceShow(message.id)">replace查看</button>
</li>
</ul>
<button @click="$router.back()">回退</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'Messages',
data(){
return{
messages:[]
}
},
mounted () {
setTimeout( ()=>{
const messages = [
{title:'message-001',id:1},
{title:'message-002',id:2},
{title:'message-003',id:3},
{title:'message-004',id:4}
]
this.messages = messages
},1000)
},
methods:{
pushShow(id){
this.$router.push(`/home/messages/detail/${id}`)
},
replaceShow(id){
this.$router.replace(`/home/messages/detail/${id}`)
}
}
}
</script>
<style scoped>
</style>
MessageDetail.vue
<template>
<div>
<div>
<p>ID:{{$route.params.id}}</p>
<ul>
<li>id:{{message.id}}</li>
<li>title:{{message.title}}</li>
<li>content:{{message.content}}</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'MessageDetail',
data(){
return{
message:{}
}
},
mounted(){
setTimeout(() =>{
const allMessages = [
{title:'message-001',content:'001content.....',id:1},
{title:'message-002',content:'002content.....',id:2},
{title:'message-003',content:'003content.....',id:3},
{title:'message-004',content:'004content.....',id:4}
]
this.allMessages = allMessages
//将字符串变成数字
const id = this.$route.params.id * 1
this.message = this.allMessages.find(detail=>detail.id === id)
},1000)
},
//这里涉及到一个问题,就是用户点击触发路由的时候,路由路径并没有变化,一直都是'/home/message/detail'
//发生变化的只是后面的参数,这是不会触发路由的,解决的办法就是使用watch监视路由路径的改变,进行路由的跳转
watch:{
//$route表示路由对象
$route:function (value) { //路由路径发生了改变,实际上是param发生了改变,value是改变的最新的route值
//一旦发生了改变,就执行这个函数
const id = value.params.id * 1
this.message = this.allMessages.find(detail=> detail.id === id)
}
}
}
</script>
<style>
</style>
App.vue
<template>
<div>
<div><h2>Router Basic -01</h2></div>
<div class="row">
<div class="row-left">
<div class="content">
<!--vue-router使用的第一种方式:声明式使用 link声明 view显示-->
<router-link to="/about">About</router-link>
<router-link to="/home">Home</router-link>
</div>
</div>
<div class="row-right">
<keep-alive>
//通过属性携带向路由组件传递参数,msg在about和home中声明接收之后均可使用
<router-view></router-view>
</keep-alive>
</div>
</div>
</div>
</template>
<script>
export default {
name:'App',
}
</script>
<style scoped>
.row{
width:400px;
height:300px;
margin: 0 auto;
border:1px solid red;
}
.row-left{
width:30%;
height: 100%;
float: left;
border:1px solid blue;
}
.row-right{
width:68%;
height:100%;
float: left;
}
</style>
main.js
import Vue from 'vue'
import App from './App'
//注册配置对象
import router from './routers'
new Vue({
el:'#app',
components:{
App,
},
template: '<App/>',
router //映射
})
index.js
/*路由器模块*/
//1引入vue和vue-router
import Vue from 'vue'
import VueRouter from 'vue-router'
//2.声明使用路由
Vue.use(VueRouter)
//3.引入路由组件
import About from '../views/About'
import Home from '../views/Home'
import News from '../views/News'
import Messages from '../views/Messages'
import MessageDetail from '../views/MessageDetail'
//4.向外暴露路由配置对象 并配置路由
export default new VueRouter({
routes:[
{
//路径 以'/'开头表示根路径
path:'/about',
//组件名
component:About,
},
{
path:'/home',
component:Home,
children:[
{
path:'/home/news',
component:News,
},
{
//子路由路径前面的根目录可以不写
path:'messages',
component:Messages,
children:[
{
//传入id参数,使其匹配到指定的消息细节上显示
path:'/home/messages/detail/:id',
component:MessageDetail,
}
]
},
{
path:'',
redirect:'/home/news',
},
]
},
{
//设置默认路径为'/about',就是不触发路由的时候,定位到/about这个组件
path:'/',
redirect:'/about'
},
]
})
关于vuerouter的知识还有很多,我只是抛砖引玉,大家要想了解关于vuerouter的更细致的东西,请点击进入官方API进行阅读:Vue-router
我的分享就到这里了,感谢大家阅读。