我们平时写跳转链接的时候通常都是使用标签,但a标签的跳转相当于从一个页面跳转到另一个页面,这样页面会重新加载,会有Dom性能的损耗。
而Vue-Router也是进行跳转,但他不会跳转到新的页面,不会重新全局的渲染,而是选择路由所指的组件进行局部的渲染,这就是我们所说的前端路由,也是SPA(单页面应用)的路径管理器。我们在将前端发展历程中就说过SPA阶段,vue的spa就是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。
还记得在使用vue-cli创建工程的时候,让我们选择router是否使用history模式吗?我们那时候选择了no。其实router有两种模式,一个是Hash模式,一个是history模式,默认是前者。
hash模式
hash模式使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置。使用hash模式时url的形式是这样的
history模式
由于hash模式会在url中自带#,我们可以用路由的history模式,在router文件夹里的index.js
中增加:
const router = new VueRouter({
routes,
mode:'history'
})
这样就没有#了,而且这种模式充分利用了html5 history interface中新增的pushState()
和replaceState()
方法,可以用于浏览器记录栈。
方式1:直接修改地址栏到对应的页面
方式2:this.$router.push(‘路由的地址’)
方法3:使用
标签和
标签,如下
Home |
About |
Index
link需要一个to属性,指向要跳转的URL,而view则是跳转后组件所渲染到的位置。
进入router
文件夹的index.js
,给routes数组添加路由对象
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path:'/index', //path是跳转的地址
name:'Index', //路由的名称
component: () => import('../views/Index.vue') //引入的组件
}
]
注意,引入组件有两种写法,一种是直接在一开始直接引入,另一种是懒加载的方式,即进行跳转的时候再进行加载,是一种优化的方案。
现实开发中,我们可能会需要将各组件进行嵌套,这里就需要用到子路由了。
首先在components
中新建两个组件H1.vue
和H2.vue
<template>
<div>
<h1>I am H1 pagesh1>
div>
template>
<script>
export default {
}
script>
<style scoped>
style>
然后修改router/index.js的代码,在原有的路由下配置加入children字段
{
path:'/index',
name:'Index',
component: () => import('../views/Index.vue'),
children:[
{
path:'/h1',
name:'H1',
component:()=>import('../components/H1.vue')
},
{
path:'/h2',
name:'H2',
component:()=>import('../components/H2.vue')
}
]
}
然后在主页面加入router-view
标签,给子模版提供插入的位置
<template>
<div>
<h2>{
{msg}}h2>
<router-view>router-view>
div>
template>
最后用
标签增加两个新的导航链接
<router-link to="/index">Indexrouter-link> |
<router-link to="/h1">H1router-link> |
<router-link to="/h2">H2router-link>
这样就实现了在主页面中嵌套子模版的功能,同样的子模版还能继续往下嵌套
$route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数。
$route.path
–当前路由的路径$route.params
–当前路由的参数对象,以键值对的方式存储$route.query
–URL的查询参数,也是键值对的方式存储$route.path
$route.hash
–当前路由的hash值$route.fullPath
–完成解析后的 URL,包含查询参数和 hash 的完整路径。$route.match
–数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。$route.name
–当前路径的名字**$router **是“路由实例”对象,即使用 new VueRouter创建的实例,包括了路由的跳转方法,钩子函数等。以下是他的常用方法
$router.go(-1)
–跳转到上一次浏览的页面
$router.replace('/index')
–指定跳转的地址
$router.push('/index')
–通过push进行跳转
其中push和replace都是跳转,push会向history栈添加一个新的记录,当我们点击浏览器的返回按钮时可以看到之前的页面。
而replace则不会向history添加新记录,而是直接替换当前记录,因此也不能返回。
这里引用官网的解释
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
什么是状态管理?你可以把它想象成是一个全局对象,当两个页面需要对同一个变量进行操控时,我们就需要用到它。而且,贯彻落实响应式的思想,vuex也是响应式的,当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么响应组件也会得到高效的更新。
进入store/index.js,我们可以看到如下代码有四个字段:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
从字面意思理解,就是状态。我们可以把state看作是所有组件的data,用于保存所有组件的公共数据,举个例子,现在H1.vue
和H2.vue
都是一个计数器,并且共用一个count
值。
首先在state中定义一个count
state: {
count:0
},
然后在H1和H2将其取出
//H1.vue
data(){
return {
num1: this.$store.state.count
}
},
//H2.vue
data(){
return {
num2: this.$store.state.count
}
},
然后在页面展示,可以看到两个页面都显示为0
Mutations
Mutation是Vuex中改变state的唯一方法,因此mutation里面定义的相当于store的methods,举个栗子,现在我们要对count值进行加减操作。
首先在Mutation定义两个事件,其中state为传入的state对象,payload为改变的值
mutations: {
addCount(state,payload){
state.count+=payload
},
subCount(state,payload){
state.count-=payload
}
},
然后在组件中定义两个按钮并绑定两个方法,在两个方法中分别注册这两个事件
methods:{
add(){
this.$store.commit('addCount',1)
},
sub(){
this.$store.commit('subCount',2)
}
}
点击对应按钮,即可触发mutation中的事件,然后改变state里的值
Actions
Actions与Mutations类似,不同点在于:
actions
提交的是mutations
而不是直接变更状态actions
中可以包含异步操作, mutations
中绝对不允许出现异步actions
中的回调函数的第一个参数是context
, 是一个与store
实例具有相同属性和方法的对象举个栗子,我们现在使用setTimeout来模拟异步操作,延迟2s之星mutations中的事件。
首先在actions定义一个事件:
actions: {
addCountAsync(context,payload){
setTimeout(()=>{
context.commit('addCount',payload)
},2000)
}
在页面注册这个事件
addAsync(){
this.$store.dispatch('addCountAsync',5)
}
点击按钮,2秒后才会加5.
Modules
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象,到时候store对象可能就变得十分臃肿,因此Vuex提供了一个module(模块),每个模块都有自己的state,mutation,action,从而可以是代码变得更加模块化
,使用方法如下:
const moduleA = {
state: {
... },
mutations: {
... },
actions: {
... }
}
const moduleB = {
state: {
... },
mutations: {
... },
actions: {
... }
}
本文主要介绍了vue-router和vuex的基本使用方法,对于开发单页面应用而言,这两者都是非常核心的功能,但如果只是简单的单页面应用,vuex反而使得开发更加繁琐,而如果需要构建中大型单页应用,就可能要考虑如何更好地在组件外部管理状态,因此是否使用还是要看实际的需求。