目录
location.hash\history.pushState方法
VueRouter(router)
和v-if/v-show一样,是用来切换组件的显示,Vue Router是通过哈希来切换(#/xxx),且能够在切换的时候传递参数。注意要在Vue导入之后导入。
VueRouter引入链接
<script src=”https://unpkg.com/vue-router@2.0.0/dist/vue-router.js”></script>
使用方法
- 定义需要切换的组件对象,例如one={template:'<div>one</div>’},two={template:'<div>two</div>’}。
- 通过一个包含多个对象的数组来定义路由规则,每个对象就是一个规则,例如const v=[{path:’/one’,component:one},{path:’/two’,component:two}]。这里的one、two为component对象,不能传component的名称,path:’/’相当于当前路径。
- 创建VueRouter对象,const vr=new VueRouter({routes:v})。
- 将创建好的路由对象绑定在Vue实例上new Vue({el:’#app’,data:{},router:vr})。
- 通过直接设置location.href=’#/one’或this.$router.push(‘/one’)或this.$router.replace(‘/one’)(注意和this.$route区分,route为当前匹配的路由对象信息,router为全部的路由信息)跳转或a标签改变当前网页链接,例如<a href=’#/one’>,点击便会改变当前url地址为….html#/one,此时router-view标签便会根据路由规则查找path=’/one’的组件显示,此例会显示one的组件。注意push相当于是压入栈顶,可以通过this.$router.back()方法或浏览器后退键回到上一次的路由,而replace相当于把栈顶的给替换了,是无法回到上一次的路由。
router-view标签
根据不同的路由规则和当前的url对应显示不同的组件。
name属性(命名视图)
当有name属性后为命名视图,作用:在相同的url情况下想通过router-vie标签展示不同的组件。例如给router-view标签添加属性name=’rv1’,还需改变路由规则const v=[{path:’/one’,components:{rv1:one,rv2:two}},{path:’/two’,component:two}],这时url地址为….html#/one时,router-view标签显示组件one,想要显示组件two,把name改为’rv2’即可(改url也行)。
router-link标签
搭配router-view标签,用于切换组件。上面有to属性表示当前url后拼接的地址即使以https://开头依然会拼接在其后,注意不需要像a标签一样添加#了(直接to=’/one’即可),tag属性表示当前标签的显示形式(以HTML中的什么标签替换该标签,默认为a标签),显示点击后的标签的class会自动添加值’router-link-exact-active router-link-active’,在原router-link中设置属性active-class=’str’,则router-link-active会变成str。
传递参数形式
方法一:通过URL参数在之后添加?key1=value1&key2=value2的形式,在组件对象的生命周期方法(例如one={template:'<div>one</div>’,created(){}})中通过this.$route.query拿到数据对象,对象的属性和值与其对应。
方法二:在指定路由规则时通过占位符传递数据属性名,通过URL传递数据属性值。例如const v=[{path:’/one/:name/:age‘,component:one,props:true},{path:’/two’,component:two}],<a href=’#/one/pyf/18‘>,在组件对象的生命周期方法(例 如one={template:'<div>one</div>’,created(){}})中通过this.$route.params拿到数据对象(不推荐,取值方式推荐使用下面代码),对象的属性和值与其对应(注意此时url/#/one/不能显示one组件了,只有url/#/one/str1/str2才能显示one组件,其中str1、str2可以随便写)。
通常通过在路由中开启props属性后,在组件中绑定传过来的对应属性名,后便可以在模板中直接使用。例如下面代码props开启后传递id属性。
const User = {
// 请确保添加一个与路由参数完全相同的 prop 名
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const routes = [{ path: '/user/:id', component: User, props: true }]
嵌套路由
在定义路由规则时,添加children属性,该属性为新的子路由规则例如const v=[{path:’/one’,component:one,children:[{path:’oneson’,component:oneson}]},{path:’/two’,component:two}],注意嵌套路由(子路由)可以省略一级路径的地址,且不用带/,例中切换到oneson组件时的url为….html#/one/oneson,注意router-link标签中的to写法还是不变(to=’/one/oneson’),切换组件oneson是在组件one下显示,而不会将整个one组件完全替换。
重定向
当打开网页,想默认显示组件two而不在url后面加/two时,我们需要重定向,即在使用方法的第二步的数组中添加一个对象{path: ‘/’, redirect: ‘/two’ },此时当我们输入url(url/、url/#、url/#/都行)会自动给我们添加#/two,但是此时输入url/#/b则不会自动显示组件two(输入不对应的其它url也不会),如果想要显示,即可将path的路径/改为*即可(注意这些由于权重问题是不会影响跳转one组件的,正常输入one的url也会显示one组件)。如果是在嵌套路由中,即想默认显示子路由,我们需要将path:”。
路由拦截
当我们需要进行判断满足条件时在跳转(通常导航中的我的,当未登陆时跳转为登陆页面),这时我们可以在需要拦截到的组件的生命周期方法mounted中添加判断,当不满足时使用location.href=”或this.$router.push(”)进行跳转。Vue提供了更好的解决方法如下。
全局前置守卫
在创建VueRouter对象之后添加语句vr.beforeEach(funtion(to,from,next){}),当跳转到任何路由组件页面之前会运行function函数,其中to、from是一个对象,包含跳转路由的信息,to.fullPath指向跳转到的路由组件,from.fullPath指向由哪个路由组件跳转的,next为一个函数名,当next()执行时,才能跳转到to.fullPath的路径上去,也可以next(str)跳转到其它组件页面(str为路由路径例如’/one’)。
全局后置钩子
在创建VueRouter对象之后添加语句vr.afterEach(funtion(to,from){}),当跳转到路由组件页面后才会运行function函数,参数意义同上,无next。
局部守卫
都是组件的生命周期函数。
- beforeRouterEnter(to,from,next){}:在跳转到该页面之前被调用,如果只需要在单个路由组件中添加拦截,我们可以在需要拦截的组件对象中添加该方法,其中参数意义同上。
- beforeRouterUpdate(to,from,next){}:在路由改变,但组件被复用时调用,即嵌套路由中子组件之间的切换,参数同上。
- beforeRouterLeave(to,from,next){}:离开该组件的对应路由时调用,其中next(false)可以禁止离开。
命名路由
当定义路由规则的数组中的对象中添加属性name:’yf’,此时我们可以通过this.$router.push({name:’yf’,params:{name:’p’})访问设置name:’yf’路由的组件,也和点击下面router-link跳转。通过this.$route.params.name便可以拿到传入的参数’p’。
<router-link :to="{name:'yf',params:{name:'p'}}">
User
</router-link>
路由模式(history)
通常我们在设置路由时未加#号,而在切换时自动加上了#号,这时由于路由的模式是hash模式,它还有一种history模式,即不带#号的模式,我们可以通过在定义路由规则的数组的对象中添加属性mode:’history’实现,此时切换该路由时将不带#号(由于没有网络请求改变,通过客户端改变的网络地址,且去除#号后相当于正常网页,刷新网页时,会像后端发送请求,如果后端没有正确配置会返回404,所以后端需要配置当URL匹配不到任何静态资源时,应该返回同一个页面)。
路由原理
- hash路由:location.hash切换,通过window.onhashchange监听路径的切换。
- history路由:history.pushState切换(IE10以上支持),window.onpopstate监听路径的切换,注意是没有网络请求的,通过客户端改变的网络地址。
location.hash\history.pushState方法
js的BOM对象(window.location/history/navigator对象,弹出框,cookie,窗口和滚动条方法等)_YF-SOD的博客-CSDN博客
路由懒加载
项目(Vue-CLI)开发中,通常所有的路由都会在直接被打包(npm run build)到一个文件中,这时该文件过大,当客户端访问时网速不好,会导致加载过慢,此时我们可以采用路由懒加载(动态加载,当切换到该路由时,我们才去请求该路由的文件),会生成多个文件。使用方法:在定义路由规则时,将对象中的component属性指向一个函数function(){return import(/* webpackChunkName: “group-foo” */’path’)},其中path为该路由组件引入的相对路径,注释代表将该路由组件打包到带有group-foo的js文件命中(可以将多个组件合并到一个文件中),不写会单独打包。
自定义简易VueRouter(history模式)
定义后通过Vue.use(VueRouter)注册路由插件,使用和上面使用方式相同。
let _Vue = null
export default class VueRouter {
static install(Vue) {
// 1.判断当前插件是否已经被安装
if (VueRouter.install.installed) {
return
}
VueRouter.install.installed = true
// 2.把Vue构造函数记录到全局变量
_Vue = Vue
// 3.把创建Vue实例时候传入的router对象注入到Vue实例上
// 混入
_Vue.minxin({
beforeCreate() {
if (this.$options.router) {
_Vue.prototype.$router = this.$options.router
}
this.$options.router.init()
}
})
}
constructor(options) {
this.options = options
this.routeMap = {}
this.data = _Vue.observable({
current: '/'
})
}
init() {
// 遍历所有的路由规则,把路由规则解析成键值对的形式存储到routerMap中
this.createRouteMap()
// 注册router-link和router-view组件
this.initComponents(_Vue)
// 通过popstate监听url地址改变current值以及对应用到值的地方进行重新渲染。
this.initEvent()
}
createRouteMap() {
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
initComponents(Vue) {
const self = this
Vue.component('router-link', {
props: {
to: string
},
render(h) {
return h('a', {
attrs: {
href: this.to
},
on: {
click: this.clickHandler
}
}, [this.$slot.default])
},
methods: {
clickHandler(e) {
history.pushState({}, '', this.to)
this.$router.data.current = this.to
e.preventDefault()
}
}
// template: '<a :href="to"><slot></slot></a>'
})
Vue.component('router-view', {
render(h) {
const component = self.routeMap[self.data.current]
return h(component)
}
})
}
initEvent() {
window.addEventListener('popstate', () => {
this.data.current = window.location.pathname
})
}
}
自定义详细VueRouter(hash模式)
GitHub – aiwmyself/VueRouter: VueRouter-hash