该系列是为了让看过Vue官方文件或学过Vue但是却不知道怎麽下手去重构现在有的网站而去规画的系列文章,在这边整理了许多我自己使用Vue重构很多网站的经验分享给读者们。
今天让我们来聊聊如果使用 Vuex,要如何搭配 composition api 来帮助我们管理重复的逻辑以及抓取 Vuex 资料。
我们先来看看这次的范例要做什麽
这是一个非常简单的网页,有一个会滑入的选单以及滑入的 login 页面,我们看一下专案结构。
|-- src
|-- App.vue
|-- main.js
|-- assets
| |-- bg.jpg
| |-- close.svg
| |-- logo.png
|-- components
| |-- Header.vue
| |-- Login.vue
| |-- SlidMenu.vue
|-- store
| |-- index.js
|-- view
|-- Home.vue
首先是我们的 Vuex 的 store
import { createStore } from "vuex";
export default createStore({
state: {
loginState: false,
menuState: false,
},
actions: {
handleLoginState({ commit }, bool) {
commit("SET_LOGIN_STATE", bool);
},
handleMenuState({ commit }, bool) {
commit("SET_MENU_STATE", bool);
},
},
mutations: {
SET_LOGIN_STATE(state, bool) {
state.loginState = bool;
},
SET_MENU_STATE(state, bool) {
state.menuState = bool;
},
},
getters: {
loginState: (state) => state.loginState,
menuState: (state) => state.menuState,
},
});
在这边我们会需要两个状态,一个控制 Menu、一个控制 login 的开关,然後设定相对应的 acions 以及mutations,取资料我使用 getters。
接下来看一下Header.vue的内容( CSS的部分我就不秀出来了)
Header.vue
<script>
import { computed } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
const MenuState = computed(() => store.getters.menuState);
const LoginState = computed(() => store.getters.loginState);
const handleMenu = () => {
store.dispatch("handleMenuState", !MenuState.value);
};
const handleLogin = () => {
store.dispatch("handleLoginState", !LoginState.value);
};
return {
headleMenu,
headleLogin,
};
},
};
</script>
<template>
<header>
<nav>
<a @click="handleMenu">Menu</a>
<a @click="handleLogin">Login</a>
</nav>
</header>
</template>
这边我定义了两个 function 去对 store dispatch,然後取出 Menu 跟 login 的状态,去做判断,然後塞入dispatch中,绑定@click在两个上,接下来看一下Menu跟Login的部分。
SlidMenu.vue
<script>
import { computed } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
const MenuState = computed(() => store.getters.menuState);
const CloseMenu = () => {
store.dispatch("handleMenuState", false);
};
return { MenuState, CloseMenu };
},
};
</script>
<template>
<div :class="['slid_menu', { active: MenuState }]">
<a class="close" @click="CloseMenu">
<img src="../assets/close.svg" />
</a>
<nav>
<a>ABOTU</a>
<a>ADDRESS</a>
<a>USER</a>
<a>STRENGTH</a>
<!-- 以下省略 -->
</nav>
</div>
</template>
Login.vue
<script>
import { computed } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
const LoginState = computed(() => store.getters.loginState);
return { LoginState };
},
};
</script>
<template>
<div :class="['login', { active: LoginState }]">
<h1>Login Page</h1>
</div>
</template>
我再Menu跟Login身上绑定了一个active的class,如果这个class被add上去了,就会把Menu给滑出来,如果remove掉了,就会收回去,然後Menu加一个function是可以把选单给关闭的。
以上的用法就是一个很典型的Vuex的使用方式,但是你会发现不管是在取得资料,以及操作dispatch的时候,感觉好像可以封装一下,不用写这麽多重复的code,这时候composition api 就派上用场啦!!!
我们先新增一个composition-api的资料夹,然後新增一个 useStateHandle.js
useStateHandle.js
import { computed } from "vue";
import { useStore } from "vuex";
export function useStateHandle() {
const store = useStore();
const loginState = computed(() => store.getters.loginState);
const menuState = computed(() => store.getters.menuState);
const stateHandle = (type, bool) => {
store.dispatch(type, bool);
};
return { loginState, menuState, stateHandle };
}
我们可以在这个 useStateHandle.js 里面使用 computed 跟 getters 的方式取得我们 store 的资料,以及建立一个 function 去执行dispatch ,透过带入的type参数,来决定执行哪个 actions,最後都return 出去。
我们Vuex完全不用改变任何东西,接下来我们来看一下
Header.vue
<script>
import { useStateHandle } from "@/composition-api/useStateHandle.js";
export default {
setup() {
const { loginState, menuState, stateHandle } = useStateHandle();
return {
loginState,
menuState,
stateHandle,
};
},
};
</script>
<template>
<header>
<nav>
<a @click="stateHandle('handleMenuState', !menuState)">Menu</a>
<a @click="stateHandle('handleLoginState', !loginState)">Login</a
</nav>
</header>
</template>
我们可以看到原本写的那些 store 的 code 全部不见了,只剩下我从 useStateHandle
里面取出来的参数,透过我包装好的 stateHandle,我可以带入我想执行的 actions 的名称,然後跟参数,就可以操作执行 Vuex 里面 state。
Login.vue
<script>
import { useStateHandle } from "@/composition-api/useStateHandle.js";
export default {
setup() {
const { loginState } = useStateHandle();
return { loginState };
},
};
</script>
<template>
<div :class="['login', { active: loginState }]">
<h1>Login Page</h1>
</div>
</template>
SlidMenu.vue
<script>
import { useStateHandle } from "@/composition-api/useStateHandle.js";
export default {
setup() {
const { menuState, stateHandle } = useStateHandle();
return { menuState, stateHandle };
},
};
</script>
<template>
<div :class="['slid_menu', { active: menuState }]">
<a class="close" @click="stateHandle('handleMenuState', false)">
<img src="../assets/close.svg" />
</a>
<nav>
<a>ABOTU</a>
<!-- 以下省略 -->
</nav>
</div>
</template>
这样我们就可以减少从 Vuex 取的 state 的重复逻辑,以及我们要执行 actions 的 function,可以说是code少了非常多,我们开发网站的时候常常会有很多这样类型的逻辑是可以封装的,除了今天介绍的以外,还可以封装非同步的处理,也可以去对 scroll 轴或是 resize 等事件进行共用逻辑的抽出,可以说是 composition api 提供了非常大的便利性以及管理方式。
codesandbox 范例 : https://codesandbox.io/s/vue2-vuex-to-vue3-vuex-composition-api-c44cg
有兴趣的朋友可以玩玩看
Ps. 购买的时候请登入或注册该平台的会员,然後再使用下面连结进入网站点击「立即购课」,这样才可以让我获得更多的课程分润,还可以帮助我完成更多丰富的内容给各位。
我有开设了一堂专门针对Vue3从零开始教学的课程,如果你觉得不错的话,可以购买我课程来学习
https://hiskio.com/bundles/9WwPNYRpz?s=tc
那如果对於JS基础不熟的朋友,我也有开设JS的入门课程,可以参考这个课程
https://hiskio.com/bundles/b9Rovqy7z?s=tc
Mike 的 Youtube 频道
Mike的medium
MIke 的官方 line 帐号,好友搜寻 @mike_cheng
>>: Day 06 Flex message simulator- 美化自己的chatbot
大家好! 今天我们要实作解析 JSON 资料,并计算资料的变异数。 我们进入今天的主题吧! 公式 母...
访问控制(RAM)是什麽? 访问控制(Resource Access Management,RAM)...
昨天提到了一个奇怪的现象: byte num = 128; 如上撰写,你的IDE将会在128底下亮出...
昨天我们完成了 user sheet 的 query & upsert 功能,今天就要正式将...
前言 昨天聊到了 TP 告知 main Thread 任务完成的方法。今天说说 TP 本身在运行甚麽...