先写仓库地址:https://gitee.com/orderkk/vuex-vue3.0-ts.git
项目目录介绍:
目录介绍:
assets: 存放静态文件资源
components: 存放组件文件
hooks: 剥离了项目中的methods, 封装了一些基本方法
store:vuex存放的目录
typings: 存放typescript interface的目录
粘贴部分代码:
// @/store/index.ts
import { createStore } from 'vuex'
import state from './state'
import mutations from './mutations'
import actions from './actions'
export default createStore({
state,
mutations,
actions,
modules: {
}
})
// @/store/actions.ts
import { IState, ITodo } from "@/typings";
import { Commit } from "vuex";
import { REMOVE_TODO, SET_DOING, SET_STATUS, SET_TODO, SET_TODO_LIST } from "./actionTypes";
interface ICtx {
commit: Commit,
state: IState
}
export default {
[SET_TODO]({ commit }: ICtx, todo: ITodo): void {
commit(SET_TODO, todo)
},
[SET_TODO_LIST]({ commit }: ICtx, todoList: ITodo[]): void {
commit(SET_TODO_LIST, todoList)
},
[REMOVE_TODO]({ commit }: ICtx, id: number): void {
commit(REMOVE_TODO, id)
},
[SET_STATUS]({ commit }: ICtx, id: number): void {
commit(SET_STATUS, id)
},
[SET_DOING]({ commit }: ICtx, id: number): void {
commit(SET_DOING, id)
}
}Ï
// @/store/actionTypes.ts
export const SET_TODO: string = 'SET_TODO'
export const SET_TODO_LIST: string = 'SET_TODO_LIST'
export const REMOVE_TODO: string = 'REMOVE_TODO'
export const SET_STATUS: string = 'SET_STATUS'
export const SET_DOING: string = 'SET_DOING'
// @/store/mutations.ts
import { IState, ITodo, TODO_STATUS } from "@/typings";
import { REMOVE_TODO, SET_DOING, SET_STATUS, SET_TODO, SET_TODO_LIST } from "./actionTypes";
export default {
[SET_TODO](state: IState, todo: ITodo): void {
state.list = [todo, ...state.list]
},
[SET_TODO_LIST](state: IState, todoList: ITodo[]): void {
state.list = todoList
},
[REMOVE_TODO](state: IState, id: number) {
state.list = state.list.filter((item: ITodo) => item.id != id)
},
[SET_STATUS](state: IState, id: number) {
state.list = state.list.map((item: ITodo) => {
if (item.id === id) {
switch (item.status) {
case TODO_STATUS.FINISHED:
item.status = TODO_STATUS.WILLDO
break;
case TODO_STATUS.WILLDO:
item.status = TODO_STATUS.FINISHED
break;
case TODO_STATUS.DOING:
item.status = TODO_STATUS.FINISHED
break;
default:
break;
}
}
return item
})
},
[SET_DOING](state: IState, id: number) {
state.list = state.list.map((item: ITodo) => {
if (item.id != id) {
if (item.status === TODO_STATUS.DOING) {
item.status = TODO_STATUS.WILLDO
}
} else {
item.status = item.status === TODO_STATUS.WILLDO ? TODO_STATUS.DOING : TODO_STATUS.WILLDO
}
return item
})
}
}
// @/store/state.ts
import { IState } from "@/typings";
export default <IState>{
list: []
}
// @/typings/index.ts
enum TODO_STATUS {
FINISHED = 'finished',
WILLDO = 'willdo',
DOING = 'doing'
}
interface ITodo {
id: number,
content: string,
status: TODO_STATUS
}
interface IState {
list: ITodo[]
}
export {
TODO_STATUS,
ITodo,
IState
}
// @/App.vue
<template>
<div class="wrapper">
<todo-input />
<todo-list :todoLists="todoLists" />
</div>
</template>
<script lang="ts">
import { computed, defineComponent, onMounted } from "vue";
import TodoList from "./components/TodoList/Index.vue";
import TodoInput from "./components/TodoInput/Index.vue";
import { IUseTodo, useTodo } from "./hooks";
import { Store, useStore } from "vuex";
export default defineComponent({
name: "App",
components: {
TodoList,
TodoInput,
},
setup() {
const { setTodoList }: IUseTodo = useTodo();
const store: Store<any> = useStore();
onMounted(() => {
setTodoList();
});
return {
todoLists: computed(() => {
return store.state.list;
}),
};
},
});
</script>
// @/hooks/index.ts
import { REMOVE_TODO, SET_DOING, SET_STATUS, SET_TODO, SET_TODO_LIST } from "@/store/actionTypes"
import { ITodo, TODO_STATUS } from "@/typings"
import { watch } from "vue"
import { Store, useStore } from "vuex"
interface IUseTodo {
setTodo: (value: string) => void,
setTodoList: () => void,
removeTodo: (id: number) => void,
setStatus: (id: number) => void,
setDoing: (id: number) => void
}
interface IUseLocalStorage {
getLocalList: () => ITodo[]
setLocalList: (todolist: ITodo[]) => void
}
function useLocalStorage(): IUseLocalStorage {
function getLocalList(): ITodo[] {
return JSON.parse(localStorage.getItem('todolist') || '[]')
}
function setLocalList(todolist: ITodo[]): void {
localStorage.setItem('todolist', JSON.stringify(todolist))
}
return {
getLocalList,
setLocalList
}
}
function useTodo(): IUseTodo {
const store: Store<any> = useStore();
const { getLocalList, setLocalList }: IUseLocalStorage = useLocalStorage();
const todolist: ITodo[] = getLocalList()
watch(() => {
return store.state.list
}, (todolist) => {
setLocalList(todolist)
})
function setTodo(value: string): void {
const todo: ITodo = {
id: Date.now(),
content: value,
status: TODO_STATUS.WILLDO
}
store.dispatch(SET_TODO, todo)
// setLocalList(store.state.list)
}
function setTodoList(): void {
store.dispatch(SET_TODO_LIST, todolist)
}
function removeTodo(id: number): void {
store.dispatch(REMOVE_TODO, id)
// setLocalList(store.state.list)
}
function setStatus(id: number): void {
store.dispatch(SET_STATUS, id)
// setLocalList(store.state.list)
}
function setDoing(id: number): void {
store.dispatch(SET_DOING, id)
// setLocalList(store.state.list)
}
return {
setTodo,
setTodoList,
removeTodo,
setStatus,
setDoing
}
}
export {
IUseTodo,
useTodo,
useLocalStorage
}
// @/components/TodoInput/Index.vue
<template>
<div>
<input type="text" v-model="todoValue" @keyup.enter="setTodoValue" />
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, ref } from "vue";
import { useTodo, IUseTodo } from "../../hooks/index";
export default defineComponent({
name: "TodoInput",
setup() {
let todoValue = ref<string>("");
const { setTodo }: IUseTodo = useTodo();
const setTodoValue = (e: KeyboardEvent): void => {
setTodo(todoValue.value);
todoValue.value = "";
};
return {
todoValue,
setTodoValue,
};
},
});
</script>
// @/components/TodoList/Index.vue
<template>
<div>
<h1>todo-list</h1>
<todo-item
v-for="item in todoLists"
:key="item.key"
:item="item"
@removeTodo="removeTodo"
@setStatus="setStatus"
@setDoing="setDoing"
/>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, PropType } from "vue";
import TodoItem from "./Item.vue";
import { ITodo } from "../../typings/index";
import { IUseTodo, useTodo } from "../../hooks";
export default defineComponent({
name: "TodoList",
props: {
todoLists: Array as PropType<ITodo[]>,
},
components: {
TodoItem,
},
setup(props, { emit }) {
const { removeTodo, setStatus, setDoing }: IUseTodo = useTodo();
return {
removeTodo,
setStatus,
setDoing,
};
},
});
</script>
// @/components/TodoList/Item.vue
<template>
<div>
<input
type="checkbox"
:checked="item.status === FINISHED"
@click="setStatus(item.id)"
/>
<span :class="item.status === FINISHED ? 'line-thoungth' : ''">
{{ item.content }}
</span>
<button @click="removeTodo(item.id)">删除</button>
<button
v-if="item.status != FINISHED"
@click="setDoing(item.id)"
:class="item.status === DOING ? 'doing' : 'willdo'"
>
{{ item.status === DOING ? "正在做..." : "马上做..." }}
</button>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue";
import { ITodo, TODO_STATUS } from "../../typings";
interface IStatusState {
DOING: TODO_STATUS;
WILLDO: TODO_STATUS;
FINISHED: TODO_STATUS;
}
export default defineComponent({
name: "TodoItem",
props: {
item: Object as PropType<ITodo>,
},
setup(props, { emit }) {
const statusState: IStatusState = {
DOING: TODO_STATUS.DOING,
WILLDO: TODO_STATUS.WILLDO,
FINISHED: TODO_STATUS.FINISHED,
};
const removeTodo = (id: number): void => {
emit("removeTodo", id);
};
const setStatus = (id: number): void => {
emit("setStatus", id);
};
const setDoing = (id: number): void => {
emit("setDoing", id);
};
return {
...statusState,
removeTodo,
setStatus,
setDoing,
};
},
});
</script>
<style scoped>
.line-thoungth {
text-decoration: line-through;
}
.doing {
background-color: #cdcdcd;
color: red;
}
.willdo {
background-color: orange;
color: #fff;
}
</style>
// @/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
createApp(App).use(store).mount('#app')