资讯动态

用Claude Code从零搭建宠物生命周期管理App:React Native+Expo+SQLite全流程

发布时间:2026/10/14 6:41:26 来源:尧图企业网站定制
1. 项目缘起与整体设计思路1.1 为什么选宠物生命周期管理这个方向宠物生命周期管理这个选题乍一看好像是个小众赛道但实际拆开来看它覆盖的需求密度非常高。一只宠物从被领养、日常喂养、疫苗接种、驱虫记录、体重变化、发情期、绝育手术到老年期慢性病管理再到临终关怀和身后事处理整条链路涉及的时间跨度可以长达十几年。这中间产生的数据是碎片化的、非结构化的而且大多数养宠人根本没有系统记录的习惯。我身边养猫养狗的朋友几乎每个人手机里都有一堆备忘录、相册截图、微信聊天记录用来记疫苗时间、驱虫日期、上次洗澡是什么时候。信息散落在各处等到需要的时候翻半天找不到。这就是一个非常典型的“数据有但不可用”的场景。所以这个项目的核心目标很明确用Claude Code从零搭建一个宠物生命周期管理App把宠物的全生命周期数据结构化、可视化、可提醒化。它不是一个简单的记事本而是一个带有时间轴、提醒引擎、健康趋势分析、多宠物管理的完整系统。适合谁来参考这篇内容如果你是有一定编程基础、想用AI辅助开发一个完整移动端项目的开发者或者你是产品经理/独立开发者想了解如何用Claude Code把想法快速落地成可运行的产品原型这篇内容会非常有参考价值。即使你之前没用过Claude Code只要你会基本的命令行操作和JavaScript/TypeScript跟着走完全没问题。1.2 技术选型背后的取舍逻辑在动手之前我先说清楚技术选型的逻辑因为选错了后面全是坑。前端框架React Native Expo为什么不用FlutterFlutter的渲染性能确实好但Expo生态在快速原型开发上的优势太明显了。Expo Router做文件路由、Expo Notifications做本地推送、Expo SQLite做本地存储这些开箱即用的能力可以让你在几个小时内跑通核心链路。而且Claude Code对React Native Expo的代码生成质量明显更高因为训练数据里这套组合的样本量足够大。本地存储SQLite Drizzle ORM宠物生命周期数据是典型的关系型数据宠物表、事件表、提醒表、健康记录表表之间有明确的外键关系。用SQLite做本地存储配合Drizzle ORM做类型安全的查询既轻量又可靠。不用AsyncStorage的原因是它不适合结构化查询你没法用SQL去筛选“过去30天体重变化超过10%的宠物”。状态管理ZustandRedux太重Context API在频繁更新时性能差。Zustand的API极简配合Immer做不可变更新代码量少且可读性强。对于这种中等复杂度的AppZustand是最优解。提醒引擎Expo Notifications 本地调度宠物疫苗、驱虫、体检这些提醒不需要服务端推送本地调度就够了。Expo Notifications支持精确到秒的本地通知调度而且可以在App被杀掉后依然触发。这比接第三方推送服务简单太多也省去了服务端成本。AI辅助开发Claude CodeClaude Code在这个项目里的角色不是“帮你写几行代码”而是“帮你从零搭建整个项目骨架并持续迭代”。它的优势在于能理解项目上下文、能跨文件修改、能根据你的自然语言描述生成完整的模块代码。我实测下来用Claude Code搭建这个项目的效率比传统手写高出至少3倍。1.3 项目整体架构拆解整个App的架构可以分成四层数据层SQLite数据库 Drizzle ORM 数据迁移脚本业务逻辑层宠物管理、事件记录、提醒调度、健康分析UI层React Native组件 Expo Router页面通知层Expo Notifications本地调度数据流是这样的用户在UI层操作 → 业务逻辑层处理 → 数据层持久化 → 通知层根据数据变化重新调度提醒。这个架构的关键设计原则是数据层和通知层解耦。提醒的调度不依赖UI层的状态而是直接读取数据库中的事件日期计算出下一次提醒时间然后调度本地通知。这样即使App没有打开提醒也能正常触发。注意Expo Notifications在iOS和Android上的行为有差异。iOS的本地通知需要用户授权Android 13也需要运行时权限。这个在后面的实操环节会详细讲。2. 环境搭建与项目初始化2.1 Claude Code的安装与配置Claude Code的安装方式取决于你的操作系统。我以macOS为例Linux和Windows WSL的步骤基本一致。首先确保你的Node.js版本在18以上然后用npm全局安装npm install -g anthropic-ai/claude-code安装完成后进入你的工作目录运行claude第一次运行会引导你完成认证配置。认证完成后你就进入了Claude Code的交互界面。这里有一个关键配置项需要调整项目上下文文件。Claude Code会读取项目根目录下的CLAUDE.md文件作为项目上下文。这个文件里写什么直接决定了Claude Code生成代码的质量。我的CLAUDE.md是这样写的# 宠物生命周期管理App ## 技术栈 - React Native Expo (SDK 52) - TypeScript - Expo Router (文件路由) - SQLite Drizzle ORM - Zustand (状态管理) - Expo Notifications (本地提醒) ## 项目结构 - app/ 页面路由 - db/ 数据库schema和迁移 - stores/ Zustand状态 - services/ 业务逻辑 - components/ 通用组件 - utils/ 工具函数 ## 编码规范 - 使用函数式组件 Hooks - 所有数据库操作通过services层 - 类型定义放在types/目录 - 日期统一用ISO 8601字符串存储这个文件的作用是给Claude Code一个“项目宪法”它每次生成代码都会参考这个上下文。实测下来有了这个文件之后生成的代码风格一致性提升非常明显。2.2 Expo项目初始化在Claude Code的交互界面里直接输入自然语言指令帮我初始化一个Expo项目使用TypeScript模板项目名叫pet-lifecycle然后安装以下依赖expo-router, expo-sqlite, expo-notifications, zustand, drizzle-orm, drizzle-kit, date-fnsClaude Code会执行以下命令npx create-expo-applatest pet-lifecycle --template typescript cd pet-lifecycle npx expo install expo-router expo-sqlite expo-notifications npm install zustand drizzle-orm drizzle-kit date-fns这里有一个细节需要注意expo-router的安装需要额外配置package.json的main字段和app.json的scheme。Claude Code会自动帮你改好但你要知道它改了什么。package.json的改动{ main: expo-router/entry }app.json的改动{ expo: { scheme: petlifecycle, plugins: [expo-router] } }实操心得scheme字段必须设置否则Expo Router的深链接功能无法正常工作。这个坑我踩过当时调试了半小时才发现是scheme没配。2.3 数据库Schema设计数据库设计是这个项目的核心。我让Claude Code根据我的描述生成初始schema然后手动调整了几个关键字段。// db/schema.ts import { sqliteTable, text, integer, real } from drizzle-orm/sqlite-core; export const pets sqliteTable(pets, { id: text(id).primaryKey(), name: text(name).notNull(), species: text(species).notNull(), // cat, dog, other breed: text(breed), birthDate: text(birth_date), adoptionDate: text(adoption_date), gender: text(gender), weight: real(weight), avatar: text(avatar), createdAt: text(created_at).notNull(), updatedAt: text(updated_at).notNull(), }); export const events sqliteTable(events, { id: text(id).primaryKey(), petId: text(pet_id).notNull().references(() pets.id, { onDelete: cascade }), type: text(type).notNull(), // vaccine, deworm, vet, bath, weight, medication, other title: text(title).notNull(), description: text(description), date: text(date).notNull(), nextDate: text(next_date), metadata: text(metadata), // JSON string for flexible data createdAt: text(created_at).notNull(), }); export const reminders sqliteTable(reminders, { id: text(id).primaryKey(), petId: text(pet_id).notNull().references(() pets.id, { onDelete: cascade }), eventId: text(event_id).references(() events.id, { onDelete: cascade }), title: text(title).notNull(), body: text(body), triggerDate: text(trigger_date).notNull(), repeatInterval: integer(repeat_interval), // days, null no repeat notificationId: text(notification_id), enabled: integer(enabled).notNull().default(1), createdAt: text(created_at).notNull(), });这个schema的设计有几个关键决策为什么用text存日期而不是integer时间戳因为SQLite没有原生日期类型用ISO 8601字符串存储可读性更好而且Drizzle ORM对字符串日期的处理更直观。查询时用date 2024-01-01这样的字符串比较就能工作。为什么events表要加metadata字段因为不同事件类型需要记录不同的附加信息。比如疫苗事件需要记录疫苗品牌、批号体重事件需要记录具体数值。用JSON字符串存这些灵活数据避免了为每种事件类型建单独的表。为什么reminders表要存notificationId因为Expo Notifications在取消通知时需要传入之前调度时返回的ID。把这个ID存下来才能在用户删除提醒时正确取消已调度的通知。2.4 数据库迁移与初始化Drizzle Kit负责生成迁移文件。在drizzle.config.ts中配置import type { Config } from drizzle-kit; export default { schema: ./db/schema.ts, out: ./db/migrations, dialect: sqlite, driver: expo, } satisfies Config;然后运行npx drizzle-kit generate这会在db/migrations目录下生成SQL迁移文件。在App启动时通过expo-sqlite执行这些迁移// db/index.ts import { openDatabaseSync } from expo-sqlite; import { drizzle } from drizzle-orm/expo-sqlite; import { migrate } from drizzle-orm/expo-sqlite/migrator; import migrations from ./migrations/migrations; const expoDb openDatabaseSync(pet_lifecycle.db); export const db drizzle(expoDb); export async function initDatabase() { await migrate(db, migrations); }注意openDatabaseSync是同步打开数据库但migrate是异步的。在App的根布局中调用initDatabase时要确保在渲染任何需要数据库的组件之前完成迁移。我的做法是在根布局的useEffect中调用并用一个isReady状态控制渲染。3. 核心功能模块实现3.1 宠物管理模块宠物管理是基础模块包含增删改查。我让Claude Code生成了完整的CRUD逻辑然后手动优化了表单验证部分。Zustand store的设计// stores/petStore.ts import { create } from zustand; import { db } from ../db; import { pets } from ../db/schema; import { eq } from drizzle-orm; import { generateId } from ../utils/id; interface PetStore { pets: Pet[]; loading: boolean; loadPets: () Promisevoid; addPet: (data: OmitPet, id | createdAt | updatedAt) Promisevoid; updatePet: (id: string, data: PartialPet) Promisevoid; deletePet: (id: string) Promisevoid; } export const usePetStore createPetStore((set, get) ({ pets: [], loading: false, loadPets: async () { set({ loading: true }); const result await db.select().from(pets).orderBy(pets.createdAt); set({ pets: result, loading: false }); }, addPet: async (data) { const now new Date().toISOString(); const newPet { ...data, id: generateId(), createdAt: now, updatedAt: now, }; await db.insert(pets).values(newPet); await get().loadPets(); }, updatePet: async (id, data) { await db.update(pets) .set({ ...data, updatedAt: new Date().toISOString() }) .where(eq(pets.id, id)); await get().loadPets(); }, deletePet: async (id) { await db.delete(pets).where(eq(pets.id, id)); await get().loadPets(); }, }));这里有一个设计决策值得说明每次增删改后都重新加载整个列表。这在数据量小的时候完全没问题而且保证了UI和数据库的一致性。如果宠物数量超过100只可以优化成局部更新但对于这个场景全量刷新是最简单可靠的方案。宠物详情页需要展示宠物的完整信息包括年龄计算。年龄计算有个坑不同物种的年龄换算方式不同。猫和狗的1岁相当于人类的多少岁这个换算表是行业共识我把它做成了一个工具函数// utils/age.ts export function calculateAge(birthDate: string): { years: number; months: number } { const birth new Date(birthDate); const now new Date(); let years now.getFullYear() - birth.getFullYear(); let months now.getMonth() - birth.getMonth(); if (months 0) { years--; months 12; } return { years, months }; } export function toHumanAge(species: string, years: number): number { if (species cat) { if (years 1) return years * 15; if (years 2) return 15 (years - 1) * 9; return 24 (years - 2) * 4; } if (species dog) { // 简化版实际应按体型细分 if (years 1) return years * 15; if (years 2) return 15 (years - 1) * 9; return 24 (years - 2) * 5; } return years; }实操心得猫的年龄换算前两年是159之后每年加4岁这是兽医领域的通用标准。狗的换算更复杂因为小型犬和大型犬的老化速度差异很大。我在代码里做了简化处理如果你要做专业版建议按体型细分。3.2 事件记录与时间轴事件记录模块是整个App使用频率最高的部分。用户需要快速记录一次疫苗、一次驱虫、一次体重测量然后在一个时间轴上看到所有历史事件。时间轴的UI实现我用的是FlatList配合SectionList的思路按月份分组。每个事件卡片显示类型图标、标题、日期、距离今天的天数。事件类型我定义了以下几种每种有不同的颜色和图标事件类型颜色图标典型提醒周期vaccine蓝色针管每年一次deworm绿色药丸每月一次vet橙色听诊器按需bath青色水滴每2-4周weight紫色秤每周/每月medication红色药瓶按医嘱other灰色星标按需事件添加表单的关键设计是动态字段。选择不同事件类型时表单显示的附加字段不同。比如选择“weight”时显示体重输入框选择“vaccine”时显示疫苗品牌和批号输入框。这个动态表单的实现逻辑const eventTypeFields: Recordstring, FieldConfig[] { vaccine: [ { key: brand, label: 疫苗品牌, type: text }, { key: batch, label: 批号, type: text }, ], weight: [ { key: value, label: 体重(kg), type: number }, ], medication: [ { key: drug, label: 药物名称, type: text }, { key: dosage, label: 剂量, type: text }, ], };这些附加字段的值统一存到metadata字段的JSON字符串里。读取时解析出来渲染。注意SQLite的JSON函数在Expo SQLite中支持有限所以不要在SQL层面做JSON查询而是在JavaScript层面解析。这意味着你不能用SQL筛选“体重超过5kg的事件”但可以在加载后在JS里过滤。对于本地App的数据量这个性能损耗可以忽略。3.3 提醒引擎的实现提醒引擎是这个App最有技术含量的部分。核心逻辑是当用户创建一个带有nextDate的事件时自动创建一个提醒并在nextDate当天触发本地通知。Expo Notifications的调度逻辑// services/notificationService.ts import * as Notifications from expo-notifications; import { Platform } from react-native; Notifications.setNotificationHandler({ handleNotification: async () ({ shouldShowAlert: true, shouldPlaySound: true, shouldSetBadge: true, }), }); export async function requestPermission(): Promiseboolean { const { status: existingStatus } await Notifications.getPermissionsAsync(); let finalStatus existingStatus; if (existingStatus ! granted) { const { status } await Notifications.requestPermissionsAsync(); finalStatus status; } if (finalStatus ! granted) return false; if (Platform.OS android) { await Notifications.setNotificationChannelAsync(pet-reminders, { name: 宠物提醒, importance: Notifications.AndroidImportance.HIGH, vibrationPattern: [0, 250, 250, 250], }); } return true; } export async function scheduleReminder( title: string, body: string, triggerDate: Date, repeatIntervalDays?: number ): Promisestring { const trigger: Notifications.NotificationTriggerInput repeatIntervalDays ? { type: Notifications.SchedulableTriggerInputTypes.TIME_INTERVAL, seconds: repeatIntervalDays * 24 * 60 * 60, repeats: true, } : { type: Notifications.SchedulableTriggerInputTypes.DATE, date: triggerDate, }; const id await Notifications.scheduleNotificationAsync({ content: { title, body, sound: true, data: { type: pet-reminder }, }, trigger, }); return id; } export async function cancelReminder(notificationId: string) { await Notifications.cancelScheduledNotificationAsync(notificationId); }这里有几个关键点需要展开说权限请求的时机不要在App启动时就请求通知权限而是在用户第一次创建提醒时请求。这样用户能理解为什么需要这个权限授权率更高。Android通知渠道Android 8.0需要设置通知渠道否则通知不会显示。importance设为HIGH才能让通知在锁屏上弹出。重复提醒的实现Expo Notifications的TIME_INTERVAL触发器支持重复但最小间隔是60秒。对于“每月驱虫”这种需求用seconds: 30 * 24 * 60 * 60来调度。但要注意如果用户修改了提醒日期需要先取消旧的重复通知再创建新的。通知ID的持久化调度通知后返回的ID必须存到数据库的notificationId字段。否则用户删除提醒时你没法取消已经调度的通知它还会继续触发。踩坑记录我一开始没有存notificationId结果用户删除提醒后通知还在触发。后来加了字段重新调度才解决。这个坑很隐蔽因为测试时如果不删除提醒就发现不了。3.4 健康趋势分析健康趋势分析模块用图表展示宠物体重变化、疫苗间隔、驱虫频率等数据。图表库我选的是react-native-gifted-charts因为它对Expo的兼容性好API也简单。体重趋势图的实现// components/WeightChart.tsx import { LineChart } from react-native-gifted-charts; import { useMemo } from react; export function WeightChart({ events }: { events: Event[] }) { const chartData useMemo(() { return events .filter(e e.type weight) .map(e { const meta JSON.parse(e.metadata || {}); return { value: meta.value || 0, label: formatDate(e.date, MM/dd), date: e.date, }; }) .sort((a, b) a.date.localeCompare(b.date)); }, [events]); if (chartData.length 2) { return EmptyState message至少需要两次体重记录才能生成趋势图 /; } return ( LineChart data{chartData} width{300} height{200} color#8B5CF6 thickness{2} dataPointsColor#8B5CF6 curved areaChart startFillColor#8B5CF6 startOpacity{0.3} endOpacity{0.05} / ); }健康分析还有一个重要功能是异常检测。比如体重在短时间内下降超过10%或者疫苗间隔超过推荐周期系统会给出提示。export function detectAnomalies(events: Event[]): Anomaly[] { const anomalies: Anomaly[] []; const weightEvents events .filter(e e.type weight) .sort((a, b) a.date.localeCompare(b.date)); for (let i 1; i weightEvents.length; i) { const prev JSON.parse(weightEvents[i - 1].metadata || {}).value; const curr JSON.parse(weightEvents[i].metadata || {}).value; if (prev curr) { const change ((curr - prev) / prev) * 100; if (Math.abs(change) 10) { anomalies.push({ type: weight, severity: warning, message: 体重在${weightEvents[i].date}变化了${change.toFixed(1)}%建议关注, }); } } } return anomalies; }实操心得异常检测的阈值不要设得太敏感。我一开始设了5%结果正常波动也会触发提示用户会觉得烦。后来改成10%并加上“建议关注”而不是“异常警告”体验好很多。4. 常见问题与排查技巧实录4.1 数据库迁移失败怎么办这是新手最容易遇到的问题。典型症状是App启动时报“no such table: pets”或者迁移文件找不到。排查步骤确认drizzle.config.ts中的schema路径正确确认npx drizzle-kit generate成功生成了SQL文件确认db/migrations/migrations.ts文件存在且导出了迁移数据确认initDatabase在根布局的useEffect中被调用如果迁移文件生成了但App还是报错大概率是migrations.ts没有正确导出。Drizzle Kit生成的迁移文件需要有一个入口文件汇总// db/migrations/migrations.ts import journal from ./meta/_journal.json; import m0000 from ./0000_initial.sql; export default { journal, migrations: { m0000, }, };这个文件Drizzle Kit不会自动生成需要手动创建。我当初就是卡在这里Claude Code生成的代码里没有这个文件后来手动补上才跑通。4.2 通知不触发或延迟触发通知问题排查表症状可能原因解决方案完全不触发权限未授予检查requestPermission返回值Android不触发未设置通知渠道调用setNotificationChannelAsync延迟触发系统省电策略引导用户关闭电池优化重复触发旧通知未取消删除提醒时调用cancelReminder时间不对时区问题用ISO字符串存储调度时转Date对象时区问题特别隐蔽。如果你用new Date(2024-01-01)在UTC8时区会解析成2023-12-31T16:00:00Z。正确的做法是用new Date(2024-01-01T00:00:00)明确指定本地时间。4.3 Expo Router页面跳转参数丢失Expo Router用文件路由跳转时传参有两种方式路径参数和查询参数。路径参数/pet/[id]通过useLocalSearchParams()获取。 查询参数/pet/detail?idxxx同样通过useLocalSearchParams()获取。坑在于如果参数值是中文或特殊字符需要encodeURIComponent编码。我遇到过宠物名字带空格导致路由匹配失败的情况后来统一做了编码处理。4.4 性能优化长列表卡顿当事件记录超过500条时时间轴列表会明显卡顿。解决方案是用FlatList的getItemLayout属性避免动态测量用React.memo包裹事件卡片组件分页加载每次只加载最近100条图片用expo-image替代Image它有更好的缓存机制const ITEM_HEIGHT 80; const getItemLayout (_, index) ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index, });实操心得getItemLayout要求列表项高度固定。如果你的卡片高度不固定这个优化用不了。我的做法是把卡片高度固定为80超出部分用省略号点击后进详情页看完整内容。4.5 Claude Code使用中的常见问题问题一生成的代码风格不一致解决方案在CLAUDE.md中明确编码规范并在每次对话开始时提醒它参考该文件。问题二修改一个文件时破坏了另一个文件解决方案让Claude Code在修改前先读取相关文件用“先读后写”的模式。指令可以这样写“先读取stores/petStore.ts和db/schema.ts然后修改petStore.ts中的addPet方法确保与schema中的字段一致。”问题三生成的依赖版本不兼容解决方案在CLAUDE.md中锁定关键依赖的版本号比如“Expo SDK 52React Native 0.76expo-router 4.x”。问题四上下文丢失Claude Code的上下文窗口有限长对话后会忘记之前的决策。解决方案是定期用/compact命令压缩上下文或者把关键决策记录到CLAUDE.md中。5. 项目扩展与个人体会5.1 后续可以扩展的方向这个项目的基础版本已经能跑通核心链路但还有很大的扩展空间。多设备同步目前数据只存在本地如果用户换手机数据就丢了。可以接入Supabase或Firebase做云端同步。但要注意宠物健康数据属于隐私数据同步方案必须支持端到端加密。宠物社交可以加入宠物档案分享功能生成漂亮的分享卡片。这个功能对增长很有帮助但要注意隐私边界用户可以选择分享哪些字段。AI健康助手接入大语言模型根据宠物的历史数据给出健康建议。比如“你的猫最近三个月体重下降了8%建议带去做甲状腺检查”。这个功能的技术门槛不高但需要专业的兽医知识库做支撑。多语言支持用i18n-js做国际化目前只支持中文扩展到英文和日文可以覆盖更多用户。5.2 我用Claude Code开发这个项目的真实感受说实话第一次用Claude Code搭建完整项目时我是持怀疑态度的。毕竟“AI写代码”这件事被吹了太多年实际用起来往往差强人意。但这个项目做完之后我的看法变了。Claude Code最大的价值不是“帮你写代码”而是“帮你保持项目一致性”。在传统开发中你写了一个模块过两天写另一个模块时可能忘了之前的接口设计导致风格不一致。Claude Code会读取项目上下文生成的代码风格和接口设计高度一致。这节省了大量重构时间。但它也不是万能的。数据库schema设计、提醒引擎的调度逻辑、异常检测的阈值设定这些需要业务判断的地方Claude Code给出的方案往往需要手动调整。我的经验是让Claude Code做“实现”你做“决策”。你告诉它要什么它帮你写出来但“要什么”这件事必须你自己想清楚。还有一个很实用的技巧当你遇到bug时直接把错误信息粘贴给Claude Code让它分析原因并给出修复方案。我实测下来对于运行时错误和类型错误它的诊断准确率很高。但对于逻辑错误比如提醒时间算错了它往往看不出来需要你自己调试。5.3 给想尝试的朋友几个建议如果你打算用Claude Code从零搭建一个App我有几个建议第一先把数据模型想清楚。数据模型是App的骨架骨架错了后面全是返工。花一个小时画ER图比花一天改代码划算得多。第二小步提交。每完成一个模块就git commit一次。Claude Code有时候会改坏东西有commit记录你可以随时回滚。第三不要完全信任生成的代码。Claude Code生成的代码大部分是对的但边界条件处理经常有问题。比如空数组、null值、网络超时这些情况它往往不会主动处理。你需要自己检查并补充。第四善用CLAUDE.md。这个文件是你的“项目宪法”写得越详细Claude Code的表现越好。我现在的CLAUDE.md有200多行涵盖了技术栈、目录结构、编码规范、命名约定、错误处理模式等。第五保持学习。Claude Code是工具不是替代品。你仍然需要理解React Native的生命周期、SQLite的查询优化、通知调度的工作原理。工具越强越需要你有判断力。这个项目我前后花了大约三天时间完成基础版本如果纯手写估计要两周。效率提升是实实在在的但前提是你知道自己在做什么。如果你完全不懂React NativeClaude Code也救不了你——它生成的代码你连调试都无从下手。所以把它当作一个超级高效的结对编程伙伴而不是一个全自动的代码生成器。你负责方向和决策它负责实现和细节。这个分工模式下效率提升最明显。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