# uniapp-project-template **Repository Path**: runler/uniapp-project-template ## Basic Information - **Project Name**: uniapp-project-template - **Description**: uniapp-project-template 模版 vue3_vite_ts_pinia,使用vscode编辑器,eslint+prettier + husky 代码规范 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-06-09 - **Last Updated**: 2024-06-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 项目初始化--uniapp--vscode--vue3--ts 本文链接: 视频教程 - 黑马程序员 - 小兔鲜uniapp项目 ## HBuilderX 创建 uni-app 项目 ### 注意开启服务端口 ![img](https://cdn.nlark.com/yuque/0/2024/png/28316884/1716618412339-08590728-0444-4c2d-86a4-05f5bd7fbdc2.png) ## 目录结构 ``` ├─pages 业务页面文件存放的目录 │ └─index │ └─index.vue index页面 ├─static 存放应用引用的本地静态资源的目录(注意:静态资源只能存放于此) ├─unpackage 非工程代码,一般存放运行或发行的编译结果 ├─index.html H5端页面 ├─main.js Vue初始化入口文件 ├─App.vue 配置App全局样式、监听应用生命周期 ├─pages.json **配置页面路由、导航栏、tabBar等页面类信息** ├─manifest.json **配置appid**、应用名称、logo、版本等打包信息 └─uni.scss uni-app内置的常用样式变量 ``` ## 命令行创建 uni-app 项目 vsCode ### 不必依赖 HBuilderX,TypeScript 类型支持友好 ## 1 vue3 + ts 版 ``` npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-ts-project-xxxxxx 或直接gitee下载 https://gitee.com/dcloud/uni-preset-vue/repository/archive/vite-ts.zip `npx @dcloudio/uvm@latest` 更新, 更新日志详见:https://download1.dcloud.net.cn/hbuilderx/changelog/4.15.2024050802.html ``` ### 创建其他版本可查看:[uni-app 官网](https://uniapp.dcloud.net.cn/quickstart-cli.html) ## 2 编译和运行 uni-app 项目 ### 安装依赖 ``` pnpm i --registry=https://registry.npmmirror.com ``` ### 编译成微信小程序 ``` pnpm dev:mp-weixin ``` ### 导入微信开发者工具 – 温馨提示: 在 manifest.json 文件添加 ### 微信小程序 appid 方便真机预览 ``` 微信开发者工具 左上角--项目--导入项目--项目文件夹-- ..... \dist\dev\mp-weixin ``` ## 3 用 vsCode 开发配置 ### 安装 uni-app 插件 #### uni-create-view :快速创建 uni-app 页面 并注册pages.json #### uni-helper :uni-app代码提示 ctrl+i 唤醒代码提示 #### uniapp小程序扩展 :鼠标悬停标签 查文档 ``` // .vscode/extensions.json { // 推荐的扩展插件 "recommendations": [ "mrmaoddxxaa.create-uniapp-view", // 创建 uni-app 页面 "uni-helper.uni-helper-vscode", // uni-app 代码提示 "evils.uniapp-vscode", // uni-app 文档 "vue.volar", // vue3 语法支持 "vue.vscode-typescript-vue-plugin", // vue3 ts 插件 "editorconfig.editorconfig", // editorconfig "dbaeumer.vscode-eslint", // eslint "esbenp.prettier-vscode" // prettier ] } ``` ## 4 TS 类型校验 ``` // 微信小程序类型申明文件 原生微信小程序类型 2选1 pnpm i -D @types/wechat-miniprogram // 或 miniprogram-api-typings // uni-app 类型声明文件 pnpm i -D @uni-helper/uni-app-types // uni-ui 类型声明文件 pnpm i -D @uni-helper/uni-ui-types // 不使用 TS 可能会报 uni 找不到的 错 pnpm i @types/uni-app -save-dev // 找不到模块“vue”或其相应的类型声明 tsconfig.json 中types:['node'] pnpm i --save-dev @types/node ``` ``` // tsconfig.json { "extends": "@vue/tsconfig/tsconfig.json", "compilerOptions": { "ignoreDeprecations": "5.0", // typeScript 5.0报错 "sourceMap": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] }, "lib": ["esnext", "dom"], "types": [ "@dcloudio/types", // uni-app API 类型 "miniprogram-api-typings", // 原生微信小程序类型 2选1 // "@types/wechat-miniprogram", // 原生微信小程序类型 2选1 "@uni-helper/uni-app-types", // uni-app 组件类型 ] }, // vue 编译器类型,校验标签类型 "vueCompilerOptions": { // "experimentalRuntimeMode": "runtime-uni-app", // 原配置 `experimentalRuntimeMode` 现调整为 `nativeTags` // vue-official插件版本v2.0.12 太高会不识别 不允许属性nativeTags。其配置无效,组件识别失效不变色 "nativeTags": ["block", "component", "template", "slot"], }, "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] } ``` ### 另: 解决json 注释问题 vscode 设置 搜 文件关联 添加项 manifest.json 值 jsonc 和 pages.json 值 jsonc 注意:其他文件不允许添加注释 ``` // js版本 jsconfig.json { "compilerOptions": { "target": "es5", "module": "esnext", "baseUrl": "./", "moduleResolution": "node", "paths": { "@/*": ["./src/*"] }, "lib": ["esnext", "dom", "dom.iterable", "scripthost"], "jsx": "preserve" // template 模版 警告 } } // 配置 路径 src-->@ 自动提示路径 ``` ## 5 安装 sass ``` pnpm i sass -D pnpm i sass-loader -D // 可以不安装 ``` ## 6 引入 uni-ui 组件库 ``` // https://uniapp.dcloud.net.cn/component/uniui/quickstart.html#npm%E5%AE%89%E8%A3%85 pnpm i @dcloudio/uni-ui ``` ### 安装 uni-ui 组件类型申明提示 ``` pnpm i -D @uni-helper/uni-ui-types // 需要在tsconfig.json types类型中注册 "@uni-helper/uni-ui-types" ``` ### 组件自动导入 ``` // pages.json { // 组件自动导入 "easycom": { // 开启自动扫描 "autoscan": true, // 以正则方式自定义组件匹配规则 "custom": { // uni-ui 规则如下配置 "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue" } }, // 默认配置 "pages": [ // …省略 ] } ``` ## 7 配置 @==src ``` // vite.config.ts import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import uni from '@dcloudio/vite-plugin-uni' // https://vitejs.dev/config/ export default defineConfig({ plugins: [uni()], resolve: { extensions: ['.ts', '.js', '.json', '.vue', '.less', '.scss', '.css'], // 省略后缀 以及 index.* alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, }) ``` ## 8 .editorconfig ``` # Editor configuration, see http://editorconfig.org # 表示是最顶层的 EditorConfig 配置文件 root = true [*] # 表示所有文件适用 charset = utf-8 # 设置文件字符集为 utf-8 indent_style = space # 缩进风格(tab | space) indent_size = 2 # 缩进大小 end_of_line = lf # 控制换行类型(lf | cr | crlf), lf 适配 mac,linix ; cr 适配window; trim_trailing_whitespace = true # 去除行首的任意空白字符 insert_final_newline = true # 始终在文件末尾插入一个新行 [*.md] # 表示仅 md 文件适用以下规则 max_line_length = off trim_trailing_whitespace = false ``` ## 9-10 统一代码风格–安装 eslint + prettier ``` pnpm i -D eslint prettier eslint-plugin-vue @vue/eslint-config-prettier @vue/eslint-config-typescript @rushstack/eslint-patch @vue/tsconfig ``` ## 9 .eslintrc.cjs ``` /* eslint-env node */ require("@rushstack/eslint-patch/modern-module-resolution"); module.exports = { root: true, extends: [ "plugin:vue/vue3-essential", "eslint:recommended", "@vue/eslint-config-typescript", "@vue/eslint-config-prettier", ], // 小程序全局变量 globals: { uni: true, wx: true, WechatMiniprogram: true, getCurrentPages: true, UniHelper: true, }, parserOptions: { ecmaVersion: "latest", }, rules: { "prettier/prettier": [ "warn", { $schema: 'https://json.schemastore.org/prettierrc', printWidth: 100, tabWidth: 2, useTabs: false, // 结尾是否添加分号 [0]-关闭 1-warn 2-error semi: false, singleQuote: true, trailingComma: 'all', bracketSpacing: true, jsxBracketSameLine: true, arrowParens: 'avoid', endOfLine: 'auto', }, ], "vue/multi-word-component-names": ["off"], "vue/no-setup-props-destructure": ["off"], "vue/no-deprecated-html-element-is": ["off"], "@typescript-eslint/no-unused-vars": ["off"], }, }; ``` ```json module.exports = { env: { browser: true, es2021: true, node: true, jest: true, }, /* 指定如何解析语法 */ parser: 'vue-eslint-parser', /** 优先级低于 parse 的语法解析配置 */ parserOptions: { ecmaVersion: 'latest', sourceType: 'module', parser: '@typescript-eslint/parser', jsxPragma: 'React', ecmaFeatures: { jsx: true, }, }, /* 继承已有的规则 */ extends: [ 'eslint:recommended', 'plugin:vue/vue3-essential', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', ], plugins: ['vue', '@typescript-eslint'], /* * "off" 或 0 ==> 关闭规则 * "warn" 或 1 ==> 打开的规则作为警告(不影响代码执行) * "error" 或 2 ==> 规则作为一个错误(代码不能执行,界面报错) */ rules: { // eslint(https://eslint.bootcss.com/docs/rules/) 'no-var': 'error', // 要求使用 let 或 const 而不是 var 'no-multiple-empty-lines': ['warn', { max: 1 }], // 不允许多个空行 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-unexpected-multiline': 'error', // 禁止空余的多行 'no-useless-escape': 'off', // 禁止不必要的转义字符 // typeScript (https://typescript-eslint.io/rules) '@typescript-eslint/no-unused-vars': 'error', // 禁止定义未使用的变量 '@typescript-eslint/prefer-ts-expect-error': 'error', // 禁止使用 @ts-ignore '@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型 '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。 '@typescript-eslint/semi': 'off', // eslint-plugin-vue (https://eslint.vuejs.org/rules/) 'vue/multi-word-component-names': 'off', // 要求组件名称始终为 “-” 链接的单词 'vue/script-setup-uses-vars': 'error', // 防止 ``` 小程序 底部安全区域css环境变量 env(safe-area-inset-bottom) ## 代理服务器 ``` export default defineConfig({ server: { proxy: { '/front': { // target: import.meta.env.VITE_API_URL, target: loadEnv('', process.cwd()).VITE_API_URL, // 获取环境变量 读取env文件 VITE_API_URL的值 changeOrigin: true // rewrite: (path) => path.replace(/^\/api/, '') }, '/boss': { target: loadEnv('', process.cwd()).VITE_API_URL, // 报错 直接输入.env文件读取参数值 import.meta.env.VITE_API_URL changeOrigin: true } } } }) ``` **如果调用被拦截的话,请检查微信小程序里的项目设置,然后选中** **不检验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书** ## 样式预定义 uni.scss 中尾部 添加 @import "@/common/style/base-style.scss"; // 引入自定义变量 文件,注意结尾加分号 App.vue中 ``` ``` ## 事件定义和监听 ### uniapp页面通讯中 功能:用于子页面通知父页面更新数据列表 uni.$on(eventName,callback) 定义全局自定义事件 list.vue uni.$emit(eventName,Object) 触发全局的自定义事件,传递参数 edit.vue ### mock数据 pnpm install -D vite-plugin-mock mockjs ``` export default defineConfig(({ command }) => { return { plugins: [ vue(), // Mock配置 viteMockServe({ localEnabled: command === 'serve', }), ``` #### **在配置vite-plugin-mock的时候,出现了如下错误:** ``` file:///Users/Desktop/myapp/node_modules/vite-plugin-mock/dist/index.mjs:128 if (!require.cache) { ^ ``` 在node_modules/vite-plugin-mock/dist/index.mjs这个文件中做如下配置: ``` import { createRequire } from 'module'; const require = createRequire(import.meta.url); ``` 模拟数据 ``` //用户信息数据 function createUserList() { return [ { userId: 1, avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', username: 'admin', password: '111111', desc: '平台管理员', roles: ['平台管理员'], buttons: ['cuser.detail'], routes: ['home'], token: 'Admin Token', }, { userId: 2, avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', username: 'system', password: '111111', desc: '系统管理员', roles: ['系统管理员'], buttons: ['cuser.detail', 'cuser.user'], routes: ['home'], token: 'System Token', }, ] } //对外暴露一个数组,数组里包含两个接口 //登录假的接口 //获取用户信息的假的接口 export default [ // 用户登录接口 { url: '/api/user/login', //请求地址 method: 'post', //请求方式 response: ({ body }) => { //获取请求体携带过来的用户名与密码 const { username, password } = body //调用获取用户信息函数,用于判断是否有此用户 const checkUser = createUserList().find( (item) => item.username === username && item.password === password, ) //没有用户返回失败信息 if (!checkUser) { return { code: 201, data: { message: '账号或者密码不正确' } } } //如果有返回成功信息 const { token } = checkUser return { code: 200, data: { token } } }, }, // 获取用户信息 { url: '/api/user/info', method: 'get', response: (request) => { //获取请求头携带token const token = request.headers.token //查看用户信息是否包含有次token用户 const checkUser = createUserList().find((item) => item.token === token) //没有返回失败的信息 if (!checkUser) { return { code: 201, data: { message: '获取用户信息失败' } } } //如果有返回成功信息 return { code: 200, data: { checkUser } } }, }, ] ``` ``` import Mock from "mockjs" // 内存模拟数据 const arr = [] for (let i = 0; i < 10; i++) { arr.push({ id: Mock.mock("@id"), name: Mock.mock("@cname"), place: Mock.mock("@county(true)"), }) } export default [ { url: "/list", method: "get", response: () => { return arr }, }, { url: "/del/:id", method: "delete", response: (req) => { const index = arr.findIndex((item) => item.id === req.query.id) if (index > -1) { arr.splice(index, 1) return { success: true } } else { return { success: false } } }, }, { url: "/edit/:id", method: "patch", response: ({ query, body }) => { const item = arr.find((item) => item.id === query.id) if (item) { item.name = body.name item.place = body.place return { success: true } } else { return { success: false } } }, }, ] ```