vuex小结

news/2024/7/7 13:18:51

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

store状态管理

1.认识store

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

  1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

2. store的基本使用——简单的计数器

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <p v-cloak>{{ count }}</p>
    <p>
      <button @click="increment">+</button>
      <button @click="decrement">-</button>
    </p>
  </div>
  <script src="./vue.js"></script>
  <script src="./vuex.js"></script>
  <script>
    const store = new Vuex.Store({
     // 数据(状态)
     // 读取数据:store.state.count
      state: {
        count: 0
      },
      // 用来操作数据的方法
  	  // 修改数据:store.commit('addCount', 参数)
      mutations: {
        increment:state=>state.count++,
        decrement:state=>state.count--
      }
    })
    var vm = new Vue({
      el: '#app',
      computed: {
        count () {
          return store.state.count
        }
      },
      methods: {
        increment () {
          // 触发store.js方法
          store.commit('increment')
        },
        decrement () {
          store.commit('decrement')
        }
      }
    })
  </script>
</body>
</html>

再次强调,我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。

由于 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性中返回即可。触发变化也仅仅是在组件的 methods 中提交 mutation。

核心概念

1.State

单一状态树

Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。

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

获取state的方法:

在组件中获取state==> this.$store.state.count

在主页面中获取state==> store.state.count

2.Getter

有时候我们需要从 store 中的 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)
    }
  }
})
var vm = new Vue({
      el: '#app',
      computed: {
        doneTodosCount () {
          return store.getters.doneTodos
        }
      },
      created(){
        console.log(this.doneTodosCount)
        // 返回的是todos数组中对象done为true的项
      }
    })

3.Mutation

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

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

你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

store.commit('increment')

Mutation 必须是同步函数

一条重要的原则就是要记住 mutation 必须是同步函数。为什么?请参考下面的例子:

mutations: {

  someMutation (state) {

    api.callAsyncMethod(() => {

      state.count++

    })

  }

}

现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。

提交载荷

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

4.Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。

  • Action 可以包含任意异步操作

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

    Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.statecontext.getters 来获取 state 和 getters。当我们在之后介绍到 Modules时,你就知道 context 对象为什么不是 store 实例本身了。

    分发 Action

    Action 通过 store.dispatch 方法触发:

    store.dispatch('increment')
    
    

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

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

5.Module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

// store.state.a // -> moduleA 的状态
// store.state.b // -> moduleB 的状态

var vm = new Vue({
      el: '#app',
      computed: {
        count(){
          return store.state.a.count;
        },
        doneTodosCount () {
          // return store.getters.doubleCount;
          return store.state.a.count;
        }
      },
      methods:{
        increment () {
          // 触发store.js方法
          store.commit('increment')
        },
        decrement () {
          store.commit('decrement')
        }
      },
      created(){
        console.log(this.doneTodosCount)
      }
    })

注意:

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。

所以action、mutation 和 getter名称不可重复

转载于:https://my.oschina.net/shuaihong/blog/1604438


http://www.niftyadmin.cn/n/3615959.html

相关文章

基于Java语言编写的数据库中间件Mycat

一个新颖的数据库中间件产品支持mysql集群&#xff0c;或者mariadb cluster&#xff0c;提供高可用性数据分片集群。基于Java语言编写的数据库中间件 什么是MyCat MyCat是一个开源的分布式数据库系统&#xff0c;是一个实现了MySQL协议的服务器&#xff0c;前端用户可以把它看…

git命令行操作详解

目录 1.常用操作1.1 新建代码库1.2 配置1.3 remote管理1.4 添加和撤销操作1.5 代码提交1.6 分支操作1.7 查看信息1.8 pull操作1.9 push操作1.10 tag操作2. 其他一些汇总2.1 github上初始一个项目2.2 重命名远程分支&#xff08;先删除远程分支&#xff0c;重命名本地分支&#…

Linux(Centos7)系统安装Python3.6.8教程

大坑&#xff1a; 系统自带的python2不要卸载&#xff0c;一些系统命令要用&#xff0c;2和3可以共存。 linux中Python3.6.8安装 [rootmaster ~]# cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) 1、首先要查看系统中有没有自带的gcc gcc --version2、通过wg…

LNMP架构(六)之php-fpm,慢执行日志,open_basedir,php-fpm进程管理

2019独角兽企业重金招聘Python工程师标准>>> Php-fpm的pool vim /usr/local/php/etc/php-fpm.conf//在[global]部分增加 include etc/php-fpm.d/*.confvim /usr/local/php/etc/php-fpm.conf//在[global]部分增加 include etc/php-fpm.d/*.conf //这里没有安装的ph…

Docker网络模式说明

现在的Docker版本不推荐继续使用Link了&#xff0c;而是推荐用网络模式解决问题&#xff0c;简单讲一下最常用的几个网络模式&#xff0c;其他我用到时候再补充。 bridge -net不加参数就是默认的bridge模式&#xff0c;这个默认bridge模式下&#xff0c;容器会连接到默认网桥do…

TCC细读 - 2 核心实现

TCC&#xff0c;基于业务层面的事物定义&#xff0c;粒度完全由业务自己控制&#xff0c;本质上还是补偿的思路&#xff0c;它把事物运行过程分为try-confirm-cancel阶段&#xff0c;每个阶段逻辑由业务代码控制 业务活动管理器控制业务活动的一致性&#xff0c;它登记业务活动…

Linux安装Anaconda3及Conda创建虚拟环境

在进行Python开发的时候我们无可避免的使用Anaconda这一集成工具&#xff0c;但是在安装的时候我们我们需要明确很多注意点&#xff0c;才能放心的将我们的Python Module交给它来管理&#xff01; Anaconda是一个开源的包、环境管理器&#xff0c;可以用于在同一个机器上安装不…

工作中任务管理的四个原则和四个技能

工作中任务管理的四个原则和四个技能 这是前一阵给团队培训&#xff0c;提高团队工作绩效时写的。 四个原则&#xff1a; l 瓶颈性任务最优先解决原则 l 高不确定性的任务优先解决原则 l 前置性原则 l 复杂多变任务的处理原则 瓶颈性任务最优先解决原则 比如说&#xff0c;上面…