<template>
  <div id="app">
    <div>
      count:{{$store.state.count}}
    </div>
    <!-- getters里面的未发生变化的情况下,多次调用getters里面的值,只需执行一次,节省性能 -->
    <div>
      gettter:{{$store.getters.getCount}}
    </div>
    <div>
      gettter:{{$store.getters.getCount}}
    </div>
    <div>
      gettter:{{$store.getters.getCount}}
    </div>
    <button @click="$store.state.count = 10">不合规改变state</button>

    <!-- 不要直接修改state的值,因为一个state的值可能被多个组件使用,如果在某个组件里直接修改这个state的值,会影响到其他组件,不利于查找数据的改变来源。 -->
    <!-- <button @click="$store.state.count = 10">不合规改变state</button>

    <button @click="$store.commit('changeCount', 10)">同步加{{$store.state.count}}</button>

    <button @click="$store.dispatch('changeCount', 100)">异步加{{$store.state.count}}</button> -->
  </div>
</template>
<script>
export default {
  mounted() {
    console.log(this.$store)
  }
}
</script>
// src/vuex/store.js
import { applyMixin } from './install'
const forEachValue = (obj, cb) => {
  Object.keys(obj).forEach(key => cb(obj[key], key))
}
export let Vue
export class Store {
  constructor(options) {
    let computed = {}
    this.getters = {}
    // 在这里执行是为了让computed先赋值后调用
    forEachValue(options.getters, (value, key) => {
      // this.getters[key] = value // value现在是function,但是getters是属性 在组件中是这样使用的 -> $store.getters.getCount

      // 不这样写的原因是因为这样直接将value执行的结果赋值给了getters,再次取值后值不会变
      // this.getters[key] = value(this.state)

      // 这样写可以将getters变成属性,直接调用
      // Object.defineProperty(this.getters, key, {
      //   // 这种方式每次取值都会重新执行一次,如果在页面中多次调用同一个getters的值,也要执行多次,性能不高
      //   get:() => {
      //     return value.call(this, this.state )
      //   }
      // })

      computed[key] = () => { // 通过 computed 属性做了优化,计算属性也会被放到当前实例上
        return value.call(this, this.state)
      }
      Object.defineProperty(this.getters, key, {
        get:() => {
          return this._vm[key] // 取 computed 的key属性
        }
      }) 
    })
    // 把数据变成响应式的
    this._vm = new Vue({
      data: {
        // 不加 $ 这样写内部会使用代理操作,把所有属性代理给 this._vm,Vue不会对 $ 符开头的属性进行代理操作,这样写可以避免代理节省性能
        $$state: options.state
      },
      computed
    })
    console.log('this._vm',this._vm)
  }
  get state() {
    return this._vm._data.$$state
  }
}

export const install = (_Vue) => {
  Vue = _Vue
  applyMixin(Vue)
}