pnpm官网:https://www.pnpm.cn/


1 安装

npm

npm install -g pnpm # 或 npm install -g @pnpm/exe

version

> pnpm -v
8.9.2

2 创建项目

# pnpm create vite 
pnpm create vite vite3-vue3 -- --template vue

cd <Project name>
pnpm install
pnpm run dev

3 集成 Vue-Router

pnpm i vue-router@4

router/index.js

import { createRouter, createWebHashHistory } from 'vue-router'

export const constantRoutes = [
  {
    path: '/login',
    component: () => import('@/views/login/Login.vue'),
    hidden: true
  },
]

const router = createRouter({
  history: createWebHashHistory(),
  scrollBehavior: () => ({ top: 0 }),
  routes: constantRoutes
})

export default router

main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from '@/router'

const app = createApp(App)

app.use(router)
app.mount('#app')

4 集成 Pinia

Pinia 是 Vue 的存储库,它允许跨组件/页面共享状态
安装

pnpm i pinia

5 页面

store/user.js

import { loginAction } from '@/api/user'
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => {
    return {
      username: '',
      avatar: ''
    }
  },

  actions: {
    update_username(username) {
      this.$patch((state) => {
        state.username = username
      })
    },

    login(data) {
      return new Promise((resolve, reject) => {
        loginAction(data).then(res => {
          if (res.code === 200) {
            resolve(null)
          } else {
            reject(res)
          }
        }).catch((error) => {
          reject(error)
        })
      })
    }
  }
})

main.js

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from '@/router'
import { createPinia } from 'pinia'

const app = createApp(App)

app.use(router)
app.use(createPinia())
app.mount('#app')

6 配置 alias

在过去使用vue-cli的时候,一般使用 @ 去引入某些文件,由于 Vite 没有提供类似的配置,所以需要手动对其进行相关配置

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  define: {
    // path库报错修复
    'process.platform': null,
    'process.version': null
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
})

7 封装数据请求

安装

pnpm i axios

utils/request.js

import axios from 'axios'
import {getMemberToken} from "@/utils/auth.js";
import {message} from 'ant-design-vue';
import {ref} from 'vue';

let reqConfig
let loadingE

const service = axios.create()

// 请求拦截
service.interceptors.request.use(
    (request) => {
        // token setting
        request.headers['Authorization'] = "Bearer " + getMemberToken()
        /* download file*/
        if (request.isDownLoadFile) {
            request.responseType = 'blob'
        }
        /* upload file*/
        if (request.isUploadFile) {
            request.headers['Content-Type'] = 'multipart/form-data'
        }
        reqConfig = request
        if (request.bfLoading) {
            const content = ref('Loading...');
            loadingE = message.loading({content: () => content.value});
            setTimeout(() => {
                content.value = 'Loaded!';
            }, 1000);
        }
        /*
         *params会拼接到url上
         * */
        if (request.isParams) {
            request.params = request.data
            request.data = {}
        }
        return request
    },
    (err) => {
        Promise.reject(err)
    }
)
// 响应拦截
service.interceptors.response.use(
    (res) => {
        if (reqConfig.afHLoading && loadingE) {
            loadingE.close()
        }
        // 如果是下载文件直接返回
        if (reqConfig.isDownLoadFile) {
            return res
        }
        const {code} = res.data
        const successCode = '0,200,20000'
        if (successCode.includes(code)) {
            return res.data
        } else {
            //返回错误信息
            //注:如果没有return 则,会放回到请求方法中.then ,返回的res为 undefined
            return Promise.reject(res.data)
        }
    },
    (err) => {
        /*http错误处理*/
        if (loadingE) loadingE.close()
        const content = ref('Loading...');
        loadingE = message.loading({content: () => content.value});
        setTimeout(() => {
            content.value = 'Loaded!';
        }, 1000);
        const errObj = {
            msg: err.toString(),
            reqUrl: reqConfig.baseURL + reqConfig.url,
            params: reqConfig.isParams ? reqConfig.params : reqConfig.data
        }
        return Promise.reject(JSON.stringify(errObj))
    }
)

export function request({
	url,
	data,
	method,
	isParams,
	bfLoading,
	afHLoading,
	isUploadFile,
	isDownLoadFile,
	baseURL
}) {
    return service({
        url: url,
        method: method ?? 'get',
        data: data ?? {},
        isParams: isParams ?? false,
        bfLoading: bfLoading ?? false,
        afHLoading: afHLoading ?? true,
        isUploadFile: isUploadFile ?? false,
        isDownLoadFile: isDownLoadFile ?? false,
        baseURL: baseURL ?? import.meta.env.VITE_APP_BASE_URL
    })
}

export default request

api/user.js

import request from '@/utils/request'

export function loginUrlApi() {
    return request({
        url: '/wx/api/v1/member/loginUrl',
        isParams: true,
        data: {
            url: encodeURIComponent(
                window.location.href
            )
        }
    })
}

8 集成 ant

安装

pnpm install ant-design-vue

如果要使用其中的图标功能,还需要额外安装一个依赖

pnpm install @ant-design/icons-vue

按需加载

pnpm install unplugin-vue-components -D

vite.config.js

import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import Components from "unplugin-vue-components/vite";
import {AntDesignVueResolver} from "unplugin-vue-components/resolvers";

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        vue(),
        Components({
            resolvers: [
                AntDesignVueResolver({
                    importStyle: "less"
                })
            ],
            // 解决组件命名冲突问题
            directoryAsNamespace: true
        }),
    ],
    css: {
        preprocessorOptions: {
            less: {
                javascriptEnabled: true,
                modifyVars: {
                    "@primary-color": "#0083FF"
                }
            }
        }
    },
    define: {
        // path库报错修复
        'process.platform': null,
        'process.version': null
    },
    resolve: {
        alias: {
            '@': path.resolve(__dirname, 'src'),
        },
    },
    server: {
        proxy: {
            '/wx/api': {
                target: 'http://127.0.0.1:7201',
                changeOrigin: true,
                rewrite: path => path.replace(RegExp(`^api`), '')
            },
        }
    }
})