1、第一步:安装
npm install vuex --save
2、main.ts引入
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
// import { createStore } from 'vuex'
import Home from "./views/Home.vue"
import Login from "./views/Login.vue"
import ColumnDetail from "./views/ColumnDetail.vue"
import store from './store' 引入
import App from './App.vue'
const app = createApp(App)
app.use(router)
app.use(store) // 使用
app.mount('#app')
3、store.ts
import { createStore, Commit } from 'vuex'
import axios, { AxiosRequestConfig } from 'axios'
import { arrToObj, objToArr } from './helper'
export interface ResponseType<P = {}> {
code: number;
msg: string;
data: P;
}
export interface UserProps {
isLogin: boolean;
nickName?: string;
_id?: string;
column?: string;
email?: string;
avatar?: ImageProps;
description?: string;
}
export interface ImageProps {
_id?: string;
url?: string;
createdAt?: string;
fitUrl?: string;
}
export interface ColumnProps {
_id: string;
title: string;
avatar?: ImageProps;
description: string;
}
export interface PostProps {
_id?: string;
title: string;
excerpt?: string;
content?: string;
image?: ImageProps | string;
createdAt?: string;
column: string;
author?: string | UserProps;
isHTML?: boolean;
}
interface ListProps<P> {
[id: string]: P;
}
export interface GlobalErrorProps {
status: boolean;
message?: string;
}
export interface GlobalDataProps {
token: string;
error: GlobalErrorProps;
loading: boolean;
columns: { data: ListProps<ColumnProps>; currentPage: number; total: number };
posts: { data: ListProps<PostProps>; loadedColumns: string[] };
user: UserProps;
}
const asyncAndCommit = async(url: string, mutationName: string,
commit: Commit, config: AxiosRequestConfig = { method: 'get' }, extraData?: any) => {
const { data } = await axios(url, config)
if (extraData) {
commit(mutationName, { data, extraData })
} else {
commit(mutationName, data)
}
return data
}
const store = createStore<GlobalDataProps>({
state: {
token: localStorage.getItem('token') || '',
error: { status: false },
loading: false,
columns: { data: {}, currentPage: 0, total: 0 },
posts: { data: {}, loadedColumns: [] },
user: { isLogin: false }
},
mutations: {
// login(state) {
// state.user = { ...state.user, isLogin: true, name: 'viking' }
// },
createPost(state, newPost) {
state.posts.data[newPost._id] = newPost
},
fetchColumns(state, rawData) {
const { data } = state.columns
const { list, count, currentPage } = rawData.data
state.columns = {
data: { ...data, ...arrToObj(list) },
total: count,
currentPage: currentPage * 1
}
},
fetchColumn(state, rawData) {
state.columns.data[rawData.data._id] = rawData.data
},
fetchPosts(state, { data: rawData, extraData: columnId }) {
state.posts.data = { ...state.posts.data, ...arrToObj(rawData.data.list) }
state.posts.loadedColumns.push(columnId)
},
fetchPost(state, rawData) {
state.posts.data[rawData.data._id] = rawData.data
},
deletePost(state, { data }) {
delete state.posts.data[data._id]
},
updatePost(state, { data }) {
state.posts.data[data._id] = data
},
setLoading(state, status) {
state.loading = status
},
setError(state, e: GlobalErrorProps) {
state.error = e
},
fetchCurrentUser(state, rawData) {
state.user = { isLogin: true, ...rawData.data }
},
login(state, rawData) {
const { token } = rawData.data
state.token = token
localStorage.setItem('token', token)
axios.defaults.headers.common.Authorization = `Bearer ${token}`
},
logout(state) {
state.token = ''
state.user = { isLogin: false }
localStorage.remove('token')
delete axios.defaults.headers.common.Authorization
}
},
actions: {
fetchColumns({ state, commit }, params = {}) {
const { currentPage = 1, pageSize = 6 } = params
// if (!state.columns.isLoaded) {
// return asyncAndCommit('/columns', 'fetchColumns', commit)
// }
if (state.columns.currentPage < currentPage) {
return asyncAndCommit(`/columns?currentPage=${currentPage}&pageSize=${pageSize}`, 'fetchColumns', commit)
}
},
fetchColumn({ state, commit }, cid) {
if (!state.columns.data[cid]) {
return asyncAndCommit(`/columns/${cid}`, 'fetchColumn', commit)
}
},
fetchPosts({ state, commit }, cid) {
if (!state.posts.loadedColumns.includes(cid)) {
return asyncAndCommit(`/columns/${cid}/posts`, 'fetchPosts', commit, { method: 'get' }, cid)
}
},
fetchPost({ state, commit }, id) {
const currentPost = state.posts.data[id]
if (!currentPost || !currentPost.content) {
return asyncAndCommit(`/posts/${id}`, 'fetchPost', commit)
} else {
return Promise.resolve({ data: currentPost })
}
},
updatePost({ commit }, { id, payload }) {
return asyncAndCommit(`/posts/${id}`, 'updatePost', commit, {
method: 'patch',
data: payload
})
},
fetchCurrentUser({ commit }) {
return asyncAndCommit('/user/current', 'fetchCurrentUser', commit)
},
login({ commit }, payload) {
return asyncAndCommit('/user/login', 'login', commit, { method: 'post', data: payload })
},
createPost({ commit }, payload) {
return asyncAndCommit('/posts', 'createPost', commit, { method: 'post', data: payload })
},
deletePost({ commit }, id) {
return asyncAndCommit(`/posts/${id}`, 'deletePost', commit, { method: 'delete' })
},
loginAndFetch({ dispatch }, loginData) {
return dispatch('login', loginData).then(() => {
return dispatch('fetchCurrentUser')
})
}
},
getters: {
getColumns: (state) => {
return objToArr(state.columns.data)
},
getColumnById: (state) => (id: string) => {
return state.columns.data[id]
},
getPostsByCid: (state) => (cid: string) => {
return objToArr(state.posts.data).filter(post => post.column === cid)
},
getCurrentPost: (state) => (id: string) => {
return state.posts.data[id]
}
}
})
export default store
4、取数据
import { defineComponent, computed, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { useStore } from 'vuex' // 1、引入useStore
import { GlobalDataProps, ColumnProps } from '../store'
import PostList from '../components/PostList.vue'
import { addColumnAvatar } from '../helper'
export default defineComponent({
components: {
PostList
},
setup() {
const route = useRoute()
const store = useStore<GlobalDataProps>() // 2、获取
const currentId = route.params.id
onMounted(() => {
store.dispatch('fetchColumn', currentId) // 3、存数据
store.dispatch('fetchPosts', currentId)
})
const column = computed(() => {
const selectColumn = store.getters.getColumnById(currentId) as ColumnProps | undefined
if (selectColumn) {
addColumnAvatar(selectColumn, 100, 100)
}
return selectColumn
})
const list = computed(() => store.getters.getPostsByCid(currentId)) // 取
return {
column,
list
}
}
})