Vue 实现一简单响应式状态管理Store

Before

在 Vue 中做数据的集中式状态管理首先想到的是 Vuex, 这是官方指定的状态管理模式。但是如果不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。(该描述出自 Vuex 官网描述)  Vuex 官网文档

状态管理的本质是数据共享,也可以用这种思路实现组件通信,这里简单的探索一下如何实现一简单数据共享的 Store。

基本思路:定义一个全局可访问的 store 对象,该对象中维护了一可供访问的属性state, 并且提供了一些可以操作state的方法,简单来说这就实现了一个超级简单的数据共享。

定义 Store.js

import Vue from "vue";

class Store {
    constructor(){
        this.state ={
            arr:[],
            count:0
        }
    }

    // 添加
    addItem = (item) => {
        this.state.arr.unshift(item)
    }

    // 删除
    delItem = () => {
        this.state.arr.pop()
    }

    // count++
    increate = () => {
        this.state.count++
    }
}

const store =  new Store()

store.install = () => {
    Vue.prototype.$verySimpleStore = store 
}

export default store
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// 将 store 挂到 Vue原型
import store from "./assets/js/store";
Vue.use(store)

Vue.use(ElementUI);
new Vue({
  render: h => h(App),
}).$mount('#app')

这里通过类实例化一个 store 对象,在其实例上声明state(注意是对象), addItem、delItem为对象上用来操作 arr数组 的增加与删除方法,increate 为给 count 递增的函数。通过Vue.use()将 store 对象挂在Vue的原型上,这样就可以实现该对象的全局访问(组件vc通过原型链获取 $verySimpleStore 属性)。如果对此不熟悉,传送门

案例 -- 使用Store

  

 在根组件中引入vcA、vcB两个组件(简称A、B组件),在 A 组件中希望输入一段字符,将其存到数组 arr 中。在 B 组件中有一 删除按钮和一个点击递增的按钮,点击删除数组 arr 中最后一个元素,或者增加count值。

APP组件

<template>
  <div id="app">
    <div class="box">
      <button @click="test">click me to show the state of Store</button>
      <vcA></vcA>
      <vcB></vcB>
      <ul>
           <!-- state.arr 或者 $verySimpleStore.state.arr 都会被响应式监听 -->
        <li v-for="(item,index) in state.arr" :key="index"> {{item}} </li>
      </ul>
      count: {{ state.count }}
    </div>
  </div>
</template>

<script>
import vcA from "./components/vcA.vue";
import vcB from "./components/vcB.vue";
export default {
  name: 'App',
  components:{
    vcA,
    vcB
  },
  mounted(){
  },
  data() {
    return {
      state:this.$verySimpleStore.state
    }
  },
  methods: {
    test(){
      console.log('Store',this.$verySimpleStore.state);
    }
  },
}
</script>

A组件

<template>
    <div>
        <input type="input" @keyup.enter="enterValue">
    </div>
</template>

<script>
export default {
   methods:{
    enterValue(e){
        let per = {name:e.target.value,age:18}
        this.$verySimpleStore.addItem(per)
        e.target.value = ''
    }
   },
}

B组件

<template>
    <div ref="vcbBox">
        <button @click="delBtn">click me to del</button>
        <button @click=" $verySimpleStore.increate() ">click me to count++</button>
    </div>
</template>

<script>
export default {
   methods:{
    delBtn(){
        this.$verySimpleStore.delItem()
    },
   },
}
</script>

这样一来,一个超级简单的状态管理 Store 基本就实现了。

数据响应式变化?

在 App 中将其赋值给 data 中的 state 属性,这样做目的是为了给 Store 中 state 增加响应式。如果没有这一步,页面不会监听到数据变化,也不会发生修改。

如果不做这一步,我们怎么来实现Store的响应式状态?

在Vue 中,数据经过了深层次侦听,故当其变化时可以动态更新页面(数组的变化通过改写七种方式来实现,注意,这只是针对Vue2)。于是我们可以这样改造一下代码。

改造Store.js

// state 不再指向一对象,而是指向了一个 vm 实例,data 中 state 里面的属性会代理到this.state(即vm)身上,从而实现数据侦听   
 constructor(options){
        this.state = new Vue({
            data:options.state
        })
    }

// 实例化一个 store 将 options 传入
const store =  new Store({
    state: {
        arr:[],
        count:0
    }
})

在组件中,无需通过data来引用,直接调用Store中state状态。 

改写App组件

<template>
  <div id="app">
    <div class="box">
      <button @click="test">click me to show the state of Store</button>
      <vcA></vcA>
      <vcB></vcB>
      <ul>
        <li v-for="(item,index) in $verySimpleStore.state.arr" :key="index"> {{item}</li>
      </ul>
      count: {{ $verySimpleStore.state.count }}
    </div>
  </div>
</template>

<script>
import vcA from "./components/vcA.vue";
import vcB from "./components/vcB.vue";
export default {
  name: 'App',
  components:{
    vcA,
    vcB
  },
  mounted(){
  },
  data() {
    return {
      // state:this.$verySimpleStore.state
    }
  },
  methods: {
    test(){
      console.log('Store',this.$verySimpleStore.state);
    }
  },
}
</script>

以上便是一个简单的状态管理Store的简单实现。

参考来源:

简单状态管理起步使用

vuex 响应式原理

Vue 简单状态管理—store模式

自己实现简单的 Store 模式

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值