做者:Anthony Gore
译者:前端小智
来源:vuejsdevelopers
有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。前端
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及个人系列文章。vue
Vuex
是 Vue.js 生态系统中必不可少的工具。可是新接触 Vuex 的开发人员可能会被诸如“状态管理模式”这样的术语所排斥,而且对他们实际须要Vuex的目的感到困惑。git
本文算是 Vuex的入门,固然也会 Vuex 的高级概念,并向你们展现如何在应用程序中使用 Vuex。github
要理解Vuex,首先要理解它要解决的问题。面试
假设咱们开发了一个多用户聊天应用。界面有用户列表、私人聊天窗口、带有聊天记录的收件箱和通知栏,通知用户当前未查看的其余用户的未读消息。vuex
数以百万计的用户天天经过咱们的应用与数以百万计的其余用户聊天。然而,有人抱怨一个恼人的问题:通知栏偶尔会给出错误的通知。用户被通知有一条新的未读消息,但当他们查看时,它只是一条已经被看过的消息。npm
该做者所描述的是几年前 Facebook 开发人员在其聊天系统中遇到的真实状况。 解决这一问题的过程当中 开发人员建立名为 "Flux"的应用程序体系结构。 Flux 构成了Vuex,Redux 和其它相似库的基础。设计模式
Facebook开发者为“僵尸通知”这个问题,苦苦挣扎了一段时间。他们最终意识到,它的持久性不只仅是一个简单的缺陷——它指出了应用程序架构中的一些潜在缺陷。数组
抽象中最容易理解该缺陷:当应用程序中有多个共享数据的组件时,它们互连的复杂性将增长到没法预测或理解数据状态的地步。 所以,该应用程序没法扩展或维护。微信
Flux
是一个模式,不是一个库。咱们不能去Github下载 Flux。它是一种相似MVC的设计模式。像Vuex和Redux这样的库实现Flux模式的方式与其余框架实现MVC模式的方式相同。
事实上,Vuex并无实现Flux的所有,只是一个子集。不过如今不要担忧这个问题,咱们关注于理解它所遵循的关键原则。
组件可能具备仅须要了解的本地数据。 例如,滚动条在用户列表组件中的位置可能与其余组件无关。
可是,要在组件之间共享的任何数据(即应用程序数据)都必须保存在一个单独的位置,与使用它的组件分开。
这个单一位置称为 "store"。 组件必须从该位置读取应用程序数据,而且不能保留其本身的副本以防止冲突或分歧。
import { createStore } from "vuex"; // Instantiate our Vuex store const store = createStore({ // "State" 组件的应用程序数据 state () { return { myValue: 0 }; } }); // 组件从其计算的属性访问 state const MyComponent = { template: "<div>{{ myValue }}</div>", computed: { myValue () { return store.state.myValue; } } };
组件能够从store
中自由读取数据。 可是不能更改 store
中的数据,至少不能直接更改。
取而代之的是,它们必须告知 store
要更改数据的意图,store
由负责经过一组定义的功能(称为mutation
)进行更改。
为何采用这种方法? 若是咱们集中数据更改逻辑,那么在状态不一致的状况下,咱们只须要在同一地方排查就好了,不用到具体的每一个文件中。 咱们将某些随机组件(可能在第三方模块中)以意外方式更改数据的可能性降至最低。
const store = createStore({ state() { return { myValue: 0 }; }, mutations: { increment (state, value) { state.myValue += value; } } }); // 须要更新值吗? // 错误的,不要直接更改 store 值 store.myValue += 10; // 正确的,调用正确的 mutations。 store.commit('increment', 10);
若是应用程序在其体系结构中实现了上述两个原则,那么调试数据不一致就容易得多。能够记录提交并观察状态如何变化(在使用Vue Devtools 时确实能够这样作)。
但若是咱们的mutation
被异步调用,这种能力就会被削弱。咱们知道提交的顺序,但咱们不知道组件提交它们的顺序。
同步mutation
可确保状态不取决于不可预测事件的顺序和时间。
有了全部这些背景知识,咱们终于能够解决这个问题-Vuex 是一个库,可帮助咱们在Vue应用程序中实现Flux架构。 经过执行上述原则,即便在多个组件之间共享数据时,Vuex 仍可将咱们的应用程序数据保持在透明且可预测的状态。
如今,咱们已经对Vuex有了一个高级的了解,咱们看看如何在实际项目建立基于Vuex的应用程序。
为了演示Vuex的用法,咱们设置一个简单的待办应用程序。 你们能够在此处访问代码的有效示例。
示例地址:https://codesandbox.io/s/happ...
若是你们本身的电脑尝试一波,那么可使用下面的命令:
vue create vuex-example
cd vuex-example npm i -S vuex@4 npm run serve
如今,建立 Vuex store,在项目中建立 src/store/index.js
:
mkdir src/store touch src/store/index.js
打开文件并导入createStore
方法。此方法用于定义store
及其特性。如今,咱们导出该store
,以便在Vue应用中能访问它。
// src/store/index.js import { createStore } from "vuex"; export default createStore({});
为了能够从任何组件中访问 Vuex store,咱们须要在主文件中导入 store
模块,并将store
做为插件安装在主Vue实例上
// src/main.js import { createApp } from "vue"; import App from "@/App"; import store from "@/store"; const app = createApp(App); app.use(store); app.mount("#app");
如上所述,Vuex 的重点是一般在大型应用程序中建立可扩展的全局状态。 可是,咱们能够在一个简单的待办应用程序中演示其功能。
完成后效果以下所示:
如今,删除 HelloWorld 文件:
rm src/components/HelloWorld.vue
如今,添加一个新组件 TodoNew
,它负责建立新的待办事项。
touch src/components/TodoNew.vue
打开 TodoNew.vue
并输入如下内容:
// src/components/TodoNew.vue <template> <form @submit.prevent="addTodo"> <input type="text" placeholder="Enter a new task" v-model="task" /> </form> </template>
如今转到组件定义,有两个局部状态属性-task
和给新待办事项提供惟一标识符的id
。
// src/components/TodoNew.vue <template>...</template> <script> export default { data() { return { task: "", id: 0 }; }, methods: { addTodo: function() { // } } }; </script>
过会,咱们会建立一个显示待办事项的组件。 因为它和TodoNew
组件都须要访问相同的数据,所以这是咱们在 Vuex 存储中保存的全局state
的理想选择。
如今,回到state
并定义属性状态。 这里使用 Vux4 提供的 createStore
函数,该函数返回一个对象。 该对象具备一个属性 todos
,它是一个空数组。
// src/store/index.js import { createStore } from "vuex"; export default createStore({ state () { return { todos: [] } } });
从原则2能够知道,Vuex state 不能直接更改,须要定义mutator
函数。
如今,咱们向store
添加一个mutation
属性,并添加一个函数属性addTodo
。 全部mutator
方法第一个参数。 第二个可选参数是 store,第二个是传递的数据。
// src/store/index.js import { createStore } from "vuex"; export default createStore({ state () { return { todos: [] } }, mutations: { addTodo (state, item) { state.todos.unshift(item); } } });
mutation
如今,能够在TodoNew
组件中使用它,在 TodoNew
组件定义一个addTodo
方法。
要访问store
,咱们可使用全局属性this.$store
。 使用commit
方法建立一个新的mutation
。 须要传递了两个参数-首先是mutation
的名称,其次是咱们要传递的对象,是一个新的待办事项(由id
和task
值组成)。
// src/components/TodoNew.vue methods: { addTodo: function() { const { id, task } = this; this.$store.commit("addTodo", { id, task }); this.id++; this.task = ""; } }
到目前为止:
task
变量。addTodo
方法store
中。// src/components/TodoNew.vue <template> <form @submit.prevent="addTodo"> <input type="text" placeholder="Enter a new task" v-model="task" /> </form> </template> <script> export default { data() { return { task: "", id: 0 }; }, methods: { addTodo: function() { const { id, task } = this; this.$store.commit("addTodo", { id, task }); this.id++; this.task = ""; } } }; </script>
如今,咱们已经建立了用于添加待办事项的功能。 接下来,就是把它们显示出来。
建立一个新组件TodoList.vue
文件。
touch src/components/TodoList.vue
内容以下:
// src/components/TodoList.vue <template> <ul> <li v-for="todo in todos" :key="todo.id" > {{ todo.description }} </li> </ul> </template>
todos
是一个计算属性,咱们在其中返回Vuex store 的内容。
// src/components/TodoList.vue <script> export default { computed: { todos() { // } } }; </script>
与直接访问store
内容不一样,getter
是相似于存储的计算属性的函数。在将数据返回到应用程序以前,这些工具很是适合过滤或转换数据。
例如,下面有getTodos
,它返回未过滤的状态。 在许多状况下,可使用filter
或map
来转换此内容。
todoCount
返回todo
数组的长度。
经过确保组件愿意保留数据的本地副本,getter
有助于实现原则1,即单一数据来源。
// src/store/index.js export default createStore({ ... getters: { getTodos (state) { return state.todos; }, todoCount (state) { return state.todos.length; } } })
返回TodoList
组件,咱们经过返回this.$store.getters.getTodos
来完成功能。
// src/components/TodoList.vue <script> export default { computed: { todos() { return this.$store.getters.getTodos; } } }; </script>
App.vue
要完成此应用程序,如今要作的就是导入并在App.vue
中声明咱们的组件。
// src/App.vue <template> <div> <h1>To-Do List</h1> <div> <TodoNew /> <TodoList /> </div> </div> </template> <script> import TodoNew from "@/components/TodoNew.vue"; import TodoList from "@/components/TodoList.vue"; export default { components: { TodoNew, TodoList } }; </script>
显然,在大型应用程序中,拥有全局状态管理解决方案将有助于让咱们的应用程序可预测和可维护。
但对于比较小的项目,有时候以为使用 Vuex 太大材小用了,还这个仍是你们跟着实际需求走比较合理。
Vuex的优势:
Vuex的缺点:
~ 完, 我是刷碗智,刷碗去咯,下期见!
原文:https://vuejsdevelopers.com/2...
代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug。
有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收录,有一线大厂面试完整考点、资料以及个人系列文章。