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
```javascript
import 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地址一致,就会默认展示这个子路由
```javascript
import 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 表示从哪来
- 统计用户访问某个页面的次数(数据采集)