vue-router 基本语法
一.介绍1.路由路由其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击页面上的about 按钮,页面中就要显示about 的内容。Home按钮 => home 内容, about按钮 => about 内容,也可以说是一种映射. 2.vue-router当你要把 vue-router 添加到项目。我们需要将组件(compone
一.介绍
1.路由
路由其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击页面上的about 按钮,页面中就要显示about 的内容。Home按钮 => home 内容, about按钮 => about 内容,也可以说是一种映射.
2.vue-router
当你要把 vue-router 添加到项目。我们需要将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们
二.基本使用
(一).动态路由匹配
//2.user.vue
<router-link to="/user/foo">/user/foo</router-link>
//2.router.js
const User = {
template: `<div>User {{ $route.params.id }}</div>`
}
/*新增user路径,配置了动态的id*/
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
const app = new Vue({ router }).$mount('#app')
注意:
复用组件时,路由参数的变化作出响应,可以简单地 watch(监测变化) $route 对象
const User = {
template: '...',
watch: {
'$route' (to, from) {
// 对路由变化作出响应...
}
}
}
在组件中使用
export default {
watch:{
$route(){
//重复使用操作
this.addViewTags();
}
},
methods: {
addViewTags(){
if(this.$route.name){
const route = this.$route
this.$store.dispatch('addVisitedViews',route);
}
}
}
}
(二).嵌套路由
简单的语法:
配置嵌套路由 message父页面 嵌套着news页面
path: '/message',
component: message,
children: [
{
path: 'news',
component: news
}
]
在message页面
<router-link to="/message/news">Message</router-link>
<router-view></router-view>
1.实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件,例如:
const User = {
template: `
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view></router-view>
</div>
`
}
const UserHome = { template: '<div>Home</div>' }
const UserProfile = { template: '<div>Profile</div>' }
const UserPosts = { template: '<div>Posts</div>' }
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
// 当 /user/:id 匹配成功,
// UserHome 会被渲染在 User 的 <router-view> 中
{ path: '', component: UserHome },
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
{ path: 'profile', component: UserProfile },
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
{ path: 'posts', component: UserPosts }
]
}
]
})
const app = new Vue({ router }).$mount('#app')
移步这里。
2.vue项目中路由配置小案例
配置路由router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import index from '@/components/index'
import about from '@/components/about'
import message from '@/components/message'
import news from '@/components/news'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect:'about'
},
{
path: '/',
name: 'index',
component: index,
children: [
{path: '/about',component: about},
{
path: '/message',
component: message,
children: [
{path: 'news',component: news},
]
}
]
}
]
})
index.vue
<template>
<div>
<router-link to="/about">关于我们</router-link>
<router-link to="/message">新闻资讯</router-link>
<div class="indexcnt">
<keep-alive> <router-view></router-view></keep-alive>
</div>
</div>
</template>
<script>export default {}</script>
<style lang="scss">
.indexcnt{
border:1px solid #ccc;
background-color: #ccc;
color: #fff;
}
</style>
about.vue
<template>
<div><h1>关于我们页面</h1><input type="tetx" name="name">
</div>
</template>
<script>export default {}</script>
<style scoped lang="scss">
</style>
message.vue
<template>
<div>
<h1>新闻资讯页面</h1>
<router-link to="/message/news">新闻信息</router-link>
<div class="messagecnt">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {}
</script>
<style lang="scss">
.messagecnt{
background-color: #fff;
color: #333;
}
</style>
news.vue
<template>
<div>
<h2>新闻列表</h2>
<ul class="ulSty"> <li v-for="item in news">{{item.title}}</li></ul>
</div>
</template>
<script>
export default {
data () {
return {
news:[
{"id":"01","title":'新闻列表1'},
{"id":"02","title":'新闻列表2'},
{"id":"03","title":'新闻列表3'},
{"id":"04","title":'新闻列表4'}
]
}
}
}
</script>
<style lang="scss">
.ulSty{
li{
list-style-type: none;
}
}
</style>
(三).缓存路由<keep-alive>
语法:
<keep-alive>
<router-view></router-view>
</keep-alive>
1.router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import index from '@/components/index'
import about from '@/components/about'
import user from '@/components/user'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect:'about'
},
{
path: '/',
name: 'index',
component: index,
children: [
{path: '/about',name: '关于我们',component: about},
{path: '/user',name: '用户信息',component: user}
]
}
]
})
2.user.vue
<template>
<div>
<h1>User:</h1>
用户信息
</div>
</template>
<script>
export default {
}
</script>
<style scoped lang="scss">
</style>
3.about.vue
<template>
<div>
<h1>about:</h1>
<input type="tetx" name="name">
</div>
</template>
<script>
export default {
}
</script>
<style scoped lang="scss">
</style>
4.index.vue
<template>
<div>
<router-link to="/about">关于我们</router-link>
<router-link to="/user">用户信息</router-link>
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss"></style>
(三).命名路由
通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
}
]
})
以下这两种方式都会把路由导航到 /user/123 路径。
要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象:
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
这跟代码调用 router.push() 是一回事:
router.push({ name: 'user', params: { userId: 123 }})
(四).命名视图----多个<router-view></router-view>
例如创建一个布局,有 sidebar(侧导航) 和 main(主内容) 两个视图,这个时候命名视图就派上用场了。
注意:在<router-view></router-view>要加 class="view" 还要标志a ,b
1.app.vue
<div id="app">
<router-link to="/">点击显示多个内容</router-link>
<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>
</div>
2.router.js
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const Baz = { template: '<div>baz</div>' }
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/',
components: {
default: Foo,//默认显示
a: Bar,
b: Baz
}
}
]
})
new Vue({
router,
el: '#app'
})
(五).编程式的导航
实例中定义一个方法,这个方法绑定在标签上,然后就设置路由跳转。
语法 this.$router.history.push('要跳转路由的地址')
小小demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.active{
color:red;
}
</style>
</head>
<body>
<div id="app">
<!--编程时导航-->
<button @click="goHome">去首页</button>
<button @click="goList">去列表</button>
<router-view></router-view>
</div>
</body>
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/vue-router/dist/vue-router.js"></script>
<script>
let home={
template:'<div>home</div>'
};
let list={
template:'<div>list</div>'
}
const routes=[
{path:'/home',component:home},
{path:'/list',component:list}
]
let router=new VueRouter({
routes:routes,
linkActiveClass:'active'
});
//默认加载第一个路径
router.push("/home");
let vm=new Vue({
el:"#app",
methods:{
//编程时导航
goHome(){
//页面跳转,push是增加到历史管理
this.$router.history.push('/home')
//go表示前进后退
//this.$router.history.go(-1)
},
goList(){
this.$router.history.push('/list')
//将当前历史管理替换成list
//this.$router.history.replace('/list')
}
},
// 会在实例中提供两个属性this.$route(属性),this.$router(方法);
router:router,
})
</script>
</html>
(六).重定向和别名
1.重定向:重定向也是通过 routes 配置来完成,
意思是,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b
1.下面例子是从 /a 重定向到 /b:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})
2.重定向的目标也可以是一个命名的路由:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: { name: 'foo' }}
]
})
3.动态返回重定向目标:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: to => {
// 方法接收 目标路由 作为参数
// return 重定向的 字符串路径/路径对象
}}
]
})
注意:动态返回重定向目标--》首先参数解构,获取hash、params、query,然后根据获取值进行逻辑判断之后动态路由重定向。这里的return值是path值,而不是params值,必须是一个已经存在的path才能进行路由重定向。而且这个path不能使自身,因为作为一个重定向路由跳转到自身还要继续重定向,就会进行一个死循环。
2.别名:是为让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构
/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。
(七).路由组件传参
在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。使用 props 将组件和路由解耦
1.props 配置:
1.布尔模式
如果 props 被设置为 true,route.params 将会被设置为组件属性。
{ path: '/user/:id', component: User, props: true },
2.对象模式
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。
const router = new VueRouter({
routes: [
{ path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
]
})
3.函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。
const router = new VueRouter({
routes: [
{ path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
]
})
URL /search?q=vue 会将 {query: 'vue'} 作为属性传递给 SearchUser 组件。
2.路由路径携带参数
1.配置路由
children: [
{
path: 'mdetail/:id',
component: messageDetail
}
]
2.路由路径
<router-link :to="'/home/message/mdetail/'+m.id">{{m.title}}</router-link>
3.路由组件中读取请求参数
this.$route.params.id
实例:基于嵌套路由:vue项目中路由配置小案例
补充:
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import index from '@/components/index'
import about from '@/components/about'
import message from '@/components/message'
import news from '@/components/news'
import newdetail from '@/components/newdetail'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect:'about'
},
{
path: '/',
name: 'index',
component: index,
children: [
{path: '/about',component: about},
{
path: '/message',
component: message,
children: [
{
path: 'news',
component: news,
children:[
{path: 'newdetail/:id',component: newdetail}
]
},
]
}
]
}
]
})
news.vue:
<template>
<div>
<h2>新闻列表</h2>
<ul class="ulSty">
<li v-for="item in news">
<router-link :to="'/message/news/newdetail/'+item.id">{{item.title}}</router-link>
</li>
</ul>
<div class="mewscnt">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
data () {
return {
news:[
{"id":"01","title":'新闻列表1'},
{"id":"02","title":'新闻列表2'},
{"id":"03","title":'新闻列表3'},
{"id":"04","title":'新闻列表4'}
]
}
}
}
</script>
<style lang="scss">
.ulSty li{
list-style-type: none;
}
.mewscnt{
background-color: #f00;
color: #fff;
}
</style>
newdetail.vue
<template>
<div>
<p>新闻详情:id为:{{this.$route.params.id}}</p>
</div>
</template>
<script>
export default {
}
</script>
<style scoped lang="scss">
</style>
(八). 用 vue-route实现导航守卫
导航守卫表示路由正在发生改变。正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
记住参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route 对象来应对这些变化,或使用 beforeRouteUpdate 的组件内守卫。
(九).路由元信息
定义路由的时候可以配置 meta 字段:
routes: [
{
path: '/foo',
component: Foo,
children: [
{
path: 'bar',
component: Bar,
// a meta field
meta: { requiresAuth: true }
}
]
}
]
routes 配置中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录。
一个路由匹配到的所有路由记录会暴露为 $route 对象(还有在导航守卫中的路由对象)的 $route.matched 数组。因此,我们需要遍历 $route.matched 来检查路由记录中的 meta 字段。
下面例子展示在全局导航守卫中检查元字段:
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!auth.loggedIn()) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // 确保一定要调用 next()
}
})
(十).过渡动效
<transition>
<router-view></router-view>
</transition>
(十 一).滚动行为
使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。注意: 这个功能只在支持 history.pushState 的浏览器中可用。
(十 二).路由懒加载
当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。
(1).异步组件模式:
const Foo = resolve => {
// require.ensure 是 Webpack 的特殊语法,用来设置 code-split point
// (代码分块)
require.ensure(['./Foo.vue'], () => {
resolve(require('./Foo.vue'))
})
}
(2).Amd风格的require模式
(代码分块的语法)
const routes = [
{
path: '',
component: resolve => require(['./index.vue'],resolve),
}, {
path: '/user',
component: resolve => require(['./user.vue'],resolve),
}];
ensure模式写起来有点繁琐,我更倾向于后面一种写法。
(3).amd 与 ensure 区别
1.require-amd
说明: 同AMD规范的require函数,使用时传递一个模块数组和回调函数,模块都被下载下来且都被执行后才执行回调函数
语法: require(dependencies: String[], [callback: function(…)])
参数
dependencies: 模块依赖数组
callback: 回调函数
2.require-ensure
说明: require.ensure在需要的时候才下载依赖的模块,当参数指定的模块都下载下来了(下载下来的模块还没执行),便执行参数指定的回调函数。require.ensure会创建一个chunk,且可以指定该chunk的名称,
如果这个chunk名已经存在了,则将本次依赖的模块合并到已经存在的chunk中,最后这个chunk在webpack构建的时候会单独生成一个文件。
语法: require.ensure(dependencies: String[], callback: function([require]), [chunkName: String])
dependencies: 依赖的模块数组
callback: 回调函数,该函数调用时会传一个require参数
chunkName: 模块名,用于构建时生成文件时命名使用
注意点:requi.ensure的模块只会被下载下来,不会被执行,只有在回调函数使用require(模块名)后,这个模块才会被执行。
(十 三).API
(十 四).注意点
1.默认路由 redirect
2.缓存路由<keep-alive>
在<keep-alive> 里面放<router-view>。
更多推荐
所有评论(0)