小白学前端之TypeScript使用Vuex 4.0|8月更文挑战

简介: 官方介绍:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

网络异常,图片无法展示
|

后端程序猿自学前端笔记

简介


官方介绍:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

简单来说,Vuex 就像是前端的数据库或缓存,不管什么页面,只要 Vuex 里面有的数据,都可以去拿。

Vuex 分为 5 个部分:

  • State:是数据源,存放数据
  • Getters:可以取得 State 的数据,然后自定义组装返回新的数据
  • Mutations:可以改变 State 的数据,建议方法执行是同步的
  • Actions:可以异步执行 Mutations 里的方法
  • Modules:每个 Module 都有各自的 State、Getters、Mutations、Actions

这 5 个部分相辅相成。

TypeScript 使用

在 vue 项目根目录执行命令来进行 vuex 模块的安装

npm install vuex@next --save

安装好后我们新建文件 /src/store/store.ts ,然后在里面定义 InjectionKeyStore

import { InjectionKey } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex'
// 定义 State 数据类型的接口
interface IState{
}
// 类型传递
export const key: InjectionKey<Store<IState>> = Symbol()
export const store = createStore<IState> ({ 
})
// 用于组合式API setup() 里,省的每次都传入 key 
export function useStore() {
    return baseUseStore(key)
}

然后在 main.ts 文件里使用上面定义的 vuex

import { createApp } from 'vue'
import App from './App.vue'
import { store,key } from './store/store'
createApp(App)
.use(store,key)
.mount('#app')

State

State 是存储数据源的地方,所以我们可以在这里存储我们的数据,比如我这边定义一个 name 字段,需要在接口 IState 添加定义数据类型

interface IState{
    name: string
}

然后在 createStore 里添加数据

export const store = createStore<IState> ({ 
    state:{
        name: 'ooooooh灰灰'
    }
})

数据我们已经定义好了,接下来就是要在页面访问这个数据了,下面提供了两种方式来访问 vuex 里的数据

组合式 API 访问

在组合式 API 中,我们可以直接导入刚才在 /src/store/store.ts 里定义的 useStore() 方法来访问 vuex 里的数据

import { defineComponent } from 'vue';
import { useStore } from './store/store'
export default defineComponent({
  setup(){
    let store = useStore()
    // 访问 state 里的 name 数据
    console.log(store.state.name)
  }
});

运行代码的话就会在控制台打印 ooooooh灰灰

...toRefs() 访问所有字段

如果要在页面访问的话,可以利用 ...toRefs() 来直接展开 store.state 里的所有字段,然后在页面直接访问 vuex 的 state 里的字段

// App.vue
<template>
  <div>
    {{ name }}
  </div>
</template>
<script lang="ts">
  import { defineComponent, toRefs} from 'vue';
  import { useStore } from './store/store'
  export default defineComponent({
    setup(){
      let store = useStore()
      return {
        // 展开 state 所有的字段
        ...toRefs(store.state)
      }
    }
  });
</script>
<style>
</style>

reactive 聚合单个字段

如果你想单个数据导入的话,可以直接和页面数据一起放在 reactive

import { defineComponent, reactive, toRefs} from 'vue';
  import { useStore } from './store/store'
  export default defineComponent({
    setup(){
      let store = useStore()
      // 把 vuex 的 state 的数据放进 reactive 里
      let params = reactive({
        name: store.state.name
      })
      return {
        ...toRefs(params),
      }
    }
  });

computed 访问单个字段

也可以使用 computed 模块来访问数据,要先导入 vue 里的 computed

// App.vue
<template>
  <div>
    {{ name }}
  </div>
</template>
<script lang="ts">
  import { defineComponent, computed} from 'vue';
  import { useStore } from './store/store'
  export default defineComponent({
    setup(){
      let store = useStore()
      return {
        name: computed(()=>store.state.name)
      }
    }
  });
</script>
<style>
</style>

Getters

getters 里的方法在 vuex/types/index.d.ts 中是这样定义的

export type Getter<S, R> = (state: S, getters: any, rootState: R, rootGetters: any) => any;

