lizuncong (lizuncong) · GitHubI am a strong believer in reverse engineering. lizuncong has 42 repositories available. Follow their code on GitHub.https://github.com/lizuncong

        这段时间结合vue及vuex的知识来阅读vuex源码,收获挺多的。因此把阅读过程中我对vuex的理解,大到一个类,一个函数,小到一个变量的使用,都记录下来。一千个读者就有一千个哈姆雷特,在阅读过程中,由于本人功力,经验原因,难免有理解不到位的地方,欢迎多多指教。

        在实际项目中,我们经常遇到多个组件视图依赖同一个状态,并且其中的一个组件更改这个状态时,其余依赖了该状态的组件视图也要相应的更新。假设我们要实现一个定时器应用,组件树如下:

图1 组件树

      这里根组件main.js,以及后代组件app.vue,counter.vue,counterItem.vue需要共享状态count。当状态count更新时,所有依赖count的组件都必须响应更新。为了实现根组件以及后代组件能响应count的变化,我们需要把数据count放在根组件main.js的data属性中,然后通过props属性一层一层往下传递给后代组件,这样当根组件的count属性变化时,其后代中依赖了count的组件也会相应的更新。为了实现任何依赖count的组件更改count时,其他组件也能够响应更新,我们需要在根组件中定义一个方法,并且把这个方法一层一层地往下传递给后代组件。当需要在后代组件中更新count时,可通过emit方法向父级组件触发更新事件,这样一级一级往上传递emit事件,直到触发根组件main.js中的更新状态方法。可以看出,当应用越来越复杂,组件层级越来愈深时,这种一层一层往下传递data,一层一层往上触发事件的方式是繁琐、低效同时维护极其麻烦的。因此我们需要一种全局的状态管理容器,任何组件需要用到里面的状态时就去容器读取,需要变更状态时,就向容器提交变更。这样不管应用多复杂,组件树层级多深,组件都能直接访问里面的状态。而我们要做的只是维护全局的状态管理。

       这一节的源码如下,源码对应图1的组件树:

      main.js 

import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false

new Vue({
  el: '#app',
  data () {
    return {
      count: 1
    }
  },
  components: { App },
  template: '<App :count="count" @increment = "increment"/>',
  methods: {
    increment () {
      this.count++
    }
  }
})

App.vue

<template>
  <div id="app">
    app.vue
    <div>{{ count }}</div>
    <div @click="$emit('increment')">increment in app.vue</div>
    <Counter :count="count" @increment="$emit('increment')"/>
  </div>
</template>

<script>
import Counter from './components/counter'
export default {
  props: ['count'],
  components: {
    Counter
  }
}
</script>

counter.vue

<template>
  <div id="counter">
    counter.vue
    <div>{{ count }}</div>
    <div @click="$emit('increment')">increment in counter.vue</div>
    <CounterItem :count="count" @increment="$emit('increment')"/>
  </div>
</template>

<script>
import CounterItem from './counterItem'
export default {
  props: ['count'],
  components: {
    CounterItem
  }
}
</script>

counterItem.vue

<template>
  <div id="counter-item">
    counter-item
    <div>{{ count }}</div>
    <div @click="$emit('increment')">increment in counterItem.vue</div>
  </div>
</template>

<script>
export default {
  props: ['count']
}
</script>

Logo

前往低代码交流专区

更多推荐