这周要来介绍一个很好用的套件 - Vuex
看到名称应该马上可以理解他就是Vue专案在使用的套件吧xD
有看过我之前的专案开发的文章的人,应该会发现我从来没有用过 Vuex
我也是最近这两周才开始接触它的~
趁着记忆犹新时赶快把它写起来~
如果有使用不当或是有误的地方再麻烦多指教
万用起手式来了~
所谓的Vuex是什麽呢? 他可以做到哪些事呢?
官方是这麽介绍它的:
Vuex是一个专为Vue.js应用程序开发的状态管理模式。
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex也集成到Vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能。
blablabla...
当时看完这段介绍之後我还是不知道Vuex是在做什麽xD
没关系我们继续往下看:
每一个Vuex应用的核心就是store(仓库)。
“store”基本上就是一个容器,它包含着你的应用中大部分的状态(state)。
到这边应该稍微可以理解原来它的用途是「管理资料状态的容器」
原本的做法就可以在每个元件中存放资料了,那为什麽还要用Vuex呢?
通常我们的资料流向会是父传子,上层传至下层,保持数据单向流通
遇到需要从子层改变父层资料时可以使用 $emit()
呼叫父层方法进而改变数据
遇到兄弟同层之间的元件要互相影响时就会有困难了,我自己的做法是将资料放到父层再用父传子的方式处理
但是不论父传子还是兄弟互传的做法都非常的麻烦且繁琐
这时候Vuex就出现了!!
我们可以将需要用到传递的资料通通丢进Vuex管理
当元件需要使用资料时,可以使用 $store
轻松取得数据
且透过套件提供的 dispatch
方法,可以从任何元件去改变资料数据
那传递呢? 当然用不到罗~
透过Vuex我们可以把传递的方式取代掉,并且还是保持着资料数据单向流通
刚才有看到官方文件说「Vuex应用的核心就是store」
而 Store 就是存放资料状态的容器
那这个容器内包含着哪些东西呢?
以上四个项目会是基本常使用到的,其他还有像是
在数据流向的部分
前端元件(component)会透过 ditpatch
呼叫 actions 方法
actions 再透过提交(commit)的方式呼叫 mutations
mutations 再做更新 state 中的资料状态的动作
state 更新後再将数据渲染到元件中
透过这个流程达到单向数据流的操作
基本介绍之後,就先来安装它吧~
这里以使用 Vue Cli 专案为主来说明
使用npm安装指令:
npm install vuex --save
官方还有提供其他方式如:
yarn add vuex
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>
安装完成之後来建立一个最简单的Store罗~
在专案下新增一个 /store 资料夹,资料夹内再新增一个 index.js 档:
src
└── store
└── index.js
开启刚刚建立的 index.js 加入基本的程序码:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
msg: "Hello Vuex!!"
},
});
在 main.js 中引用:
import store from './store'
store 要加进vue喔!!
new Vue({
...,
store,
}).$mount('#app')
上面步骤都完成之後可以来到元件中去抓看看 msg 罗~
在元件的 computed 中使用 $store.state
来取得资料数据,可以在 App.vue 中试试看是否能抓到并渲染在画面上:
//App.vue
<template>
<div>
{{ myMsg }}
</div>
</template>
<script>
export default {
name: "App",
computed: {
myMsg() {
return this.$store.state.msg;
},
},
};
基本的 Store 就建立完成罗!!
接着我会用不包含任何功能的TodoList来介绍後面的操作
像刚才 msg 一样,我们在 Store 中建一个TodoList:
export default new Vuex.Store({
state: {
todolist: [
{ id: 1, todo: "交女朋友", done: false },
{ id: 2, todo: "财务自由", done: false },
{ id: 3, todo: "当码农", done: true },
],
},
});
在 App.vue 中抓值并渲染:
<template>
<div>
<ul>
<li v-for="item in myTodo" :key="item.id">
{{ item.todo }} - {{ item.done ? "已完成" : "未完成" }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: "App",
computed: {
myTodo() {
return this.$store.state.todolist;
},
},
};
</script>
出来的画面长这样:
前置作业完成了,再来我要加上click事件来切换 [已完成] 及 [未完成] 的状态:
<li
...
@click="todoDone(item.id, !item.done)"
>
...
</li>
对应的 todoDone() 方法:
methods: {
//id: 要修改状态的资料唯一码
//done: 要修改的值
todoDone(id, done) {
},
},
再来很重要(应该从头到尾都很重要xD)
我们要使用 dispatch
来呼叫 actions
第一个参数设定要呼叫的 actions 名称
第二个参数设定要传入的值,有多个值的话就用物件的方式带入
假设要呼叫的 actions 名称也叫 todoDone,并且将 id & done 传进去:
todoDone(id, done) {
this.$store.dispatch("todoDone", { id, done });
},
回到 /store/index.js 加入 todoDone():
actions: {
todoDone(context, { id, done }) {
},
},
说明一下 actions 的参数结构,每个 actions 会有带两个参数: myActions(context, payload)
Action函数接受一个与store实例具有相同方法和属性的context对象,因此你可以调用context.commit提交一个mutation,或者通过context.state和context.getters来获取state和getters。
我们在 context 中可以使用这些属性:
{
state, // 等同於`store.state`,若在模块中则为局部状态
rootState, // 等同於`store.state`,只存在於模块中
commit, // 等同於`store.commit`
dispatch , // 等同於`store.dispatch`
getters, // 等同於`store.getters`
rootGetters // 等同於`store.getters`,只存在於模块中
}
接着我们可以在 actions 中使用 commit
将要修改的数据提交给 mutations 来更新:
todoDone(context, { id, done }) {
context.commit('TODOLIST', { id, done });
},
第一个参数设定要提交给哪个 mutations 的名称
第二个参数设定要传入的值,有多个值的话就用物件的方式带入
通常actions会有一些资料面的逻辑处理,例如呼叫ajax等等,逻辑处理结束後才会提交到mutations
但范例中因为没有这层,所以看起来像是多做了一个没有用的动作
接着可以加入 mutations:
mutations: {
TODOLIST(state, { id, done }) {
},
}
这边使用了常量替代Mutation 事件类型:
使用常量替代mutation 事件类型在各种Flux 实现中是很常见的模式。这样可以使linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个app 包含的mutation 一目了然
用不用常量取决於你——在需要多人协作的大型项目中,这会很有帮助。但如果你不喜欢,你完全可以不这样做。
说明一下 mutations 的参数结构,每个 mutations 会有带两个参数: myMutations(state, payload)
最後就是更新资料状态
先抓到 state 中的 todolist:
let todolist = state.todolist;
使用阵列的 find()
方法抓到要改的那笔:
let todo = todolist.find((item) => {
return item.id === id;
});
更新 done 值:
todo.done = done;
整段会是这样:
TODOLIST(state, { id, done }) {
let todolist = state.todolist;
let todo = todolist.find((item) => {
return item.id === id;
});
todo.done = done;
},
也可以合并成这样:
TODOLIST(state, { id, done }) {
state.todolist.find((item) => {
return item.id === id
}).done = done;
},
到这里就完成更新资料状态罗!!
来看看结果吧~
先到这罗~
下周继续来探讨模组化以及其他的功能!!
<<: [Golang]同步工具-sync包的Wait、Signal、Broadcast方法说明-心智图总结
CDN 这个名词在前面的篇章应该出现过蛮多次的,一直感到困惑的朋友们不用担心,今天终於要来好好介绍...
今天延续之前的主题,我们将使用EfficientNetB0的架构,但不使用预训练权重,参考了Kera...
有人说作为新手不好理解,我觉得蛮正常的,一来我中文其实不好,二来要理解新概念只用看的其实不够,最好是...
Vue 由前 Google 工程师尤雨溪在 2014 年 2 月所建立的一套开放源码(Open So...
今天我们来把前面做的五张工作表合成一张仪表板吧! 首先新增一张仪表板,名称为「107年6月_台湾各姓...