他有 4 个参数,分别是 state、getters、rootState、rootGetters

其中,state 可以取得同级中 state 里的数据,getters 可以取得同级中 getters 其他的方法返回的数据

rootStaterootGetters 是在当当前 Getters 处于 module 中时,可以取得根部的 state 和 gatters 里的数据

比如我们可以将 state 里的变量封装成一句话然后返回:

export const store = createStore<IState> ({ 
    state:{
        name: 'ooooooh灰灰',
    },
    getters:{
        newName(state):string{
            // 通过 state 访问 name 字段
            return '大家好!我是:'+state.name
        }
    }
})

当我们要访问其他 getter 时,我们可以这样:

export const store = createStore<IState> ({ 
    state:{
        name: 'ooooooh灰灰',
        age: 20
    },
    getters:{
        hello(state,getters):string{
            // 通过 getters 访问其他 getter
            return '大家好!我是:'+state.name+','+getters.ageInfo
        },
        ageInfo(state):string{
            return '年龄:'+state.age
        }
    }
})

组合式 API 访问

我们可以在组合式 API 里像访问 state 的里数据一样访问 gatters 里的方法:

import { defineComponent } from 'vue';
import { useStore } from './store/store'
export default defineComponent({
  setup(){
    let store = useStore()
    // 访问 getters 里的 hello 方法
    console.log(store.getters.hello)
  }
});

此外,getters 也可以使用 ...toRefs()computed 这些方法来访问:

<template>
  <div>
    {{ hello }}
  </div>
</template>
<script lang="ts">
  import { defineComponent, computed, toRefs } from 'vue';
  import { useStore } from './store/store'
  export default defineComponent({
    setup(){
      let store = useStore()
      return {
        // 通过 computed 访问 getters 里的 hello 
        hello: computed(()=>store.getters.hello),
        // 通过 ...toRefs() 访问
        // ...toRefs(store.getters),
      }
    }
  });
</script>
<style>
</style>

Mutations

如果你要改变 state 里的数据时,就要用到 Mutations 了,它可以提供改变 state 里数据的方法,它在 vuex/types/index.d.ts 中是这样定义的:

export type Mutation<S> = (state: S, payload?: any) => any;

其中 state 可以拿到 state 里的数据,payload 是自定义传入的参数,后面有个问号,代表这是可选项

所以当我们要改变 state 的字段的值时,我们可以在 store.ts 中这样写代码 :

export const store = createStore<IState> ({ 
    state:{
        name: 'ooooooh灰灰',
    },
    mutations:{
        changeName(state){
            // 改变 state 中 name 的值
            state.name = 'greycode'
        }
    }
})

如果要自定义传入参数的话,就可以这样写:

export const store = createStore<IState> ({ 
    state:{
        name: 'ooooooh灰灰',
    },
    mutations:{
        changeName(state,newName:string){
            // 传入自定义字段并设置
            state.name = newName
        }
    }
})

组合式 API 访问

在组合式 API 中,我们可以用 commit 来提交执行这个方法:

import { defineComponent } from 'vue';
import { useStore } from './store/store'
export default defineComponent({
  setup(){
    let store = useStore()
    let change = () => {
      // 提交执行 mutations 中 changeName 方法
      // store.commit('changeName')
      // 提交执行 mutations 中 changeName 方法,并传入自定义参数
      store.commit('changeName','自定义的')
    }
    return {
      change
    }
  }
});

...mapMutations

我们可以直接在组合式 API 中使用 ...mapMutations 来获得 mutations 中的方法,然后直接在页面中调用这个方法

import { defineComponent } from 'vue';
  import { mapMutations } from 'vuex';
  import { useStore } from './store/store'
  export default defineComponent({
    setup(){
      let store = useStore()
      return {
        // 使用 ...mapMutations 来获得 mutations 中的方法
        ...mapMutations(['changeName'])
      }
    }
  });

然后直接在页面中使用:

<template>
  <div>
    <button type="button" @click="changeName">按钮</button>
    <!-- 也可以传入函数自定义参数 -->
    <button type="button" @click="changeName(’自定义名字‘)">按钮</button>
  </div>
