Code前端首页关于Code前端联系我们

使用Vuex并实现一个简单版本的Vuex

terry 2年前 (2023-09-08) 阅读数 149 #Vue

Vuex 评论

Vuex 是什么

Vuex的使用并实现一个简易版VuexVuex的使用并实现一个简易版Vuex

Vuex 是专为 Vue.js 应用程序设计的状态管理模式。它使用集中存储来管理应用程序所有组件的状态,并使用相应的规则来确保状态以可预测的方式发生变化。

  • Vuex 是专门为 Vue.js 设计的状态管理库
  • 它采用集中式的方式来存储需要共享的数据
  • 从使用角度来看,它是一个JavaScript库
  • 其作用是进行状态管理,解决复杂的组件通信和数据共享

何时使用Vuex

官方文档:
Vuex 可以帮助我们管理共享状态,并附带了几个概念和框架。这需要平衡短期和长期利益。
如果您不打算开发大型单页应用程序,那么使用 Vuex 可能会很麻烦且多余。确实如此——如果你的应用足够简单,最好不要使用 Vuex。您只需要一个简单的商店模式即可。但是,如果您需要构建
一个中型到大型单页应用程序,您很可能会考虑如何更好地管理组件外部的状态,而 Vuex 将是一个自然的
选择。引用Redux的作者Dan阿布拉莫夫的话:Flux架构就像眼镜:你知道什么时候需要它。

当您的应用有以下需求场景时:

  • 同一条件下多个视图

  • 不同角度的行为必然改变同一个状态

    建议满足这种场景的公司使用Vuex进行数据处理,例如一个非常典型的场景:购物车。

注意:不要滥用Vuex。不符合上述要求的企业请勿使用。会让你的申请变得更加麻烦。

易于使用的Vuex

首先来看看vuex是如何使用的,然后尝试加币

安装

// npm
npm install vuex --save

// yarn
yarn add vuex
 

基本配置

在src目录下创建store文件夹,并创建index.js文件。然后就会写出下面的代码。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    coin: 0
  },
})

export default store
 

,然后在mian.js中引入store

import Vue from 'vue'
import App from './App.vue'
import router from './router' // 引入 store 
import store from './store'

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)

Vue.config.productionTip = false

new Vue({
  router,
  store, // 注册 store
  render: h => h(App),
}).$mount('#app')
 

吸气剂

Vuex 允许我们在存储中定义“getters”(可以将其视为存储的计算属性)。就像计算属性一样,getter 的返回值根据其依赖项进行缓存,并且仅当依赖项值发生变化时才重新计算。

  1. 将吸气剂的属性添加到商店
const store = new Vuex.Store({
  state: {
    coin: 0
  },
  getters: {
    getCoin(state) {
      return state.coin
    }
  },
})
 
  1. 在组件中使用吸气剂
  • 直接使用
<p>硬币:{{ $store.getters.getCoin }}</p>
 
  • mapGetters

vuex 提供了一种将存储中的 getter 映射到计算属性的方法

<p>硬币:{{ getCoin }}</p>
 
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters(['getCoin']),
  },
}
 

突变

Mutations 中的方法用于更改存储中的状态数据。 Mutations中的数据必须是同步数据。

  1. 添加突变字段以存储

mutations中的函数有两个参数,第一个是store的状态,第二个是通过store.commit传递的数据

const store = new Vuex.Store({
  state: {
    coin: 0
  },
  getters: {
    getCoin(state) {
      return state.coin
    }
  },
  mutations: {
    commitCoin (state, n) {
      state.coin += n
    }
  },
})
 
  1. 在组件中使用突变
  • 直接使用
<div>
  <el-input 
    v-model="coins"
    placeholder="请输入增加的硬币数目"
    style="width: 300px"
  ></el-input>
  <el-button 
    type="primary"
    @click="addCion"
  >增加一个硬币</el-button>
  <p>硬币:{{ getCoin }}</p>
</div>
 
import { mapGetters } from 'vuex'

export default {
  data() {
    return {
      coins: 1
    }
  },
  computed: {
    ...mapGetters(['getCoin']),
  },
  methods: {
    addCion() {
      // store.commit
      this.$store.commit('commitCoin', Number(this.coins))
    }
  }
}
 

$store.commit 接收两个参数,一个是storemutations的函数名,另一个是必须传入mutation函数的参数。

  • 地图突变

行动

与突变类似的操作,除了:

  • Action 提交突变而不是直接更改状态。
  • Action 可以包含任何异步操作。
  1. 商店添加操作字段
const store = new Vuex.Store({
  state: {
    coin: 0
  },
  getters: {
    getCoin(state) {
      return state.coin
    }
  },
  mutations: {
    commitCoin (state, n) {
      state.coin += n
    }
  },
  actions: {
    addCoinSync(context, payload) {
      setTimeout(() => {
        context.commit('commitCoin', payload)
      }, 1000)
    }
  }
})
 
  1. 在组件中使用操作
  • 直接使用
import {
  mapGetters,
  mapMutations,
} from 'vuex'

export default {
  data() {
    return {
      coins: 1
    }
  },
  computed: {
    ...mapGetters(['getCoin']),
  },
  methods: {
    ...mapMutations(['commitCoin']),
    addCion() {
      // this.$store.commit('commitCoin', Number(this.coins))
      // this.commitCoin(Number(this.coins))
      this.$store.dispatch('addCoinSync', Number(this.coins))
    }
  }
}
 
  • 地图操作
import { 
  mapGetters,
  mapMutations,
  mapActions,
} from 'vuex'

export default {
  data() {
    return {
      coins: 1
    }
  },
  computed: {
    ...mapGetters(['getCoin']),
  },
  methods: {
    ...mapMutations(['commitCoin']),
    ...mapActions(['addCoinSync']),
    addCion() {
      // 等同于 this.$store.dispatch('addCoinSync', Number(this.coins))
      this.addCoinSync(Number(this.coins))
    }
  }
}
 

Vuex模拟实现

实施思路

上面我们回顾了Vuex的使用,我们自己模拟一个Vuex吧

  • 实施安装方法
    • Vuex是Vue的一个插件,所以和模拟VueRouter类似,首先实现与Vue插件一致的安装方法
  • 实现 Store 类
    • 实现构造函数并接收选项
    • stat
    • 的反应性治疗 实现
    • getters
    • 承诺,运送方式
let Vue

class Store{
    constructor(options) {
      this.state = new Vue({
          data: options.state
      })

      this.mutations = options.mutations
      this.actions = options.actions

      options.getters && this.handleGetters(options.getters)
    }

    commit = (type, arg) => {
      this.mutations[type](this.state, arg)
    }

    dispatch(type, arg) {
      this.actions[type]({
        commit: this.commit,
        state: this.state,
      }, arg)
    }

    handleGetters(getters) {
      this.getters = {}
      // 遍历getters所有key
      Object.keys(getters).forEach(key => {
        // 为this.getters定义若干属性,这些属性是只读的
        Object.defineProperty(this.getters, key, {
            get: () => {
                return getters[key](this.state)
            }
        })
      }) 
    }
}

// 向外提供 install
function install (_Vue) { 
  Vue = _Vue

  Vue.mixin({
    beforeCreate() {
      // 在 beforeCreate 中注册 store
      if (this.$options.store) {
          Vue.prototype.$store = this.$options.store
      }
    }
  })
 }

export default {
  Store,
  install,
}
 

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门