uniapp创建vue3+ts+pinia+sass项目

1.执行命令行创建,暂时在Hbuildx中无法创建ts项目

javascript 复制代码
npx degit dcloudio/uni-preset-vue#vite-ts my-uniapp-project

注意:创建失败时,注意VPN的问题。

2.安装依赖

javascript 复制代码
npm install

3.安装sass

javascript 复制代码
npm install -D sass sass-loader
  1. 安装 @uni-helper/uni-types(增加ts支持)
javascript 复制代码
npm install @uni-helper/uni-types

注意:此时可能会出现问题,例如:

npm ERR! code ERESOLVE

npm ERR! ERESOLVE unable to resolve dependency tree

npm ERR!

npm ERR! While resolving: uni-preset-vue@0.0.0

npm ERR! Found: typescript@4.9.5

npm ERR! node_modules/typescript

npm ERR! dev typescript@"^4.9.4" from the root project

npm ERR!

npm ERR! peer typescript@"^5.0.0" from @uni-helper/uni-types@1.0.0-alpha.6

npm ERR! node_modules/@uni-helper/uni-types

npm ERR! @uni-helper/uni-types@"*" from the root project

npm ERR!

npm ERR! Fix the upstream dependency conflict, or retry

npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

npm ERR!

npm ERR!

npm ERR! For a full report see:

npm ERR! C:\Users\Administrator\AppData\Local\npm-cache\_logs\2025-07-25T02_27_05_562Z-eresolve-report.txt

npm ERR! A complete log of this run can be found in: C:\Users\Administrator\AppData\Local\npm-cache\_logs\2025-07-25T02_27_05_562Z-debug-0.log

这个错误是因为 npm 依赖冲突 ,具体原因是 @uni-helper/uni-types@1.0.0-alpha.6 需要 TypeScript 5.0+,但你的项目当前使用的是 TypeScript 4.9.5。只需更新ts后再安装即可

更新ts:

javascript 复制代码
npm install typescript@latest --save-dev
  1. 配置tsconfigjson
javascript 复制代码
{
  //"extends": "@vue/tsconfig/tsconfig.json",
  "compilerOptions": {
    "module": "es2020", // 或 "es2022", "esnext", "node16", "node18"
    "target": "esnext", // 建议与 module 保持同步
    "moduleResolution": "node", // 确保模块解析策略正确
    "sourceMap": true,
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "./src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom"
    ],
    "types": [
      "@dcloudio/types",
      "vue"
    ]
  },
  "vueCompilerOptions": {
    "plugins": [
      "@uni-helper/uni-types/volar-plugin"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue"
  ]
}

6.配置环境,在根目录文件下创建.env,.env.production,.env.development,.env.test

javascript 复制代码
# Node 运行环境
NODE_ENV=development
 
# 后端接口地址
VITE_APP_BASE_URL=https://xxx.xxxx.com
 
# oss资源地址
VITE_APP_OSS_URL=https://xxx.com
 
# 接口基础地址
VITE_APP_BASE_API=/app-api
 
# 自定义环境标识
VITE_APP_ENV=development

