SPA(Single Page Application):单页面富应用
- 单页面应用: 所有功能在一个页面上实现=》组件组成,完成开发=》组件化开发
前端路由:专门为SPA提供页面(组件 .vue文件)的跳转支持
单页面-多页面对比
| 对比部分 | 单页应用(最流行) | 多页面应用(传统方式) |
|---|---|---|
| 页面组成 | 一个html文件多个组件组成 | 多个html文件 |
| 静态资源共用 | 共用,一次性加载完毕,借助ssr优化 | 不共用,每个页面都加载一遍 |
| 刷新方式 | 页面局部刷新 | 整页加载 |
| url模式 | itcast.com/#/pageone | itcast.com/pageone.html |
| 用户体验 | 用户体验良好 | 页面切换加载缓慢体验较差 |
| 数据传递 | 容易 | 依赖url传参,cookie,localStorage |
| 搜索引擎优化 | 不利于seo优化,需要ssr优化 | 支持良好 |
| 使用场景 | 追求高体验 不要求seo | 高度要求seo |
| 开发成本 | 较高 需要依赖专业的框架, 开发效率高 | 较低 重复代码多, 开发效率低 |
说明:ssr(server side render)指服务端渲染
优点:
- 整体不刷新页面,用户体验更好
- 组件化,数据传递容易, 开发效率高
缺点:
- 一定的学习成本
- 首次加载会比较慢一点
- 不利于seo搜索引擎优化
总结: 单页面应用, 用户体验好, 开发效率高
工作原理
前端路由的本质, 对url的hash值进行改变和监听,切换对应页面组件的dom结构
- 前端路由 : 是浏览器 URL 中的哈希值( # hash) 与 展示视图内容(组件) 之间的对应规则
- 为什么要学习路由:
- SPA渐进式 =>vue => vuer-router (管理组件之间的跳转)
- 提升网页显示的速度, 提高网站的性能
- vue 中的路由 : 是 hash 和 component 的对应关系, 一个哈希值对应一个组件页面
路由的使用
安装
如果使用vue-cli创建项目,没有选择路由插件,需要单独安装和写下边初始化代码npm i vue-router
- 导入路由
import VueRouter from 'vue-router'
配置路由
router/index.js中的配置
- 框架注册
- 在vue中,使用vue的插件,都需要调用Vue.use()
- 在
router/index.js中注册之后才能使用 Vue.use(VueRouter)
- 创建路由规则数组
const routes = []- 在
router/index.js中创建一个routes数组 - 实际开发在这里配置跳转规则
- 创建路由对象
const router = new VueRouter({routes
})
导出路由实例
导入路由实例
**import**router**from**'./router/index.js'index.js可以省略
- 挂载实例到vue组件
- 在
new Vue({router})内写router - 挂载之后给vue组件提供了方法:
$router和$route方法 - $router 用方法 $route 用数据 ```javascript import Vue from ‘vue’ import VueRouter from ‘vue-router’
- 在
// 框架注册 Vue.use(VueRouter) // 创建路由数组 const routes = [ ] // 创建路由对象 const router = new VueRouter({ routes }) // 导出路由实例 export default router
```javascriptimport Vue from 'vue'import App from './App.vue'// 导入实例import router from './router'Vue.config.productionTip = false// 挂载实例new Vue({router,render: h => h(App)}).$mount('#app')
规则
语法:{path:'/地址名', component:页面的组件对象}
- 默认显示某个页面,只需要把该页面的path值改成
'/' - path内是访问页面需要的地址一般写
/名字 -
导入写法
语法:
@/文件夹/文件 -
页面中使用
router-view
语法:
<router-view /> 路由提供的占位组件
- 路由的path地址对应的component渲染的组件占位
-
router-link
最终生成的是一个a标签,所以控制样式时写
a- to属性
- 语法:
<router-link to="path值"> 首页 </ router-link> - 使用router-link组件跳转页面,配合to属性
```vue
- 语法:
<a name="OOKXy"></a>### 跳转传参- query传参- 语法:`地址?key=val&key=val` key=val (键值对)- 在to属性的值后面写`?键值对`多个键值对使用`&`连接- 通过`this.$route.query`接收传参- params传参- 语法:`path:'地址/:参数名1/:参数名2'`在path路径写`/:参数名``:参数名`定义的是接收时候的属性名- 动态路由跳转时,在to属性的值把`:参数名`替换成参数值- 通过`this.$route.params`接收传参```vue<template><div id="app"><nav class="box"><router-link to="/home?a=1&b=2">首页</router-link><router-link to="/new">新闻页</router-link><router-link to="/login">登录页</router-link><router-link to="/news/123">新闻1</router-link></nav><router-view /></div></template><style lang="less" scoped>.box {a {display: inline-block;margin: 15px;}}</style>
created () {console.log(this.$route.params.id)console.log(this.$route.query)}
import Vue from 'vue'import VueRouter from 'vue-router'import Home from '../views/home.vue'import Login from '../views/login.vue'import New from '../views/new.vue'import News from '../views/index.vue'// 框架注册Vue.use(VueRouter)// 创建路由数组const routes = [{ path: '/home', component: Home },{ path: '/login', component: Login },{ path: '/new', component: New },{ path: '/news/:id', component: News }]// 创建路由对象const router = new VueRouter({routes})// 导出路由实例export default router
路由重定向
语法:path: '重定向地址', redirect: '页面地址'
用户什么也没有输入,默认显示某个页面可以通过redisrect:'页面地址'重新定向
在router/index.js - 修改配置
const routes = [{ path: '/', redirect: '/home' },{ path: '/home', component: Home }]
404页面配置
语法:path: '*', component: NotFound
当所有的路由都不匹配,匹配这个通配符,显示NotFound页面
const routes = [{ path: '*', component: NotFond }]
$route其他方法
$route.path可以获取到path地址,用做菜单显示判断$route.matched[0].path获取404的path*用做菜单显示判断v-if="$route.path !== '/login' &&$route.matched[0].path !== '*'"
路由模式
实例化时候的mode属性
- hash是默认值 (哈希模式)
- history (h5的history模式)
- 功能一样(跳转页面)
- 区别
- 哈希有# history没有#
- hash模式兼容性更好
// 创建路由对象const router = new VueRouter({routes,// mode: 'history'mode: 'hash'})
编程式导航
用js方法跳转路由就是编程式导航
跳转方法
- 通过
$router.push()跳转- 语法:
$router.push('/地址' || {path:'/地址'})- js中需要加
this.调用,模板中不需要
- js中需要加
- 语法:
- 通过
$router.replace('/地址')跳转- 语法:
$router.replace('/地址' || {path:'/地址'})
- 语法:
-
push和replace总结
两个方法的使用完全一样
- 区别
- push方法跳转,新增一条跳转记录
- replace方法跳转,替换当前的记录进行跳转,不能返回上次跳转的页面(push可以),可以返回上上次
```vue
<a name="TDbmx"></a>#### 传参- query传参(静态路由)- 传参写法- `$router.push('/地址?key=val')`- `$router.push({path:'/地址?key=val'})`- `$router.push({path:'/地址', query:{key:val}})`- 接收- `this.$route.query`- params传参(动态路由)- 写法- 在path路径写`/:参数名``:参数名`定义的是接收时候的属性名- `this.$router.push({path:'/地址/参数值1/值2'})`- 接收- `this.$route.query.参数名`<a name="hpZix"></a>### 路由嵌套语法:在父路由内写`children:[{子路由}]`- 子路由 = `path:'/父地址/地址',component:组件名`- path值必须带上父路由地址- 嵌套的路由也需要在父页面写一个挂载`<router-view/>`- 如果和父路由的path地址一致,就会默认展示这个子路由```javascriptimport Vue from 'vue'import VueRouter from 'vue-router'import Home from '../views/home.vue'import About from '../views/about.vue'import New from '../views/new.vue'import News from '../views/index.vue'import NotFond from '@/views/404'import Login from '@/views/login'import Find from '@/views/find'import My from '@/views/myMusic'import Song from '@/views/find/components/song.vue'import Top from '@/views/find/components/top.vue'import Recom from '@/views/find/components/recom.vue'// 框架注册Vue.use(VueRouter)// 创建路由数组const routes = [{ path: '*', component: NotFond },{ path: '/', redirect: '/home' },{ path: '/home', component: Home },{ path: '/about/:name', component: About },{ path: '/new', component: New },{ path: '/news/:id', component: News },{ path: '/login', component: Login },{ path: '/find', component: Find, children: [{ path: '/find', component: Recom }, { path: '/find/top', component: Top }, { path: '/find/song', component: Song }] },{ path: '/my', component: My }]// 创建路由对象const router = new VueRouter({routes,// mode: 'history'mode: 'hash'})// 导出路由实例export default router
<template><div><h1>发现</h1><nav class="nav"><router-link to="/find">推荐</router-link><router-link to="/find/top">榜单</router-link><router-link to="/find/song">歌单</router-link></nav><div class="box"><router-view /></div></div></template><script>export default {}</script><style lang="less" scoped>.nav {a {display: inline-block;margin: 5px;color: skyblue;}}.box {height: 40px;border: 1px solid orange;}</style>
高级用法
全局前置守卫
语法:router.beforeEach((to, from, next) => {})
- 在
router/index.js中配置 - 访问页面之前,执行这个回调函数
三个参数
- to 表示去哪里(访问那个页面)
- from 表示从哪来
- next 是个方法
在
router/index.js中配置- 访问页面之后,执行这个回调函数
- 俩个参数
- to 表示去哪里
- from 表示从哪来
- 统计用户访问某个页面的次数(数据采集)