</template>

Action

当要异步改变 state 中的数据时,就要用到 Action 了,但是它不是直接改变 state 中的数据,而是通过异步执行 mutations 中的方法来间接改变 state 中的数据的

它在 vuex/types/index.d.ts 中是这样定义的:

export type Action<S, R> = ActionHandler<S, R> | ActionObject<S, R>;

它支持两种类型的数据,一个是 ActionHandler<S, R> ,另一个是 ActionObject<S, R>。其中 ActionObject 一般用于 Module 中的命名空间,它们的定义如下:

export type ActionHandler<S, R> = (this: Store<R>, injectee: ActionContext<S, R>, payload?: any) => any;
export interface ActionObject<S, R> {
  root?: boolean;
  handler: ActionHandler<S, R>;
}

这里只讲下 ActionHandler ,另外一个等到 Module 模块中再讲。

在 ActionHandler 中,它有 3 个参数,分别是 this、injectee、payload,其中 this 代表的是整个 Store 对象,injectee 是当前 Action 所在的上下文,payload 是可以自定义的传入参数

所以我们可以这样使用它:

export const store = createStore<IState> ({ 
    state:{
        name: 'ooooooh灰灰'
    },
    mutations:{
        changeName(state){
            state.name = '异步改名'
        }
    },
    actions:{
        asyncChange(ctx){
          // 两秒后更改名字
          setTimeout(() =>{
            ctx.commit('changeName')
          },2000)
        }
    }
})

组合式 API 访问

定义好 actions 后,我们可以在组合式 API 中用 dispatch 来分发 action:

import { defineComponent } from 'vue';
import { useStore } from './store/store'
export default defineComponent({
  setup(){
    let store = useStore()
    let syncChange = () => {
      // 执行 actions 中的 asyncChange 方法
      store.dispatch('asyncChange')
    }
    return {
      syncChange
    }
  }
});

...mapActions

也可以用 ...mapActions 来直接获得 actions 中的方法:

import { defineComponent } from 'vue';
import { mapActions } from 'vuex';
import { useStore } from './store/store'
export default defineComponent({
  setup(){
    let store = useStore()
    return {
      ...mapActions(['asyncChange'])
    }
  }
});

页面使用的话和 mutation 差不多,直接访问 actions 中的方法名就可以了:

<template>
  <div>
    <button type="button" @click="asyncChange">按钮</button>
  </div>
</template>

最后


除此之外还有一个 Module 模块,不过一般小项目用不到而且内容也比较多,下次再学吧。