7.安装pinia(其中pinia-plugin-persistedstate 是一个为 Pinia 设计的插件,用于持久化存储 Pinia 的状态(state) ,使其在页面刷新、浏览器关闭后重新打开时能自动恢复数据。它类似于 Vuex 的持久化插件,但专门适配 Pinia 的响应式架构。

注意:如果安装失败,可能是vue版本不够最新的pinia,只需更新vue为新增vue3版本即可

javascript 复制代码
npm i pinia
npm i pinia-plugin-persistedstate

8.创建src/store/index.ts

javascript 复制代码
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
 
// 创建 pinia 实例
const pinia = createPinia()
 
// 使用持久化插件
pinia.use(piniaPluginPersistedstate)
 
export default pinia

9.配置main.ts

javascript 复制代码
import { createSSRApp } from "vue";
import App from "./App.vue";
import pinia from './store';
export function createApp() {
  const app = createSSRApp(App);
  app.use(pinia);
  return {
    app,
  };
}

10.此时vue可能会提示找不到,在src下新建文件shims-vue.d.ts

javascript 复制代码
// src/shims-vue.d.ts
declare module '*.vue' {
  /* import { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component */
}

11.封装请求,新建utils/request/index.ts

javascript 复制代码
npm i luch-request
javascript 复制代码
import Request from 'luch-request';
import type { RequestFunction, ErrorResponse, RequestConfig } from './types';
 
const baseUrl = import.meta.env.VITE_API_BASE_URL;
const baseApi = import.meta.env.VITE_API_BASE_API;
 
const options = {
    // 显示操作成功消息 默认不显示
    showSuccess: false,
    // 成功提醒 默认使用后端返回值
    successMsg: '',
    // 显示失败消息 默认显示
    showError: true,
    // 失败提醒 默认使用后端返回信息
    errorMsg: '',
    // 显示请求时loading模态框 默认不显示
    showLoading: false,
    // loading提醒文字
    // 需要授权才能请求 默认放开
    auth: false,
};
 
// 创建请求实例
const httpRequest = new Request({
    baseURL: `${baseUrl}${baseApi}`,
    timeout: 10000,
    header: {
        Accept: 'text/json',
        'Content-Type': 'application/json;charset=UTF-8',
    },
    custom: options,
});
 
// 请求拦截器
httpRequest.interceptors.request.use(
    config => {
        // 获取登录状态
        const isLoggedIn = !!uni.getStorageSync('token');
        if (config?.custom?.auth && !isLoggedIn) {
            // 未登录,弹出登录弹窗
            return Promise.reject();
        }
        // 在发送请求之前做些什么
        const token = uni.getStorageSync('token');
        if (token) {
            config.header = config.header || {};
            config.header.Authorization = `Bearer ${token}`;
        }
        return config;
    },
    error => {
        return Promise.reject(error);
    },
);
 
// 响应拦截器
httpRequest.interceptors.response.use(
    response => {
        // 对响应数据做点什么
        return response;
    },
    error => {
        // 处理错误
        const { statusCode, data } = error as ErrorResponse;
 
        switch (statusCode) {
            case 401:
                // 未授权,跳转到登录页
                uni.navigateTo({
                    url: '/pages/login/index',
                });
                break;
 
            case 403:
                // 权限不足,显示自定义弹窗
                uni.showModal({
                    title: '提示',
                    content: data.message || '您没有权限执行此操作',
                    showCancel: false,
                });
                break;
 
            case 500:
                // 服务器错误,显示系统提示
                uni.showToast({
                    title: '服务器错误,请稍后重试',
                    icon: 'none',
                });
                break;
 
            default:
                // 其他错误,显示错误信息
                uni.showToast({
                    title: data.message || '请求失败',
                    icon: 'none',
                });
        }
 
        return Promise.reject(error);
    },
);
 
const request: RequestFunction = config => {
    return httpRequest.middleware(config);
};
 
export { request };

types.ts:

javascript 复制代码
import type { HttpRequestConfig, HttpTask, HttpData } from 'luch-request';
 
// 响应数据基础接口
export interface BaseResponse<T = any> {
    code: number;
    data: T;
    message: string;
}
 
// 请求配置扩展
export type RequestConfig<T = any> = Omit<HttpRequestConfig<HttpTask>, 'data'> & {
    data?: T extends HttpData ? T : HttpData;
};
 
// HTTP 请求方法类型
export type HttpMethod =
    | 'GET'
    | 'POST'
    | 'PUT'
    | 'DELETE'
    | 'OPTIONS'
    | 'HEAD'
    | 'TRACE'
    | 'CONNECT';
 
// 请求函数类型
export type RequestFunction = <T = any, R = any>(
    config: RequestConfig<T>,
) => Promise<BaseResponse<R>>;
 
// 错误响应类型
export interface ErrorResponse {
    statusCode: number;
    data: {
        code: number;
        message: string;
    };
}
 
// 请求实例配置接口
export interface RequestInstanceConfig {
    baseURL: string;
    timeout: number;
    header: Record<string, string>;
}
 
export interface RequestError {
    statusCode: number;
    data: any;
    config: HttpRequestConfig;
    errMsg: string;
}
 
export type ErrorMiddleware = (
    error: RequestError,
    next: (error: RequestError) => void,
) => Promise<void> | void;
 
// 请求实例类型
相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学3 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端