vue-router
- 路由的简介
- SPA
- 路由
- 路由的基本使用
- 安装
- 引入
- 使用
- 标签式
- 编程式
- 注意
- 嵌套(多级)路由
- 路由传参
- query参数
- params参数
- 命名路由
- 路由的props配置
- router-link的replace属性
- 编程式路由导航
- 路由跳转
- 后退和前进
- 缓存路由组件
- 两个新的生命周期钩子函数
- 路由守卫
- 全局前置守卫
- 全局后置守卫
- 独享路由守卫
- 组件内路由守卫
- history模式和hash模式
- element-ui基本使用
路由的简介
vue-router的一个插件库,专门用来实现SPA应用
SPA
SPA(single page web application)单页面web应用
SPA整个应用只有一个完整的页面
SPA点击页面中的导航链接不会刷新页面,只会做页面的局部更新,数据需要通过ajax请求获取
![(https://img-blog.csdnimg.cn/direct/626d4f7fe214443788b2aa6681181eea.gif)
路由
一个路由就是一组映射关系(key-value)
key为路径,value可能是function或component
有前端路由也有后端路由:前端路由-key对应组件;后端路由-key对应函数
观察下面动图,前面点击文档和API时页面并没有刷新且页面头部并没有变化,只是路径和页面下部发生了变化,而点击“演练场”时直接跳转到另一个页面了
路由的基本使用
安装
注意:目前vue-router最新版本是4,只支持vue3;当前使用的是vue2所以要下2版本的
npm i vue-router@3
引入
//main.js
import VueRouter from "vue-router";
//...
Vue.use(VueRouter);
引入完成后,我们就可以在创建Vue中传入router配置项
首先创建router文件
配置上了两个路由
About和Home是两个路由组件
// router/index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
import Vue from "vue";// 引入组件
import About from "../components/About";
import Home from "../components/Home";Vue.use(VueRouter);// 创建并暴露一个路由器
export default new VueRouter({// 配置路由routes: [{path: "/about",component: About,},{path: "/home",component: Home,},],
});
然后在vue实例中配置(感觉和vuex一样一样的)
new Vue({render: (h) => h(App), //将App组件放入容器中// ...router,//...
}).$mount("#app"); //绑定模板
看浏览器中路径,有个#
说明配置成功了
使用
标签式
在组件中使用<router-link>
标签,其实解析后就是<a>
标签
to是跳转路由path,activeClass是激活状态class
<div class="row"><router-link to="/about" active-class="active">About</router-link><router-link to="/home" active-class="active">Home</router-link>
</div>
而组件展示的位置用<router-view>
<!-- 指定组件呈现位置 -->
<router-view></router-view>
运行结果
编程式
还有一种编程式路由之后讲
注意
- 上面的Home和About是路由组件
而之前使用的是一般组件,用<>标签引用
所以为了区分这两个组件,一般要在components平级创建一个pages文件夹存放路由组件
- 当一个路由组件不需要显示时,会直接将组件销毁,需要显示时再次挂载
- 我们将路由组件输出,可以看到多出来两个东西
$route
是每个路由组件都有的专属属性,存储着自己的路由信息
$router
是整个应用的路由器,只有一个,来管理路由
嵌套(多级)路由
路由套路由
如下在Home下再添加两个路由
注意:子路由的path不要写成"/home/news"
或者"/news"
router会给拼好的
// 创建并暴露一个路由器
export default new VueRouter({// 配置路由// 一级路由routes: [{path: "/about",component: About,},{path: "/home",component: Home,// 二级路由children: [{path: "news",component: News,},{path: "message",component: Message,},],},],
});
使用时to要写全<router-link to="/home/news" active-class="active">Home/News</router-link>
路由传参
query参数
传递参数,两种写法
<!-- 跳转路由并携带query参数,to的字符串写法 -->
<router-link :to="`/home?id=${id}i&name=${name}`" active-class="active">Home</router-link>
<!-- 跳转路由并携带query参数,to的对象写法 -->
<router-link:to="{path: '/home',query: {id,name,},}"active-class="active">Home</router-link
>
接收参数
<h2>我是Home内容:Hello {{ $route.query.name }}</h2>
params参数
配置路由的地方也要修改,要写上需要传的参数
{path: "/home/:id/:name", //使用占位符声明接收params参数// path: "/home",component: Home,// ...
},
<!-- 跳转路由并携带params参数,to的字符串写法 -->
<router-link :to="`/home/${id}/${name}`" active-class="active">Home</router-link
>
对象写法需要注意的是必须要用name指定路由,不可以用路径path(是一个坑)
<router-link:to="{name: 'home',params: {id,name,},}">Home</router-link
>
接收参数
<h2>我是Home内容:Hello {{ $route.params.name }}</h2>
命名路由
就是在路由配置项中添加个name
//...
{name: "detail",path: "/detail",component: Detail,
},
//...
作用就是可以简化路由跳转编码
<router-link to="/home/news/detail" active-class="active">Detail</router-link
>
<!-- 简化为↓ -->
<router-link :to="{ name: 'detail' }" active-class="active">Detail</router-link
>
路由的props配置
接收路由参数展示时<h2>我是Home内容:Hello {{ $route.params.name }}</h2>
会不会觉的获取的比较繁琐
这里就要使用props了
需要先在路由上配置
{name: "home",path: "/home/:id/:name", //传递params参数// path: "/home",component: Home,// props的第一种写法,值为对象,对对象中的所有key-value都会以props的形式传给对应的组件// props: { a: 1, b: 333 }, // 但是不推荐,因为只能写死数据// props的第二种写法,值为布尔,若为真就会把该路由组件收到的所有params参数,以props的形式传给Detail组件// props: true, //只能与params配合使用// props的第三种写法,值为函数props($router) {return { id: $router.query.id, name: $router.query.name };},// 或者用结构赋值简写// props({query:{id,name}}) {// return { id,name };// },//...
}
在组件上用props接收使用(就是父组件传参那样)
props: ["id", "name"],
<h2>我是Home内容:Hello {{ name }}</h2>
router-link的replace属性
每一次点击router-link默认都会将历史记录push到一个栈中,指针指向当前展示的页面
每次点击浏览器的后退键,就会让指针指向上一个记录页面也会变成上一个记录的样式
而可以通过配置将push模式改为replace模式
即每次跳转都会覆盖前一个历史记录
在router-link加个replace属性就可以了
<router-link replace to="/about" active-class="active">About</router-link>
编程式路由导航
路由跳转
<button @click="toHome">点击跳转Home组件</button>
toHome() {this.$router.push({name: "home",params: {id: this.id,name: this.name,},});
},
当然也能用replace,push改为replace就行
后退和前进
back() {// 后退// this.$router.back();// 后退多步this.$router.go(-2);
},
forward() {// 前进this.$router.forward();// 前进多步// this.$router.go(2);
},
缓存路由组件
之前知识点:路由组件不显示默认是会销毁掉,再次显示时再重新挂载
但有时我们需要对页面上的数据进行缓存
就可以用<keep-alive>
标签包裹路由组件显示位置,可以添加include来配置想缓存的组件名称(这里注意要记得在组件里配置name)
如下代码就是要将Home组件内容进行缓存,而About不进行缓存
<keep-alive include="Home"><!-- 指定组件呈现位置 --><router-view></router-view>
</keep-alive>
效果如下
缓存多个组件,应该猜到了
<keep-alive :include="['Home','About']">
两个新的生命周期钩子函数
想象一个场景(懒得写实例了)
两个路由组件可以来回切换,且都为缓存路由组件,
第一个组件上在mounted设置了一个定时器setInterval实现透明渐变效果,并在beforeDestory里销毁的定时器clearInterval
从第一个路由组件切换到第二个路由组件后,会发现定时器并没有被销毁,一直在执行,是因为组件并没有被销毁,这并不是我们想得到的
咋整?
引出两个路由组件独有的生命周期钩子激活:activated
和失活:deactivated
(就是onShow和onHide)
tips:之前声明周期图中有三个钩子函数没有写在上面,激活和失活,还有一个就是nextTick
路由守卫
就是切换路由组件时进行操作
需要再touter/index.js中配置
全局前置守卫
当需要在跳转前检查权限等操作,无权限则不跳转,就需要用到前置路由守卫
首先不能先直接暴露,要在最后暴露
通过beforeEach钩子函数来控制放行,next
是用来放行,不写就不会跳转
//...
const router = new VueRouter({
//...
})
// 全局前置路由守卫 初始化以及每次路由切换前调用
// to-前往的路由信息 from-来自的路由信息 next-放行
router.beforeEach((to, from, next) => {console.log("to:", to);console.log("from:", from);next();
});export default router;
就可以在beforeEach中根据条件和目的信息等来判断是否放行
还有个问题是当我们需要检查权限的页面很多时,那判断语句就会很长,
优化方法是使用路由中的一个配置项:meta
元信息-用于添加一些自定义的数据
{name: "about",path: "/about",component: About,meta: {isAuth: true,},
},
这样在beforeEach中判断,直接用if (to.meta.isAuth){//权限判断}
全局后置守卫
当我们需要再路由正确切换后再进行一些操作时,就用后置路由守卫
比如修改页面标题首先要在每个需要配置的路由的meta中添加title属性
{name: "about",path: "/about",component: About,meta: {isAuth: true,title: "关于",},
},
在后置路由守卫中修改title
// 全局后置路由守卫 初始化以及每次路由切换后调用
// to-前往的路由信息 from-来自的路由信息
router.afterEach((to, from) => {document.title = to.meta.title || "我的页面";
});
有可能会遇到切换路由时,页面标题闪现数项目名称,是因为在index.html中我们配置的title就是项目名称,改为默认名称就可以了
<!--index.html-->
<!-- <title><%= htmlWebpackPlugin.options.title %></title> -->
<title>我的页面</title>
独享路由守卫
只对某一个路由进行操作
{name: "about",path: "/about",component: About,meta: {isAuth: true,title: "关于",},// 独享路由守卫 当跳转进入当前路由之前调用beforeEnter: (to, from, next) => {// ...}
},
没有afterEnter
组件内路由守卫
在对应路由组件中配置的
// About.vue
// 进入守卫 通过路由规则,进入该组件时被调用
beforeRouteEnter(to, from, next) {// ...
},
// 离开守卫 通过路由规则,离开该组件时被调用
beforeRouteLeave(to, from, next) {// ...
},
history模式和hash模式
路由有两种工作模式:history模式和hash模式
默认是hash模式
可以通过mode来修改模式
const router = new VueRouter({// 配置路由mode: "history",//...
})
两者区别就是
hash模式
url中#及其后面的内容是hash值,hash值不会包含在http请求中,即:hash值不会带给服务器
优缺点:
- 地址汇总永远带着#号,不美观
- 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
- 兼容性好
history模式
优缺点:
- 地址干净,美观
- 兼容性和hash模式相比略差
- 应用部署上线时需要后端人员支持,解决刷新页面服务端404问题
element-ui基本使用
移动端常用UI组件库:
- Vant
- Cube UI
- Mint UI
PC端常用UI组件库
- Element UI
- IView UI
当使用Element-UI时,按照官网写完整引入,会将所有的组件及样式都引入进来以方便直接使用,就会导致最后包体很大
所以需要按需引入,官网下面就有,看去吧
需要注意的几点:
- .babelrc文件就是babel.config.js
- 原始的配置不要删掉,要追加
- 报错
Plugin/Preset files are not allowed to ...
,["es2015", { "modules": false }]
应该改为["@babel/preset-env", { "modules": false }]