目录
相关文章
|
1月前
|
存储 JavaScript 前端开发
前端技术分享:使用Vue.js与Vuex管理状态
【10月更文挑战第1天】前端技术分享:使用Vue.js与Vuex管理状态
46 6
|
3月前
|
前端开发 JavaScript API
解锁高效应用构建:Vuex与后端交互的前端状态同步策略,让数据流动如行云流水,紧跟前端开发的热点趋势
【8月更文挑战第27天】本文深入探讨了Vue框架下的前端状态管理库Vuex与后端服务交互时的状态同步策略。通过剖析Vuex的核心机制——状态(State)、变异(Mutation)、动作(Action)及模块(Module),文章展示了如何优雅地将后端数据加载并更新至前端状态中。特别地,借助示例代码解释了Action处理API调用、Mutation更新状态的过程,并介绍了如何通过模块化和命名空间提高状态管理的准确性和时效性。此外,还讨论了组件如何利用`mapState`和`mapActions`简化状态访问与操作的方法。遵循这些策略,开发者可以在构建复杂应用时显著提升性能与用户体验。
46 0
|
1月前
|
存储 缓存 前端开发
Vuex深入探究:前端状态管理的利器
【10月更文挑战第11天】Vuex深入探究:前端状态管理的利器
21 1
|
1月前
|
JavaScript 前端开发 开发者
使用 Vue.js 和 Vuex 构建响应式前端应用
【10月更文挑战第2天】使用 Vue.js 和 Vuex 构建响应式前端应用
29 0
|
3月前
|
存储 前端开发 JavaScript
解锁前端高手之路:Vuex 状态管理实战,从零到精通的旅程!
【8月更文挑战第27天】状态管理在大型单页应用开发中至关重要。Vue.js 通过其官方工具 Vuex 提供了一套强大且直观的 API。本文从零开始引导你逐步掌握 Vuex。首先介绍如何安装和配置,然后通过具体示例深入探讨状态(State)、变更(Mutations)、动作(Actions)以及模块化 Store 的使用方法。最后,通过购物车管理实战案例展示如何运用 Vuex 解决复杂状态管理问题。掌握这些技巧后,你将能在项目中高效地利用 Vuex。
31 1
|
3月前
|
JavaScript 前端开发 编译器
TypeScript:一场震撼前端开发的效率风暴!颠覆想象,带你领略前所未有的编码传奇!
【8月更文挑战第22天】TypeScript 凭借其强大的静态类型系统和丰富的工具支持,已成为前端开发的优选语言。它通过类型检查帮助开发者早期发现错误,显著提升了代码质量和维护性。例如,定义函数时明确参数类型,能在编译阶段捕获类型不匹配的问题。TypeScript 还提供自动补全功能,加快编码速度。与 Angular、React 和 Vue 等框架的无缝集成进一步提高了开发效率,使 TypeScript 成为现代前端开发中不可或缺的一部分。
40 1
|
3月前
|
JavaScript 前端开发 安全
【技术革新】Vue.js + TypeScript:如何让前端开发既高效又安心?
【8月更文挑战第30天】在使用Vue.js构建前端应用时,结合TypeScript能显著提升代码质量和开发效率。TypeScript作为JavaScript的超集,通过添加静态类型检查帮助早期发现错误,减少运行时问题。本文通过具体案例展示如何在Vue.js项目中集成TypeScript,并利用其类型系统提升代码质量。首先,使用Vue CLI创建支持TypeScript的新项目,然后构建一个简单的待办事项应用,通过定义接口描述数据结构并在组件中使用类型注解,确保代码符合预期并提供更好的编辑器支持。
84 0
|
3月前
|
存储 JavaScript 前端开发
Vue.js + Vuex:解锁前端复杂应用的神秘钥匙,探索状态管理的新境界!
【8月更文挑战第30天】Vue.js结合Vuex状态管理,为复杂前端应用提供了解锁高效与优雅的金钥匙。Vue.js凭借简洁的API和高效虚拟DOM更新机制广受好评,但在大规模应用中,组件间状态共享变得复杂。这时,Vuex通过中心化状态存储,使状态管理清晰可见,如同为Vue.js应用增添智慧大脑。例如,在购物车应用中,Vuex通过`state`、`mutations`、`actions`和`getters`清晰管理状态,简化组件间状态同步,减少耦合,确保单一状态源,使开发更加高效有序。在Vue.js的世界里,Vuex是一位智慧管家,让前端开发不仅高效,更成为一门艺术。
26 0
|
3月前
|
资源调度 JavaScript 前端开发
Vue3+TypeScript前端项目新纪元:揭秘高效事件总线Mitt,轻松驾驭组件间通信的艺术!
【8月更文挑战第3天】Vue3结合TypeScript强化了类型安全与组件化开发。面对大型应用中复杂的组件通信挑战,可通过引入轻量级事件发射器Mitt实现事件总线模式。Mitt易于集成,通过简单几步即可完成安装与配置:安装Mitt、创建事件总线实例、并在组件中使用`emit`与`on`方法发送及监听事件。此外,利用TypeScript的强大类型系统确保事件处理器正确无误。这种方式有助于保持代码整洁、解耦组件,同时提高应用的可维护性和扩展性。不过,在大规模项目中需谨慎使用,以防事件流过于复杂难以管理。
109 1
|
3月前
|
开发框架 JSON 缓存
基于SqlSugar的开发框架循序渐进介绍(22)-- Vue3+TypeScript的前端工作流模块中实现统一的表单编辑和表单详情查看处理
基于SqlSugar的开发框架循序渐进介绍(22)-- Vue3+TypeScript的前端工作流模块中实现统一的表单编辑和表单详情查看处理