override.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import { getWatcher, getDep } from './util'
  2. export default function (Vue) {
  3. // override init and inject vuex init procedure
  4. const _init = Vue.prototype._init
  5. Vue.prototype._init = function (options = {}) {
  6. options.init = options.init
  7. ? [vuexInit].concat(options.init)
  8. : vuexInit
  9. _init.call(this, options)
  10. }
  11. /**
  12. * Vuex init hook, injected into each instances init hooks list.
  13. */
  14. function vuexInit () {
  15. const options = this.$options
  16. const { store, vuex } = options
  17. // store injection
  18. if (store) {
  19. this.$store = store
  20. } else if (options.parent && options.parent.$store) {
  21. this.$store = options.parent.$store
  22. }
  23. // vuex option handling
  24. if (vuex) {
  25. if (!this.$store) {
  26. console.warn(
  27. '[vuex] store not injected. make sure to ' +
  28. 'provide the store option in your root component.'
  29. )
  30. }
  31. let { state, getters, actions } = vuex
  32. // handle deprecated state option
  33. if (state && !getters) {
  34. console.warn(
  35. '[vuex] vuex.state option will been deprecated in 1.0. ' +
  36. 'Use vuex.getters instead.'
  37. )
  38. getters = state
  39. }
  40. // getters
  41. if (getters) {
  42. options.computed = options.computed || {}
  43. for (let key in getters) {
  44. defineVuexGetter(this, key, getters[key])
  45. }
  46. }
  47. // actions
  48. if (actions) {
  49. options.methods = options.methods || {}
  50. for (let key in actions) {
  51. options.methods[key] = makeBoundAction(this.$store, actions[key])
  52. }
  53. }
  54. }
  55. }
  56. /**
  57. * Setter for all getter properties.
  58. */
  59. function setter () {
  60. throw new Error('vuex getter properties are read-only.')
  61. }
  62. /**
  63. * Define a Vuex getter on an instance.
  64. *
  65. * @param {Vue} vm
  66. * @param {String} key
  67. * @param {Function} getter
  68. */
  69. function defineVuexGetter (vm, key, getter) {
  70. Object.defineProperty(vm, key, {
  71. enumerable: true,
  72. configurable: true,
  73. get: makeComputedGetter(vm.$store, getter),
  74. set: setter
  75. })
  76. }
  77. /**
  78. * Make a computed getter, using the same caching mechanism of computed
  79. * properties. In addition, it is cached on the raw getter function using
  80. * the store's unique cache id. This makes the same getter shared
  81. * across all components use the same underlying watcher, and makes
  82. * the getter evaluated only once during every flush.
  83. *
  84. * @param {Store} store
  85. * @param {Function} getter
  86. */
  87. function makeComputedGetter (store, getter) {
  88. const id = store._getterCacheId
  89. // cached
  90. if (getter[id]) {
  91. return getter[id]
  92. }
  93. const vm = store._vm
  94. const Watcher = getWatcher(vm)
  95. const Dep = getDep(vm)
  96. const watcher = new Watcher(
  97. vm,
  98. state => getter(state),
  99. null,
  100. { lazy: true }
  101. )
  102. const computedGetter = () => {
  103. if (watcher.dirty) {
  104. watcher.evaluate()
  105. }
  106. if (Dep.target) {
  107. watcher.depend()
  108. }
  109. return watcher.value
  110. }
  111. getter[id] = computedGetter
  112. return computedGetter
  113. }
  114. /**
  115. * Make a bound-to-store version of a raw action function.
  116. *
  117. * @param {Store} store
  118. * @param {Function} action
  119. */
  120. function makeBoundAction (store, action) {
  121. return function vuexBoundAction (...args) {
  122. return action.call(this, store, ...args)
  123. }
  124. }
  125. // option merging
  126. const merge = Vue.config.optionMergeStrategies.computed
  127. Vue.config.optionMergeStrategies.vuex = (toVal, fromVal) => {
  128. if (!toVal) return fromVal
  129. if (!fromVal) return toVal
  130. return {
  131. getters: merge(toVal.getters, fromVal.getters),
  132. state: merge(toVal.state, fromVal.state),
  133. actions: merge(toVal.actions, fromVal.actions)
  134. }
  135. }
  136. }