Vuex中的state,为什么放在component的的computed属性而非data中?

如何使用Vuex中state里的数据

参考:vuex的state中的数据的四种使用方法

  1. 存储在 Vuex 中的数据和 Vue 实例中的 data 遵循相同的规则,data遵循什么规则?
    • 类型:Object | Function,组件的定义只接受 function
    • Vue会递归的将data中的property转换为getter/setter,从而让data的property能够响应数据变化
    • var vm = new Vue({ data: {a : 1}) ,可以通过vm.$data访问原始数据对象。Vue 实例也代理了 data 对象上所有的 property,因此访问 vm.a等价于访问 vm.$data.a

参考:vue中组件的data为什么是一个函数
Vue组件是可以复用的vue实例,要保证不管组件被复用了多少次,组件中的data数据都应该是相互隔离,互不影响的,所以应该保证,组件每复用一次,data中的数据都应该被复制一次。将data写成一个函数,数据以函数的形式返回,这样每复用一次组件,就会返回一份新的data

  1. 由于Vuex的状态存储是响应式,从store实例中读取状态最简单的方法就是在计算属性中返回某个状态
// 创建一个 Counter 组件
const Counter = {
  template: `<div>{
   
   { count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

每当store.state.count变化的时候,都会重新求取计算属性,并且触发更新相关联的DOM。
**缺陷:**在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入,并且在测试组件时需要模拟状态

  1. Vuex通过store选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 Vue.use(Vuex))。通过在根实例中注册store选项,该store实例会注入到根组件下的所有子组件中,且子组件能通过this.$store访问到,
const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})
const Counter = {
  template: `<div>{
   
   { count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

自己在项目中:
main.js中,首先import store from './store',然后

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

在store中的index.js中:
在这里插入图片描述
补充:vue $mount 和 el的区别

**两者在使用效果上没有任何区别,都是为了将实例化后的vue挂载到指定的dom元素中。**如果在实例化vue的时候指定el,则该vue将会渲染在此el对应的dom中,反之,若没有指定el,则vue实例会处于一种“未挂载”的状态,此时可以通过$mount来手动执行挂载。

为什么state中的数据放在组件的computed中而不是data中

参考:为什么要使用computed而不是data获取vuex中的state
这是因为data 中的内容只会在 created 钩子触发前初始化一次,具体来说就是data中设置count: this.$store.state.count则count的值是created钩子执行前this.$store.state.count的值,赋值之后属性的值就是纯粹的字面量,之后this.$store.state.count 如何变化均影响不到count的取值。而 computed 则是通过== 依赖追踪==实现的,计算属性在它的相关依赖发生改变时会重新求值。

结合深入响应式原理,理解data和生命钩子computed

关于***data***,
Vue 不能检测数组和对象的变化

  1. 关于对象,Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的
  • 对于已经创建的实例,**Vue 不允许动态添加根级别的响应式 property。**可以使用Vue.set(object, propertyName, value),例如Vue.set(vm.someObject, 'b', 2);也可以使用vm.$set,例如this.$set(this.someObject,'b',2)
  1. 关于数组,Vue 不能检测以下数组的变动:
    • 当你利用索引直接设置一个数组项时,vm.items[indexOfItem] = newValue
    • 当你修改数组的长度时,vm.items.length = newLength
    • 针对问题一,可以使用:Vue.set(vm.items, indexOfItem, newValue)(即Vue.set)或者vm.items.splice(indexOfItem, 1, newValue)(即Array.prototype.splice)或者vm.$set(vm.items, indexOfItem, newValue)(即vm.$set)
    • 针对问题二,可以使用splice,vm.items.splice(newLength)
  2. 异步更新队列
    • Vue更新DOM是异步的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。
    • 在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate
    • 为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用,$nextTick() 返回一个 Promise 对象

关于***computed***,

  • 计算属性默认只有 getter,且是没有副作用的
  • 将同一函数定义为一个方法和定义成一个计算属性:每当触发重新渲染时,调用方法将总会再次执行函数;**计算属性是基于它们的响应式依赖进行缓存的。**只在相关响应式依赖发生改变时它们才会重新求值。在Vuex中,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
  • 为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!
  • 与侦听属性watch,当需要在数据变化时执行异步或开销较大的操作时,watch是最有用的。

猜你喜欢

转载自blog.csdn.net/weixin_43912756/article/details/108429404
今日推荐