修改url却不刷新网页的方法
location.hash = 'newUrl'html5模式,history.pushState({},'','newUrl')入栈操作history.back()出栈操作html5模式,history.replaceState({},'','newUrl')
安装
npm install vue-router --save
使用
-
导入路由对象,并且调用
Vue.use(VueRouter) -
创建路由实例,并且传入路由映射配置
-
在
Vue实例中挂载创建的路由实例在
src文件夹下创建router文件夹,再创建index.js文件,若用脚手架选择则会自动生成import VueRouter from 'vue-router' import Vue from 'vue' //1.通过Vue.use(插件) 安装插件 Vue.use(VueRouter) //2.创建VueRouter实例 const router = new VueRouter({ //配置映射关系 routes:[ ] }) //3.将router对象传入Vue实例 export default routermain.jsimport Vue from 'vue' import App from './App' import router from './router' //默认会找文件夹下的index.js Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', //挂载路由实例 router, render:h => h(App) })
路由跳转的方法
-
router-link<router-link to="keyframes">点击验证动画效果 </router-link> -
this.$router.push({ path:'/user'}) -
this.$router.replace{path:'/' }
重要提示:一定不要用location.href或者history对象的方法跳转,否则无法实现SPA的效果,数据会被直接刷新重置!!!!
举例-静态路由和动态路由
在components文件夹下新建home.vue,about.vue
<template>
<div>
<h2>我是用户:{{userId}}</h2>
<p>请多多指教!</p>
</div>
</template>
<script>
export default {
name:'user',
computed:{
userId(){
return this.$route.params.id
//$route 表示目前正在活跃的路由
}
}
}
</script>
<style>
</style>
在App.vue也就是组件树的根中
<template>
<div id="app">
<router-link to='/home'>首页</router-link>
<router-link to='about'>关于</router-link>
<!-- router-link 是已经被注册好的全局组件 必须有 to 属性 指定url 渲染为a标签 -->
<!-- 其他属性
tag = 'button':指定渲染成什么元素
replace:不用写值,点击有该属性的标签切换url时,前进后退不可选
active-class = 'active':替换下面的 router-link-active 为 active,统一替换所有的话,需要在index.js中new实例中指定 linkActiveClass:'active'
-->
<!-- class属性
router-link-active: 正在活跃,'首页'被点击后,'首页'的class中会有该类名
可以通过css选择器,修改样式
-->
<router-link :to='"/user/" + userId'>用户</router-link>
<!-- 动态路由,使用 v-bind 动态绑定 -->
<router-view></router-view>
<!-- router-view 同上 指定显示的组件位置 -->
</div>
</template>
<!-- 假设不通过router-link标签跳转页面 使用自己指定的原生标签 并且指定方法跳转
在每个对象中会有 this.$router 对象,这个对象就是index.js中的router实例
this.$router.push('url')等价于 to
this.$router.replace('url')等价于 replace
-->
<script>
export default {
name: 'App',
data(){
return {
userId:'zhansan'
}
}
}
</script>
<style>
</style>
在router文件夹下的index.js中
import VueRouter from 'vue-router'
import Vue from 'vue'
import home from '../components/home.vue'
import about from '../components/about.vue'
// 导入组件
//1.通过Vue.use(插件) 安装插件
Vue.use(VueRouter)
//2.创建VueRouter实例
const router = new VueRouter({
//配置映射关系
routes:[//每个映射关系为一个对象
{
path:'/',
redirect:'/home',
// 为了默认显示首页 当路径为根路径则自动重定向到/home
},
{
path:'/home',//url
component:home//组件
},
{
path:'/about',
component:about
},
{
path:'/user/:id',
// :id 为动态绑定的属性
component:user ,
// 可以在user组件所在vue文件中 使用this.$route.params.id获取
}
],
mode:'history'
//不写默认为哈希模式 localhost:XXXX/#/home
//指定history模式 localhost:XXXX/home
})
//3.将router对象传入Vue实例
export default router
打包文件的解析
通常打包后,会形成一个js文件,我们通常设置为bundles.js,因为所有js代码都在一个文件中,所有当用户请求网页时,这个js文件过大,导致网页会有短暂空白。
VueCLI会把项目打包成如下目录结构:
diststaticcsscss.XXXX.css抽离整合的css文件css.XXXX.css.map压缩后的代码出错不好找位置,map文件帮助寻找bug位置
jsapp.XXXX.js当前应用程序开发的所有代码(业务代码)manifest.XXXX.js为了打包的代码做底层支持,如commonjs规范,导入导出vendor.XXXX.js存放所有第三方的包代码....js.map
index.html
但是即便如此,js文件可能还是会很大,所以就有了路由的懒加载
路由的懒加载
- 路由懒载的主要作用就是将路由对应的组件打包成一个个的
js代码块 - 只有在这个路由被访问到的时候才加载对应的组件
懒加载的方式
-
方式一:结合
Vue的异步组件和Webpack的代码分析const Home = resolve => { require.ensure(['../componets/Homne.vue'], () => { resolve(require('../componets/Homne.vue')) })} //这种代码是早期代码,非常不推荐写,在老项目中可能会出现,要求能看出这是懒加载 -
方式二:
AMD写法const About = resolve => require(['../componets/About.vue'],resolve) -
方式三:
ES6写法const Home = () => import('../components/Home.vue') //推荐使用
将例子中的index.js进行改造(仅显示修改或添加的代码)
const home = () => import('../components/home.vue')
const about = () => import('../components/about.vue')
const user = () => import('../components/user.vue')
路由嵌套
目标:点击首页下的新闻会跳转到home/news,点击消息会跳转到home/message,并且在home时默认跳转到home/news
修改home.vue(仅显示修改或添加的代码)
<template>
<div>
<h2>我是首页</h2>
<p>请多多指教!</p>
<router-link to='/home/news'>新闻</router-link>
<router-link to='/home/message'>消息</router-link>
<!-- 别忘了开头的'/'一定要加 -->
<router-view></router-view>
<!-- router-view 依旧显示内容 -->
</div>
</template>
将例子中的index.js进行改造(仅显示修改或添加的代码)
const homeNews = () => import('../components/homeNews.vue')
const homeMess = () => import('../components/homeMess.vue')
const router = new VueRouter({
//配置映射关系
routes:[
{
path:'/',
redirect:'/home',
// 为了默认显示首页 当路径为根路径则自动重定向到/home
},
{
path:'/home',
component:home,
children:[//使用 children 属性实现路由嵌套
{
path:'/',
redirect:'news'
},
{
path:'news',//children 中的子路由 路径开头不要有'/'
component:homeNews
},
{
path:'message',
component:homeMess
}
]
},
{
path:'/about',
component:about
},
{
path:'/user/:id',
// :id 为动态绑定的属性
component:user ,
// 可以在user组件所在vue文件中 使用this.$route.params.id获取
}
],
mode:'history'
})
传递参数
- 传递参数主要有两种类型:
params和query params的类型- 配置路由格式:
/router/:id - 传递的方式:在
path后面跟上对应的值 - 传递后形成的路径:
/router/123,/router/abc
- 配置路由格式:
query的类型- 配置路由格式:
/router,也就是普通配置 - 传递的方式:对象中使用
query的key作为传递方式 - 传递后形成的路径:
/router?id=123,/router?id=abc
- 配置路由格式:
query的两种用法
<router-link :to='{ path:"home", query:{name:"wang",age:18 } }'>消息</router-link>
<!-- 用query时,使用v-bind传递给to属性一个对象 -->
<!-- 对象中的path就是路由,query对象存放需要传递的数据 -->
<!-- 这时url会变成:http://localhost:8080/home?name=wang&age=18 -->
<!-- 在home.vue中 使用 this.$route.query.XX 使用 -->
<router-link @click='messClick'>消息</router-link>
<script>
messClick(){
this.$router.push({path:"home", query:{name:"wang",age:18 }})
}
</script>
全局导航守卫
//index.js
//前置守卫(guard)
router.beforeEach(function(to,from,next){
//从 from 跳转到 to
//两者皆为 route 对象
document.title = to.matched[0].meta.title//自己手动在路由对象中定义meta属性 表示元数据
//把跳转页面的title修改掉
next()//必须调用
})
//后置钩子(hook)
router.afterEach((to, from) => {
//无需调用next()
})
keep-alive保持状态
<keep-alive exclude="user,home">
<router-view></router-view>
</keep-alive>
<!-- 被keep-alive 包裹的元素在切换路由时,会缓存下来,不会销毁,下次切换回来不会再重新生成 -->
<!-- 只有被这个包裹,才能使用 activated 和 deactivated 方法 -->
<!-- 它拥有两个属性 exclude 和 include -->
<!-- exclude:字符串或正则表达式,填写组件返回的name属性值,这些组件将不会被缓存下来,多个用逗号隔开,逗号两边切记不要空格 -->
<!-- include:同上,只有匹配的组件将会被缓存 -->