# 快速搭建 Mac 的 web 开发环境
# 安装 Node
检查当前 node 版本
node -v
建议安装最新正式版本 node 22.12.0
brew install node@22
# If you need to have node@22 first in your PATH, run:
echo 'export PATH="/opt/homebrew/opt/node@22/bin:$PATH"' >> ~/.zshrc
# For compilers to find node@22 you may need to set:
export LDFLAGS="-L/opt/homebrew/opt/node@22/lib"
export CPPFLAGS="-I/opt/homebrew/opt/node@22/include"
# 更新配置
source ~/.zshrc
# 检查版本
node -v
# 安装 Node 版本管理工具 NVM
安装步骤
# 安装命令
brew install nvm
# 创建nvm工作目录
mkdir ~/.nvm
# 将以下命令添加到 ~/.zshrc
# This loads nvm
export NVM_DIR="$HOME/.nvm"
[ -s "$HOMEBREW_PREFIX/opt/nvm/nvm.sh" ] && \. "$HOMEBREW_PREFIX/opt/nvm/nvm.sh"
# This loads nvm bash_completion
[ -s "$HOMEBREW_PREFIX/opt/nvm/etc/bash_completion.d/nvm" ] && \. "$HOMEBREW_PREFIX/opt/nvm/etc/bash_completion.d/nvm"
# 更新配置
source ~/.zshrc
# 检查是否安装成功
nvm -v
nvm help
常用命令
nvm ls-remote --lts 查看所有正式版本
nvm install 版本号 安装指定版本
nvm uninstall 版本号 卸载指定版本
nvm current 当前最新版本
nvm list 显示已安装的列表
nvm use 版本号 使用指定版本
nmv root
# 安装 node 包管理工具 pnpm
brew install pnpm
pnpm -v
# 推荐安装 webStorm
在使用 vscode 发现跳转定义处功能非常不好用,建议使用 webStorm,快捷键和 Android Studio 一致,可以平滑过渡
淘宝 5 元激活
# 运行项目
cd 到项目根目录
pnpm install 安装依赖
pnpm run dev 运行服务
常用命令
pnpm view mockjs versions 查看可用版本
pnpm store path 查看缓存路径
pnpm store prune 清除缓存
# 项目报错
以上步骤都正确,但是项目首次就是跑不起来?
- 首先确认你的 node 版本
- 删掉 node_modules 和 pnpm-lock.yaml 文件
- pnpm store prune 清除 pnpm 缓存
# 安装 Google 拓展
搜索拓展 Vue.js devtools
# 入门必学
- tailwindcss (opens new window) - CSS 工具类
- Vue Composition Api - Vue3 新特性
- Vant - UI 框架
- TypeScript - 编程语言
- Vue3 - 基础框架
- Vue.js devtools - Vue 调试工具
- pinia (opens new window) - 状态管理工具
# 重要文件介绍
- app.api.ts 声明 app 级别的 http 请求,例如 getAppConfig
- message-service 解析 ws 消息的相关逻辑
- src > object 存放 ws 消息相关的 model
- src > model 存放 Http 请求相关的 model
- src > const 存放枚举与常量
- src > components 全局公用组件
- src > pages > * > components 页面级别的组件
- app.store.ts 存放 app 级别的对象、方法与状态,例如 language、token
- socket.store.ts 存放 socket 对象、方法与状态
# 主题相关
# tailwind class 方式使用定义的主题颜色
<div class="tw-bg-primary">主题主色1</div>
<div class="tw-bg-secondary">主题主色2</div>
<div class="tw-text-font-title">标题颜色</div>
<div class="tw-text-font-title-dark">深色背景标题颜色</div>
<div class="tw-text-font-primary">字体主色</div>
<div class="tw-text-font-primary-dark">深色背景字体主色</div>
<div class="tw-text-font-secondary">字体次级主色</div>
<div class="tw-text-font-prompt">字体提示色3</div>
<div class="tw-text-font-prompt-dark">深色背景字体主色</div>
<div class="tw-bg-warning">警告色</div>
<div class="tw-bg-danger">提示色</div>
<div class="tw-bg-stroke1">间隔/描边色1</div>
<div class="tw-text-font-stroke1-dark">深色背景间隔/描边色</div>
<div class="tw-bg-stroke2">间隔/描边色2</div>
<div class="tw-bg-stroke3">间隔/描边色3</div>
<div class="tw-bg-accent1">点缀色1</div>
<div class="tw-bg-accent2">点缀色2</div>
<div class="tw-bg-button1">按钮颜色1</div>
<div class="tw-bg-button2">按钮颜色2</div>
<div class="tw-bg-yellow1">黄色1</div>
<div class="tw-bg-yellow1">黄色1</div>
<div class="tw-bg-gradient1">渐变色1</div>
<div class="tw-bg-gradient2">渐变色2</div>
<div class="tw-bg-gradient3">渐变色3</div>
<div class="tw-bg-gradient4">渐变色4</div>
<div class="tw-bg-gradient5">渐变色5</div>
<div class="tw-bg-gradient6">渐变色6</div>
<div class="tw-bg-gradient7">渐变色7</div>
<div class="tw-bg-gradient8">渐变色8</div>
<div class="tw-bg-gradient9">渐变色9</div>
<div class="tw-bg-gradient10">渐变色10</div>
<div class="tw-bg-gradient11">渐变色11</div>
<div class="tw-bg-gradient12">渐变色12</div>
<div class="tw-bg-gradient13">渐变色13</div>
<div class="tw-bg-gradient14">渐变色14</div>
<div class="tw-bg-[var(--color-warning)]">
颜色变量示例
</div>
<div class="tw-bg-gradient-to-t tw-from-[var(--color-warning)] tw-to-[var(--color-gradient5)] ">
渐变色变量示例
</div>
</div>
# 在 less 中使用
<div class="var-color" > 在less中使用</div > .var-color {
// 使用变量
color: var(--bg-primary);
}
# 添加新的主题色
src > styles > tailwind.css
@layer base {
// 浅色主题
.light {
--my-color: #000000;
}
// 深色主题
.dark {
--my-color: #ffffff;
}
}
src > tailwind.config.js
theme: {
...
extend: {
...
colors: {
'my-color': 'var(--my-color)',
},
},
}
使用
<div class="tw-bg-my-color">新颜色修饰背景色</div>
<div class="tw-text-my-color">新颜色修饰字体</div>
// 同上面效果一样
<div class="tw-bg-[var(--my-color)]">新颜色修饰背景色</div>
<div class="tw-text-[var(--my-color)]">新颜色修饰字体</div>
// less中 .my-color { // 使用变量 color: var(--my-color); }
# 声明一个 Http 的 api
src > api > ***.api.ts
export const findMiniApp = post<MiniAppResponse, MiniAppRequest>(
"/openapi/client/miniapp/find"
);
src > model > ***.request.d.ts
export interface MiniAppRequest {
name: string;
page: number;
limit: number;
channelId: number;
}
src > model > ***.response.d.ts
export interface MiniAppResponse {
apps: App[];
count: number;
total: number;
}
export interface App {
description: string;
downloadUrl: string;
favoriteAt: number;
flag: number;
icon: string;
iconGaussian: string;
id: number;
lastLoginAt: number;
miniappCreatedAt: number;
name: string;
screen: string;
sessionCreatedAt: number;
typ: number;
version: number;
}
使用
onMounted(async () => {
example.fetchAppConfig();
const { apps } = await findMiniApp({
name: "",
page: 1,
limit: 10,
channelId: 3,
});
miniApps.value = apps;
console.log("miniApps", miniApps.value[0].name);
});
声明其他 model 请在与 response、request 同级目录下
# 声明一个 ws 请求
src > services > service.ts
import { generateRequestId } from "@/utils";
import { useAppStore } from "@/stores/app.store";
import { useSocketStore } from "@/stores/socket.store";
import { putRequestId } from "@/services/message-service";
/** 进入 */
const enter = () => {
const app = useAppStore();
const message = {
action: "enter",
id: app.currentId,
requestId: generateRequestId(),
};
const socket = useSocketStore();
const map = new Map(Object.entries(message));
putRequestId(map);
socket.send(JSON.stringify(message));
};
export { enter };
# 如何将 ws 的消息转为驼峰 Model
import "reflect-metadata";
import { Expose, Type } from "class-transformer";
export class NewRound {
appid: string = "";
@Type(() => Current)
current: Current = new Current();
@Expose({ name: "round_id" })
roundId: string = "";
@Expose({ name: "round_name" })
roundName: string = "";
@Type(() => Last)
last: Last = new Last();
}
export class Current {
@Expose({ name: "closure_time" })
closureTime: number = 0;
round: string = "";
@Expose({ name: "server_time" })
serverTime: number = 0;
@Expose({ name: "simple_round" })
simpleRound: string = "";
@Expose({ name: "start_time" })
startTime: number = 0;
}
export class Last {
@Expose({ name: "main_result" })
mainResult: string[] = [];
@Type(() => Result)
result: Result[] = [];
round: string = "";
@Expose({ name: "simple_round" })
simpleRound: string = "";
}
export class Result {
value: string = "";
}
// ws消息
const wsMessage = { appid: "xxxx" };
// 转换完就可以 . 出来
const newRound = plainToInstance(NewRound, data);
console.log("---newRound---", newRound.roundName);