vuex

2020-11-05  本文已影响0人  Small_Song

文章目录:
1.vuex是怎么实现数据共享的
2.使用vuex的理由是什么,我们在全局定义一个class类来处理共享数据不行吗

  1. vuex Store
  2. vuex State
  3. mapState 辅助函数
  4. vuex Getter
  5. mapGetters 辅助函数
  6. Mutation
  7. vuex Action
  8. 只能通过mutation改变数据,为什么不直接触发mutation,而要通过
    action来触发mutation改变数据,如此多此一举是因为什么。
  9. localstorage, sessionstorage, vuex的区别和优势

1.Vuex是怎么实现数据共享的

一句话就是:vuex本质相当于一个没有template的组件,在当前组件的beforeCreated的时候通过mixin注入进来;

https://www.jianshu.com/p/d95a7b8afa06

2.使用vuex的理由是什么,我在全局定义一个class类来处理状态共享不行吗。

1.全局class虽然可以做到全局使用,但是没有响应式监听吧~~
2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交(commit) mutations。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

页面中模版获取state数据渲染页面,用户通过action改变数据导致页面重新渲染。

3 vuex Store

每一个 Vuex 应用的核心就是 store(仓库)。"store" 基本上就是一个容器,它包含着你的应用中大部分的状态(state)。Vuex 和单纯的全局对象有以下两点不同:

Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交(commit) mutations。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

const store = new Vuex.Store({
  state: {
    count: 0,
    step:2
  },
  mutations: {
    increment (state) {
      state.count += state.step
    }
  }
})

现在,你可以通过 store.state 来获取状态对象,以及通过 store.commit 方法触发状态变更:

store.commit('increment')
console.log(store.state.count) // -> 2

4.vuex State

Vuex 使用 单一状态树 —— 是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。

// 创建一个 Counter 组件
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

我们在这个组件里面用到了count,当我们通过store.commit('increment')时,组件里会发生rerender。

Vuex 通过 store 选项,提供了一种机制将状态从根组件『注入』到每一个子组件中(需调用 Vue.use(Vuex)):

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

5. mapState 辅助函数

当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:

// 在单独构建的版本中辅助函数为 Vuex.mapState
export default {
    computed: mapState({
    // 箭头函数可使代码更简练
    apple: state => state.apple,
    total (state) {
      return state.apple + state.orange
    }
  })
}

有了对象扩展符,我们可以这样写:

computed: {
     attribute1:function(){
    },
     ...mapState([apple,orange])
}

6. vuex Getter

Vuex 允许我们在 store 中定义『getters』(可以认为是 store 的计算属性)。Getters 接受 state 作为其第一个参数:

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

Getters 会暴露为 store.getters 对象:

store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]

Getters 也可以接受其他 getters 作为第二个参数:

getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}
store.getters.doneTodosCount // -> 1

我们可以很容易地在任何组件中使用它:

computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
}

getters的神奇之处就是参数可以有2个,state和getters,所以这就有无限可能。

7. mapGetters 辅助函数

mapGetters 辅助函数仅仅是将 store 中的 getters 映射到局部计算属性:

import { mapGetters } from 'vuex'
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false },
      { id: 3, text: '...', done: true },
   ],
   another:2
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    },
   doneCount:(state,getter){
      return state.another + getters.doneCounts.length
    }
  }
})

export default {
  computed: {
    ...mapGetters([
      'doneTodosCount',
      'doneCount',
      // ...
    ])
  }
}

如果你想将一个 getter 属性另取一个名字,使用对象形式:

mapGetters({
  // 映射 this.doneCount 为 store.getters.doneTodosCount
  doneCount: 'doneTodosCount'
})

8. Mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state,n) {
      // 变更状态
      state.count += n
    }
  }
})

store.commit('increment', 10)

其实我还可以传对象。

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

对象风格的提交方式

store.commit({
  type: 'increment',
  amount: 10
})

当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此 handler 保持不变

接下来知道我要讲什么嘛,没错就是map了。。。

import { mapMutations } from 'vuex'

computed: {
    ...mapGetters([
      'doneTodosCount',
      'count',
    ])
},
methods: {
     ...mapMutations([
        'increment','decrement',
    ]),
     change(){
         this.increment()   == this.store.commit('increment')
         this.doneTodosCount += this.count       
   }

注意执行了increment后count的值发生了变化。

9. vuex Action

Action 类似于 mutation,不同在于:

让我们来注册一个简单的 action:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment ({commit}) {
        commit('increment')
    }
  }
})

乍一眼看上去感觉多此一举,我们直接分发 mutation 岂不更方便?实际上并非如此,还记得 mutation 必须同步执行这个限制么?Action 就不受约束!我们可以在 action 内部执行异步操作:

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

通过store.dispatch('increment')分发。举个例子说吧


import * as types from './mutation-types'

const store = new vex.store({
  mutation:{
     addcart(state, product){
         state.count += product.num
   }
 },
  actions: {
  addToCart ({ commit, state }, product) => {
  if (product.inventory > 0) {
    commit(types.ADD_TO_CART, {
       num: product.num
    })
  }
}

可以用store.dispatch('addToCart',{num:3,name:'fruit'})来分发。
当然这个也有map用法,和前面讲的一样。

组合 Actions

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

store.dispatch('actionA').then(() => {
  // ...
})

对promise不够了解的可以去学一下。

在另外一个 action 中也可以:

actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}

好了,今天讲的东西有点多,下回我会结合实际项目详解vuex的用法。

10.为什么状态管理的mutation必须是同步的呢?

先问,你知道 foreach 传参函数如果是异步的话会怎么样么? 比如 foreach(async () => { await ...})

这种形式想“同步”执行数组中的异步函数是不行的。

再看,vuex 中的mutations 实现:

entry 是某个 mutation 的函数队列数组, 你声明的 mutation 最终都会被 vuex 处理成数组的形式。 对比上面的 foreach 遍历执行异步函数,现在你知道为什么 mutation 需要同步函数了么?

11. localstorage, sessionstorage, vuex的区别和优势

  • Vuex存储在内存,localstorage,sessionstorage本地数据存储。Vuex无内存大小限制,而Storage最大为5M。
  • localStorage(本地存储)则以文件的方式存储在本地,永久保存;可用于页面间数据传递;
  • sessionStorage( 会话存储 ),临时保存, 浏览器或者页面关闭,则sessionStorage被清空;只能用于当前页面,无法在页面间共享。
    vuex用于组件之间的传值,且为响应式数据,可多组件同步更改。
上一篇 下一篇

猜你喜欢

热点阅读