10.1 Vuex
10.1.1 什么是vuex
Vuex
是一个专门为Vue
应用程序设计的状态管理库。在Vue
应用程序中,通常会有多个组件共享同一个状态,而Vuex
可以帮助你管理这些状态,并且使得状态的管理变得更加简单、高效。
Vuex
采用了集中式存储管理的方式,将应用程序的状态存储在一个全局的存储器中。这个存储器可以被所有组件访问,并且提供了一些用于操作状态的API
。通过这些API
,我们可以对状态进行读取、修改、监听等操作。
在Vuex
中,状态是响应式的,也就是说,当状态发生变化时,所有依赖于这个状态的组件都会自动更新。因此,Vuex
可以很好地帮助我们实现组件之间的通信和协作。
10.1.2 vuex的属性
Vuex
是一个状态管理库,它为Vue
应用程序提供了集中式存储管理。Vuex
的核心是store
对象,store
对象包含着应用程序的状态和状态变更的方法。
store
对象具有以下属性:
state
:存储状态数据的对象,类似于组件中的data
属性。state
的属性值可以通过store.state.xxx
访问。getters
:类似于计算属性,从store
的state
中派生出一些状态,供组件使用。getters
的属性值可以通过store.getters.xxx
访问。mutations
:修改 state 中数据的方法,不支持异步操作。mutations
的属性值可以通过store.commit('mutationName', payload)
触发。actions
:类似于mutations
,但支持异步操作,通过提交mutations
来修改state
。actions
的属性值可以通过store.dispatch('actionName', payload)
触发。modules
:允许将store
拆分成模块化的代码结构,每个模块拥有自己的state
、mutations
、getters
、actions
。每个模块可以通过命名空间来隔离自己的状态和操作。
除了上述属性,还有一些辅助属性和方法,如:
strict
:用于开启严格模式,禁止直接修改state
。启用严格模式后,只能通过mutations
来修改state
。replaceState
:用于替换store
中的state
。subscribe
:用于订阅store
中的mutation
。当mutation
被触发时,订阅函数会被调用。watch
:用于监听store
中的state
或getters
的变化。当监听的值发生变化时,回调函数会被调用。
Vuex
的属性提供了一种集中式的状态管理方式,能够方便地管理应用程序的状态,提高开发效率。
10.1.3 如何安装并使用vuex
安装Vuex
的步骤如下:
- 在项目中安装
Vuex
:npm install vuex --save
- 在
Vue
应用程序中引入Vuex
:import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)
- 创建一个
Vuex
的store
对象:const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++ } }, actions: { increment(context) { context.commit('increment') } }, getters: { doubleCount(state) { return state.count * 2 } } })
以上代码创建了一个简单的
Vuex store
对象,其中包含了一个state
对象、一个mutation
和一个action
方法以及一个getter
方法。
- 将
store
对象注入到Vue
应用程序中:new Vue({ el: '#app', store, // ... 其他选项 })
现在,
Vuex
已经成功安装并配置完成。您可以在Vue
应用程序中通过以下方式使用Vuex
:
- 通过
this.$store.state.xxx
访问state
中的数据;- 通过
this.$store.commit('mutationName', payload)
触发mutation
;- 通过
this.$store.dispatch('actionName', payload)
触发action
;- 通过
this.$store.getters.xxx
访问getter
中的数据。例如,在
Vue
组件中使用Vuex
:<template> <div> <p>Count: {{ count }}</p> <p>Double Count: {{ doubleCount }}</p> <button @click="incrementCount">Increment</button> </div> </template> <script> export default { computed: { count() { return this.$store.state.count }, doubleCount() { return this.$store.getters.doubleCount } }, methods: { incrementCount() { this.$store.dispatch('increment') } } } </script>
以上示例代码展示了如何在 Vue 组件中访问 Vuex 中的数据和方法。
10.2 路由(router)
10.2.1 什么是路由
在Vue.js
中,路由(router)是用于构建单页应用程序的核心功能之一,它通过管理应用程序中的不同URL
地址来使用户界面变得动态和交互性。Vue
路由可以帮助您构建具有多个页面的单页应用程序,并且可以使用浏览器的前进和后退按钮来更改URL
路径而不刷新页面。
Vue
路由是通过Vue Router
插件来实现的。Vue Router
是一个官方支持的插件,它提供了一组API
来定义路由、配置路由参数以及导航路由等功能。
10.2.2 Vue Router的基本使用
Vue Router
的基本使用步骤:
- 安装
Vue Router
:可以使用npm
或yarn
等包管理器来安装Vue Router
。例如,使用
npm
安装:npm install vue-router --save
- 定义路由:在定义路由时,您需要创建一个
Vue Router
实例并定义应用程序的不同页面和相应的URL
路径。例如:
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: About } ] const router = new VueRouter({ routes }) export default router
在这个例子中,我们定义了两个路由,一个是首页(
/
),另一个是关于页面(/about
)。每个路由都有一个name
和一个component
,name
用于在导航中标识路由,component
是与该路由对应的组件。
- 挂载路由:接下来,需要将路由实例挂载到
Vue
实例中。例如:
import Vue from 'vue' import App from './App.vue' import router from './router' new Vue({ el: '#app', router, render: h => h(App) })
在这个例子中,我们将路由实例
router
传递给Vue
实例的router
选项,使Vue
能够使用它来管理页面和导航。
- 使用路由:可以在组件中使用路由
例如使用
router-link
组件来创建导航链接:<router-link to="/">Home</router-link> <router-link to="/about">About</router-link>
或者使用编程式导航来实现在组件之间进行导航:
// 通过 $router.push() 进行编程式导航 this.$router.push('/')
通过这些基本的步骤,可以使用
Vue Router
来实现单页应用程序的路由功能,并创建动态和交互式的用户界面。
10.2.3 参数和属性
Vue Router
在定义路由时支持多个参数和属性,下面是一些常用的参数和属性:
path
:指定路由的 URL 路径。name
:用于在导航中标识路由的名称。component
:指定与该路由对应的组件。redirect
:重定向路由。alias
:为路由设置别名。meta
:用于存储路由的元信息,例如页面标题、是否需要鉴权等。children
:定义嵌套的子路由。
下面是一个示例代码,演示了如何使用这些参数和属性来定义路由:
const routes = [
{
path: '/',
name: 'home',
component: Home,
meta: {
title: '首页'
}
},
{
path: '/about',
name: 'about',
component: About,
meta: {
title: '关于我们'
}
},
{
path: '/user/:id',
name: 'user',
component: User,
props: true
},
{
path: '/dashboard',
name: 'dashboard',
component: Dashboard,
meta: {
requiresAuth: true
}
},
{
path: '/redirect',
redirect: '/'
},
{
path: '/alias',
component: Alias,
alias: '/alias-page'
},
{
path: '/parent',
component: Parent,
children: [
{
path: 'child',
component: Child
}
]
}
]
在上面的代码中,我们定义了多个路由,其中:
/
路由指定了路由名称、组件和元信息;/about
路由指定了路由名称、组件和元信息;/user/:id
路由使用了动态路由参数:id
并且启用了路由参数传递到组件中;/dashboard
路由指定了需要进行鉴权,即需要登录才能访问的元信息;/redirect
路由指定了重定向到根路由/
;/alias
路由使用了别名/alias-page
;/parent
路由定义了嵌套的子路由/parent/child
。
这些参数和属性可以让您定义更加灵活和复杂的路由,从而实现更加丰富的单页应用程序。
10.2.4 参数传递
在Vue Router
中,有三种主要的参数传递方式:query
、params
和props
。
- Query 参数
query
参数是一种将数据添加到URL
中的方式,以?key=value
的形式添加到 URL 的末尾。query
参数可以通过$route.query
访问,在组件中使用时,可以通过$route
对象来访问,例如:<template> <div> <p>ID: {{ $route.query.id }}</p> </div> </template>
- Params 参数
params
参数是一种将数据添加到 URL 路径中的方式,以/key/value
的形式添加到 URL 的末尾。params
参数可以通过$route.params
访问,在组件中使用时,可以通过$route
对象来访问,例如:<template> <div> <p>ID: {{ $route.params.id }}</p> </div> </template>
注意,要在路由定义中使用
params
参数,需要在路由路径中使用冒号:
来标识参数名,例如:const routes = [ { path: '/user/:id', name: 'User', component: User } ]
- Props 参数
props
参数是一种将数据从父组件传递到子组件的方式。在路由定义中,可以使用props
参数来将$route
对象中的数据传递给组件的props
属性;使用
props
的方式有两种:
- 布尔模式:设置为
true
,该路由组件会将路由参数作为属性传递给组件,例如:const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, props: true } ] })
在这种情况下,当你访问
/user/123
时,User
组件会接收到一个props
对象,其中包含了id
属性,即{ id: 123 }
。
- 对象模式:在
props
中指定具体的属性和值,例如:const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, props: { default: true, color: 'red' } } ] })
在这种情况下,当你访问
/user/123
时,User
组件会接收到一个props
对象,其中包含了id
属性和color
属性,即{ id: 123, color: 'red' }
。
10.2.5 路由守卫
Vue
路由守卫是指在Vue Router
路由切换过程中执行的一系列钩子函数,用于控制路由跳转、执行异步操作、检查用户权限等等。
Vue Router
提供了全局守卫和路由独享守卫两种类型的路由守卫:
全局守卫:应用于整个应用程序的路由切换过程,可以用来控制所有路由跳转。全局守卫包括:
beforeEach(to, from, next)
:在路由切换之前执行,可以用来检查用户权限、执行异步操作等。如果需要进入下一个路由,则需要调用next()
方法,否则可以传递一个参数,如next(false)
,阻止路由跳转。afterEach(to, from)
:在路由切换之后执行,可以用来记录路由历史、统计页面访问量等。beforeResolve(to, from, next)
:在所有异步路由组件被解析之后执行,可以用来确保异步组件已经被加载并准备好渲染。路由独享守卫:只应用于某个具体的路由或路由组件。路由独享守卫包括:
beforeEnter(to, from, next)
:在某个路由被匹配到之前执行,可以用来检查用户权限、执行异步操作等。如果需要进入该路由,则需要调用next()
方法,否则可以传递一个参数,如next(false)
,阻止路由跳转。- 组件内的守卫:在组件内部通过
beforeRouteEnter
、beforeRouteUpdate
和beforeRouteLeave
来定义。这些钩子函数可以用来控制组件内部的路由跳转、执行异步操作等。需要注意的是,路由守卫是通过链式调用来实现的,如果其中一个守卫阻止了路由跳转,则后面的守卫将不再执行。另外,路由守卫可以通过
next()
方法传递一个路径对象,实现路由跳转到其他路径。
Vue Router
允许在组件内部使用路由守卫来控制组件的路由跳转、执行异步操作等。组件内路由守卫包括:
beforeRouteEnter(to, from, next)
:在组件路由被激活之前执行,此时组件实例还未被创建,因此无法通过this
访问组件实例。可以通过next(vm => {})
传递一个回调函数,在组件实例创建之后执行一些逻辑,如获取组件数据。beforeRouteUpdate(to, from, next)
:在组件路由更新时执行,可以用来检查路由参数的变化,执行一些异步操作等。beforeRouteLeave(to, from, next)
:在组件路由被离开时执行,可以用来询问用户是否要保存未保存的数据、执行一些清理操作等。
这些组件内路由守卫可以在组件的生命周期钩子函数中定义,如下所示:
export default {
beforeRouteEnter(to, from, next) {
// 在组件实例创建之前执行
next(vm => {
// 在组件实例创建之后执行
})
},
beforeRouteUpdate(to, from, next) {
// 在组件路由更新时执行
next()
},
beforeRouteLeave(to, from, next) {
// 在组件路由被离开时执行
next()
}
}
需要注意的是,组件内路由守卫只在路由跳转到该组件时才会执行,如果是通过该组件内部的代码调用router.push()
、router.replace()
等方法进行路由跳转,则不会触发组件内的路由守卫。
10.3 两个新的生命周期钩子
activated
和deactivated
是Vue 2.0
新增的生命周期钩子函数,用于组件被激活和失活时的处理。
当组件被切换为激活状态时(例如从一个包含该组件的父组件切换到另一个父组件),activated
钩子函数会被调用。这可以让开发者在组件激活时执行一些逻辑,比如向后端发送请求获取数据。
当组件被切换为非激活状态时(例如从该组件所在的父组件切换到其他页面),deactivated
钩子函数会被调用。这可以让开发者在组件失活时执行一些清理逻辑,比如取消当前组件的一些请求或动画效果。
需要注意的是,activated
和deactivated
钩子函数只在使用<keep-alive>
包裹的组件中才会生效。这是因为<keep-alive>
可以让Vue
在组件切换时将组件实例缓存下来,以便下次快速恢复组件状态,而activated
和deactivated
钩子函数就是用来处理组件被缓存和恢复时的逻辑。