vuex使用及双向数据绑定原里

638 阅读2分钟

Vuex采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化

安装

直接下载CDN引用

//可以通过@来指定版本号
<script src='https://unpkg.com/vuex@2.0.0'></script>

通过npm下载

npm i vuex --save

核心属性

State

  • 用来存储共享的数据属性或状态
  • 可以使用mapState 辅助函数简化写法

Getters

  • 相当于计算属性,它的返回值会根据它的依赖被缓存起来,只有依赖值发生了变化才会重新计算。
  • Getter接受state作为第一个参数
  • 可以使用mapGetters辅助函数简化写法

Mutaions

  • 必须为同步函数
  • 在组件中使用this.$store.commit('xx')来触发
  • 可以使用mapMutations辅助函数简化写法

Actions

  • Action提交的是mutation,由mutation中的函数来修改state中的属性或状态
  • 可以包含任意异步操作
  • 在组件中使用this.$dispath('xx')来触发
  • 可以使用mapActions辅助函数简化写法

Modules

  • 允许将store分割成模块,每个模块拥有自己的state,getters,mutation,action
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const moduleA = {
  state: () => {...},
  mutaions:: {...},
  actions: {...},
  getters: {...}
}

const store = new Vuex.Store({
  state: {
    count: 0,
    list: [{
      id: 1, text: 'xiaoyao'
    }, {
      id: 2, text: 'xianshi'
    }],
  },
  getters: {
    filterList: state => state.list.filter(item => item.id === 1),
    //通过函数的方式获取值
    getList: (state) => (id) => state.list.find(item => item.id === id),
  },
  mutations: {
    //payload 可以是对象
    increment (state, payload) {
      state.count += n;
    }
  },
  actions: {
    setIncrement(context, payload) {
      setTimeout(()=>{
        context.commit('increment', n)
      })
    }
  },
  modules: {
    a: moduleA
  }
})

需要先在根实例中注册stroe

const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})
//在组件中使用
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    },
    mapState({
      count: state => state.count
    }),
    obj() {
      return this.$store.getters.filterList
    },
    ...mapGetters(['filterList', 'getList']),
    //给getters取别名
    ...mapGetters({doneFilter: 'filterList'}),
  },
  methods: {
    ...mapMutations(['increment']),
    ...mapMutations({add: 'increment'}),
    sum() {
      this.$store.commit('increment', 2);//this.add(2)
    },
    ...mapActions(['setIncrement']),
    ...mapActions({
      add: 'increment'
    }),
    setCount() {
      this.$store.dispach('setIncrement', 2)
    }
  }
}

双向数据绑定原理2.x

image.png

Vue 主要通过以下 4 个步骤来实现数据双向绑定的:

  • 实现一个监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
  • 实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
  • 实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
  • 实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。