前言
后端渲染 ------存在性能问题
Ajax前端渲染---------提高了性能但不支持前进后退
SPA:单页页面程序,在前后端分离的基础上增加了一层前端路由,整个网站只有一个页面,内容的变化通过局部更新同时支持前进后退。
SPA实现原理之一:基于URL地址的hash,也就是锚点(#),本质上是改变window.location的href(hyper reference )属性(hash的变化会导致浏览器记录访问历史的变化,但是hash的变化不会触发新的请求。)
改变hash的两种方式
location.hash = 'url'
history.pushState({},'','url')//可撤回的操作,栈结构显示栈顶。
history.replaceState({},'','url')//不可撤回
histort.back 等同于history.go(-1)
前端路由:监听根据不同的用户事件,显示不同的页面内容
本质:用户事件与事件处理函数之间的对应关系。
<conponent :is="name"></component>
name变化显示不同组件
location.hash,取得hash值
htistory模式与hash模式 ?
Vue-router基本使用
1.引入相关库文件
2.添加路由链接
<router-link to="/user">user</router-link>
<router-link to="/register">register</router-link>
router-link默认被渲染为a标签,可以使用tag属性渲染为其他标签。
history模式下,如果要禁用前进后退,在router-link中加一个replace属性即可
<router-link to="home" replace>首页</router-link>
当router-link对应路由匹配成功时,会给元素设置加上一个router-link-active的class,设置active-class属性可以修改类默认的名称,也可以在路由里写linkActiveClass:'name',
如果想用代码实现路由
this.$router.push('/')
this.$router.replace('/')
to属性被渲染为href,to后的值会被渲染为#开头的hash值
3.添加路由填充位(路由占位符)
<router-view></router-view>
通过路由规则匹配到的组件,将会被渲染到占位符所在位置
4.定义路由组件(2中to对应的)
5.配置路由规则并创建路由实例
var router = new VueRouter({
rou tes:[
{path:"/user",component:user},
{path:"/register",component:register}
]
});
const vm = new Vue({
el:"#app",
router,
});
在项目中使用:
1.导入路由依赖并且使用Vue.use(VueRouter)
2.创建对象引入映射规则
3.在组件中挂载实例
router是大对象
route当前活跃路由
路由重定向
比起直接写component,可以修改hash值
不会出现hash为空却渲染了组件的问题。
routes:[
{path:"/",redirect:"/user"},
{path:"/user",component:user},
{path:"/register",component:register}
]
嵌套路由
父组件中路由模板+通过children属性配置子级路由
<template id="register">
<div>
<h1>register</h1>
<router-link to="/register/tab1">tab1</router-link>
<router-link to="/register/tab2">tab2</router-link>
<router-view></router-view>
</div>
</template>
var router = new VueRouter({
routes:[
{path:"/",redirect:"/user"},
{path:"/user",component:user},
{
path:"/register",
component:register,
children:[
{path:"tab1",component:tab1}, //子路由不需要/
{path:"tab2",component:tab2}
]
},
]
});
路由组件传递参数
1.props布尔值
let r = new VueRouter({
routes: [
{path:"/",redirect:"/user"},
{path: "/user/:id", component: user ,props:true}
]
});
const user = {
template: "#user",
props:["id"]
};
2.this.$route.params.name
router-index.js
[
{
path: '/user/:userId',
component: User
}
]
user.vue
<h1>{{this.$route.params.userId}}</h1>
把router-link用其他元素实现,通过绑定方法
userclick(){
this.$router.push('/user/'+this.userid)
}
profileclick(){
this.$router.push({
path: '/profile',
query: {
name: abc
}
})
}
3.query
Home组件:
<router-link :to="{path:'/profile',query:{name:'abc',age:20}}">档案</router-link>
Profile组件:
<h2>{{this.$route.query}}</h2>
路由懒加载
const Home = ()=>import('../components/Home')
{
path:'/home',
component: Home
}
命名路由
<div id="app">
<router-link :to="{name:'user',params:{id:1}}">user1</router-link>
<router-link to="/user/2">user2</router-link>
<router-link to="/user/3">user3</router-link>
<router-link to="/register">register</router-link>
<router-view></router-view>
</div>
let r = new VueRouter({
routes: [
{path:"/",redirect:"/user"},
{path: "/user/:id",name:"user",component: user },
{path: "/register", component: register }
]
});
页面导航两种方式
1.声明式导航:点击链接实现导航 如:a,router-link标签
2.编程式导航: js形式API实现,如:location.href
this.$router.push("/")//导航
this.$router.go(n)//n>0前进
<template id="user">
<div>
<p>user----{{$route.params.id}}</p>
<button @click = "toRegister">register</button>
</div>
</template>
const user = {
template: "#user",
methods:{
toRegister:function(){
this.$router.push("/register");
}
}
};
导航守卫
meta :元数据,描述数据的数据
给路由加meta->tltle
router.beforeEach((to,from,next)=>{
document.title = to.matched[0].meta,title;
next();
})
前置钩子,需要调用next()
后置钩子不需要
路由独享的守卫
routes:[{
path:'/home',
component: Home,
beforEach: (to,from,next)=>{
}
}]
组件守卫
keep-alive
是Vur内置的组件,可以使被包含的组件保留状态,或避免重新被渲染。
页面切换时实际上组件是反复创建销毁的。
<keep-alive>
<router-view/>
<keep-alive/>
当组件在 内被切换,它的 activated (被 keep-alive 缓存的组件激活时调用。)和 deactivated (被 keep-alive 缓存的组件停用时调用。)这两个生命周期钩子函数将会被对应执行。
保存路径,
beforeRouteLeave
储存当时的路径,activated中压回去
keep-alive 两个属性
include
exclude
路径起别名
在build-webpack.base.conf.js中
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),
'assets': resolve('src/assets')//别名
}
},
import里使用时直接使用
src中使用需要在前面加上~
路由练习:封装一个tabbar组件