广水住房和城乡建设部网站,简单网页制作代码html,高港网站开发,六安网站建设招商一、Vuex的状态管理 二、Vuex的安装
我们这里使用的是vuex4.x#xff0c;安装的时候需要添加 next 指定版本#xff1b;
npm install vuexnext三、创建Store
每一个Vuex应用的核心就是store#xff08;仓库#xff09;#xff1a;
store本质上是一个容器#xff0c;它…一、Vuex的状态管理 二、Vuex的安装
我们这里使用的是vuex4.x安装的时候需要添加 next 指定版本
npm install vuexnext三、创建Store
每一个Vuex应用的核心就是store仓库
store本质上是一个容器它包含着你的应用中大部分的状态state
Vuex和单纯的全局对象有什么区别呢 第一Vuex的状态存储是响应式的
当Vue组件从store中读取状态的时候若store中的状态发生变化那么相应的组件也会被更新 第二你不能直接改变store中的状态改变store中的状态的唯一途径就显示提交 (commit) mutation这样使得我们可以方便的跟踪每一个状态的变化从而让我们能够通过一些工具帮助我们更好的管理应用的状态
使用步骤 创建Store对象 在app中通过插件安装
计数器案例 四、组件中使用store
在组件中使用store我们按照如下的方式
在模板中使用在options api中使用比如computed在setup中使用
五、组件获取状态
在前面我们已经学习过如何在组件中获取状态了。 当然如果觉得那种方式有点繁琐表达式过长我们可以使用计算属性
但是如果我们有很多个状态都需要获取话可以使用mapState的辅助函数
mapState的方式一对象类型mapState的方式二数组类型也可以使用展开运算符和来原有的computed混合在一起
六、在setup中使用mapState
在setup中如果我们单个获取装是非常简单的 通过useStore拿到store后去获取某个状态即可 但是如果我们需要使用 mapState 的功能呢
默认情况下Vuex并没有提供非常方便的使用mapState的方式这里我们进行了一个函数的封装 useState.js:
import {computed} from vue;
import {mapState, useStore} from vuex;export function useState(mapper) {const store useStore()const storeStateFns mapState(mapper) // {name: function, age: function}const storeState {} // {name: ref, age: ref}Object.keys(storeStateFns).forEach((fnKey) {const fn storeStateFns[fnKey].bind({$store: store})storeState[fnKey] computed(fn)})return storeState
}
七、getters的基本使用
某些属性我们可能需要经过变化后来使用这个时候可以使用getters
getters可以接收第二个参数 getters的返回函数
getters中的函数本身可以返回一个函数那么在使用的地方相当于可以调用这个函数
mapGetters的辅助函数
这里我们也可以使用mapGetters的辅助函数。
在setup中使用
封装useGetters.js:
import {computed} from vue;
import {mapGetters, useStore} from vuex;export function useGetters(mapper) {const store useStore()const storeStateFns mapGetters(mapper) // {name: function, age: function}const storeState {} // {name: ref, age: ref}Object.keys(storeStateFns).forEach((fnKey) {const fn storeStateFns[fnKey].bind({$store: store})storeState[fnKey] computed(fn)})console.log(storeStateFns)console.log(storeState)return storeState
}
将前面封装的useState和useGetters进行再次封装 八、Mutation基本使用
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
Mutation携带数据
很多时候我们在提交mutation的时候会携带一些数据这个时候我们可以使用参数
payload为对象类型 对象风格的提交方式
Mutation常量类型
定义常量mutation-types.js
定义mutation
提交mutation mapMutations辅助函数 我们也可以借助于辅助函数帮助我们快速映射到对应的方法中 在setup中使用也是一样的 mutation重要原则
一条重要的原则就是要记住 mutation 必须是同步函数
这是因为devtool工具会记录mutation的日记每一条mutation被记录devtools都需要捕捉到前一状态和后一状态的快照但是在mutation中执行异步操作就无法追踪到数据的变化所以Vuex的重要原则中要求 mutation必须是同步函数
九、actions的基本使用
Action类似于mutation不同在于
Action提交的是mutation而不是直接变更状态Action可以包含任意异步操作
这里有一个非常重要的参数context context是一个和store实例均有相同方法和属性的context对象 所以我们可以从其中获取到commit方法来提交一个mutation或者通过 context.state 和 context.getters 来获取 state 和 getters 但是为什么它不是store对象呢这个等到讲Modules时再具体来说 actions的辅助函数
action也有对应的辅助函数
对象类型的写法数组类型的写法
actions的异步操作
Action 通常是异步的那么如何知道 action 什么时候结束呢
我们可以通过让action返回Promise在Promise的then中来处理完成后的操作
十、module的基本使用
什么是Module
由于使用单一状态树应用的所有状态会集中到一个比较大的对象当应用变得非常复杂时store 对象就有可能变得相当臃肿为了解决以上问题Vuex 允许我们将 store 分割成模块module每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块
module的命名空间
默认情况下模块内部的action和mutation仍然是注册在全局的命名空间中的
这样使得多个模块能够对同一个 action 或 mutation 作出响应Getter 同样也默认注册在全局命名空间
未使用命名空间时 如果我们希望模块具有更高的封装度和复用性可以添加 namespaced: true 的方式使其成为带命名空间的模块
当模块被注册后它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名
加了命名空间后
module的局部状态
对于模块内部的 mutation 和 getter接收的第一个参数是模块的局部状态对象 module修改或派发根组件
如果我们希望在home的action中修改root中的state那么有如下的方式
module的辅助函数
如果辅助函数有三种使用方法 方式一通过完整的模块空间名称来查找 方式二第一个参数传入模块空间名称后面写上要使用的属性 方式三通过 createNamespacedHelpers 生成一个模块的辅助函数
在options api 中使用
templatedivh2Root当前计数{{$store.state.rootCounter}}/h2h2Home当前计数{{$store.state.home.homeCounter}}/h2h2User当前计数{{$store.state.user.userCounter}}/h2hrh2{{homeCounter}}/h2h2{{doubleHomeCounter}}/h2button clickincrementhome1/buttonbutton clickincrementActionhome1/button/div
/template
script
// import {mapActions, mapGetters, mapMutations, mapState} from vuex;
import {createNamespacedHelpers} from vuex;
const {mapState, mapGetters, mapMutations, mapActions} createNamespacedHelpers(home)
export default {computed: {// 1.写法一/*...mapState({homeCounter: state state.home.homeCounter}),...mapGetters({doubleHomeCounter: home/doubleHomeCounter})*/// 2.写法二/*...mapState(home, [homeCounter]),...mapGetters(home, [doubleHomeCounter])*/// 3.写法三...mapState([homeCounter]),...mapGetters([doubleHomeCounter])},methods: {// 1.写法一/*...mapMutations({increment: home/increment}),...mapActions({incrementAction: home/incrementAction})*/// 2.写法二/*...mapMutations(home, [increment]),...mapActions(home, [incrementAction])*/// 3.写法三...mapMutations([increment]),...mapActions([incrementAction])}
}
/scriptstyle scoped/style
在composition api中使用 templatedivh2Root当前计数{{$store.state.rootCounter}}/h2h2Home当前计数{{$store.state.home.homeCounter}}/h2h2User当前计数{{$store.state.user.userCounter}}/h2hrh2{{homeCounter}}/h2h2{{doubleHomeCounter}}/h2button clickincrementhome1/buttonbutton clickincrementActionhome1/button/div
/template
script
import {createNamespacedHelpers} from vuex;
const {mapMutations, mapActions} createNamespacedHelpers(home)// 自定义hook
import {useState} from ./hooks/useState;
import {useGetters} from ./hooks/useGetters;export default {setup() {const state useState(home,[homeCounter])const getters useGetters(home, [doubleHomeCounter])const mutations mapMutations([increment])const actions mapActions([incrementAction])return {...state,...getters,...mutations,...actions}}
}
/scriptstyle scoped/style
useMapper.js:
import {computed} from vue;
import {useStore} from vuex;export function useMapper(mapper, mapFn) {const store useStore()const storeStateFns mapFn(mapper) // {name: function, age: function}const storeState {} // {name: ref, age: ref}Object.keys(storeStateFns).forEach((fnKey) {const fn storeStateFns[fnKey].bind({$store: store})storeState[fnKey] computed(fn)})console.log(storeStateFns)console.log(storeState)return storeState
}
useState.js:
import {createNamespacedHelpers, mapState} from vuex;
import {useMapper} from ./useMapper;export function useState(moduleName, mapper) {let mapperFn mapStateif (typeof moduleName string moduleName.length 0) {mapperFn createNamespacedHelpers(moduleName).mapState} else{mapperFn moduleName}return useMapper(mapper, mapperFn)
}
useGetters.js:
import {createNamespacedHelpers, mapGetters} from vuex;
import {useMapper} from ./useMapper;export function useGetters(moduleName, mapper) {let mapperFn mapGettersif (typeof moduleName string moduleName.length 0) {// 处理这种情况useGetters(home, [increment])mapperFn createNamespacedHelpers(moduleName).mapGetters} else {mapperFn moduleName // 处理这种情况useGetters([increment])}return useMapper(mapper, mapperFn)
}
十一、nexttick 官方解释将回调推迟到下一个 DOM 更新周期之后执行。在更改了一些数据以等待 DOM 更新后立即使用它。 比如我们有下面的需求
点击一个按钮我们会修改在h2中显示的messagemessage被修改后获取h2的高度
实现上面的案例我们有三种方式 方式一在点击按钮后立即获取到h2的高度错误的做法 方式二在updated生命周期函数中获取h2的高度但是页面其他数据更新也会执行该操作 方式三使用nexttick函数
nexttick是如何做到的呢