
1. 第一周学小程序先别急着写代码把生态位置看清楚如果说前端开发里还有什么东西是“看起来简单、上手就懵”的微信小程序绝对排得上号。很多新人第一天打开开发者工具看到左侧模拟器、中间代码区、右侧调试器再扫一眼默认生成的 index 页面和 logs 页面第一反应往往是“这不就是写网页吗”——然后一写就发现完全不是那么回事。页面路径要注册、样式单位换成了 rpx、数据更新必须走 setData、很多 HTML 标签不能用、图片路径处理方式也不一样到处都是“潜规则”。所以我给建议第一周别急着写代码先把小程序在微信生态里的位置搞清楚。它不是网页也不是原生 App而是一种运行在微信客户端里的“特定容器应用”。用户不需要下载安装扫个码、搜一下、从聊天记录里点进来就能打开用完关掉也不用卸载。这种形态解决的核心问题是“触达成本”一个 App 动辄几十 MB一个网页又没法调用系统能力小程序正好卡在中间——体积小、加载快、能拿手机硬件能力同时开发成本比双端原生低不少。从技术实现上说小程序走的是“双线程模型”逻辑层运行在 JavaScript 引擎里视图层由原生组件渲染两边通过一套异步消息机制通信。这也是为什么小程序里不能像网页那样直接操作 DOM所有界面更新都要靠数据驱动。第一周你不必把双线程的每个细节都吃透但必须建立这个意识它不是“套壳网页”你想用 jQuery 那种“直接改 DOM”的思路去写注定踩坑。那第一周的目标应该定成什么按我带过不少新人的经验第一周能完成三件事就算合格第一注册账号、装好工具、跑通默认项目第二看懂一个页面从“文件”到“显示在屏幕上”的全过程第三亲手写一个能响应点击、能输入、能更新列表的小页面。至于组件库、云开发、分包加载、自定义组件那是后面几周的事第一周碰它们只会让你心态崩。2. 环境搭建的细节注册、AppID和开发者工具首跑2.1 账号和 AppID 到底卡在哪里整个环境搭建流程里九成新人卡在同一个地方搞不清楚 AppID 是什么、去哪拿、为什么必须要。简单说AppID 就是你的小程序身份证在微信公众平台注册账号之后创建一个小程序应用系统会分配一串唯一的 ID。它在后续所有环节都要用开发者工具登录、真机预览、上传代码、配置服务器域名、开通云开发全都认这个 ID。这里有一个第一周新手最常用的“捷径”注册账号的时候如果只是本地练习可以选“测试号”不需要绑定小程序。但我的建议是只要你确定要长期学老老实实注册一个个人主体的小程序账号拿到正式的 AppID。原因很简单测试号很多能力是残缺的比如没法开通云开发、某些 API 调用会受影响、后续你想把代码传到手机上看真实效果流程也会绕。注册过程本身不复杂按公众平台引导填信息就行个人主体不需要营业执照身份证就能搞定。提示注册时“小程序名称”可以先随便起一个后面还能改名。但注意个人主体的小程序在类目上有限制第一周不涉及发布不用纠结这一点。2.2 下载工具和新建项目的正确姿势开发者工具直接去微信官方文档页面下稳定版就好不要追预览版除非你特别喜欢当小白鼠。装好之后用微信扫码登录然后新建项目这一步有几个选项值得说清楚AppID 填正式的不要选“测试号”后端服务选“不使用云服务”模板选 JavaScript 基础模板而不是 TypeScript 模板或云开发模板。如果你是第一次接触我强烈建议第一周先用 JavaScript 基础模板。TypeScript 本身没错但它在第一周会给你增加一层“类型系统”的认知负担而你现在需要的是先搞懂“小程序本身的工作方式”。云开发模板同理它默认给你塞了一堆云函数代码新手根本分不清哪些是前端、哪些是云端很容易糊里糊涂。新建完项目你会看到默认生成了一堆文件。先不要急着删每一个都有意义。接下来要做的事情只有一件点“编译”看模拟器里出现一个带头像和“Hello World”字样的页面。这一步跑通了说明你的工具链没问题整个第一周的技术路线就有了地基。2.3 工具栏里最该先认识的三个区域项目跑起来之后先把开发者工具的界面布局认一遍这比多写十行代码更值。模拟器在左边它模拟的是手机屏幕上的渲染效果第一周你的代码好不好看、布局对不对全看这里。中间是代码编辑区本质上是带语法高亮的文本编辑器。右边的调试器长得非常像 Chrome DevTools里面有 Console、Sources、Network、Wxml 等面板其中 Wxml 面板是小程序特有的后面调试页面结构时你会经常用到它。顶部工具栏还有两个高频按钮“预览”和“真机调试”。预览会生成一个二维码手机扫码后能在微信里打开你的小程序真机调试则会在手机上打开带调试信息的小程序可以在手机上看到 console 日志。它们的作用不一样预览看效果真机调试查问题。第一周只需要会用预览就够了真机调试等到第二周再说。3. 默认项目的结构拆解全局配置、页面四件套和注册逻辑3.1 一堆文件里真正的主心骨是 app.json新手打开项目目录看到 app.js、app.json、app.wxss、pages 文件夹、utils 文件夹、project.config.json很容易犯晕。这里我给你一个记忆锚点小程序里一切全局配置都写在 app.json一切应用生命周期逻辑写在 app.js一切全局样式写在 app.wxss。而项目里真正铺开的一片片页面全部放在 pages 目录下。重点讲 app.json因为第一周你会在它身上踩最多的坑。它长这样{ pages: [ pages/index/index, pages/logs/logs ], window: { navigationBarBackgroundColor: #ffffff, navigationBarTitleText: 我的小程序, navigationBarTextStyle: black }, style: v2, sitemapLocation: sitemap.json }这里最核心的是pages字段。它是一个数组里面每一项都是一个页面的路径数组第一项就是小程序启动后展示的首页。很多人第一周会犯一个错新建了一个页面文件但没有写进pages数组结果编译报错“page not found”或者明明写了文件但模拟器里死活不显示。记住在小程序里页面文件要生效必须先在这里注册。window字段管的是全局窗口样式比如顶部导航栏的背景色、标题文字、文字颜色。它属于全局默认值但注意每个页面自己的.json文件可以覆盖它这个后面再说。3.2 页面四件套WXML、WXSS、JS、JSON 的分工一个页面由四个同名的文件组成比如 index 页面就是 index.wxml、index.wxss、index.js、index.json。这个设计是整个小程序开发最重要的心智模型没有之一。WXML 负责结构类似 HTML但标签是受限的比如用view代替div用text代替span还有image、input、button等一套组件。写 MDN 上的那些 HTML 标签在这里基本不能直接用会报“unknown component”之类的错误。WXSS 负责样式语法和 CSS 高度一致但多了一套尺寸单位 rpx也多了一些小程序特有的选择器限制。WXSS 里你也可以用import引入其他样式文件但第一周先不玩这些专心把基础语法弄熟。JS 负责逻辑包括页面数据、生命周期函数、事件处理等。它是整个页面的“大脑”没有 JS页面就只是一堆静态的骨架和样式点什么都不会有反应。JSON 负责页面级配置比如这个页面自己的标题、导航栏样式、是否允许下拉刷新等。它是可选的如果你的页面没有特殊需求一个空对象{}也能正常跑。这四份文件靠“同名同路径”绑定在一起。你删掉其中任何一个另外三个就只能“单腿走路”页面很可能直接报错或空白。我在实践中发现很多第一周的问题并非逻辑写错而是文件结构不完整导致的。3.3 页面是怎么被“找到”的以及为什么 index 和 logs 能无缝切换从打开小程序到看到页面内容整个链路其实是这样的app.json 里的pages数组指定了页面路径小程序启动后先加载数组第一项对应的 JS 文件执行里面的生命周期函数拿到data再把 WXML 模板和数据“合成”渲染视图。默认项目里的 index 页面有一个“点击跳转 logs”的入口用的其实是wx.navigateTo这个 API。你可以大概看一下它的调用方式wx.navigateTo({ url: /pages/logs/logs })这个url里写的路径必须和 app.jsonpages数组里的路径完全一致少个斜杠、多个.wxml后缀都会白屏。这种“注册—跳转—展示”的闭环第一周一定要亲手走通几次后面写任何页面都离不开这个套路。4. 第一周实战做一个“今日清单”页面4.1 先写静态结构感受 WXML 和 HTML 的差别理论看太多没用是时候动手了。第一周我推荐做一个“今日清单”一个输入框、一个添加按钮、一个列表、一个清空按钮。功能虽然简单但数据绑定、列表渲染、事件绑定、输入处理这几个核心知识点全都能练到。先在 app.json 的pages数组里加一项pages/todo/todo建好对应目录和四个文件。然后打开 todo.wxml写初始结构view classpage view classheader text classtitle今日清单/text /view view classinput-area input classinput placeholder输入要做的事 / button classadd-btn sizemini添加/button /view view classlist view classlist-item wx:for{{list}} wx:keyid text{{item.name}}/text /view /view button classclear-btn sizemini清空/button /view注意两个地方第一HTML 里用来包文字的div和span在这里换成了view和text。text里如果要用空格或换行也没有 HTML 那么随意它默认会压缩连续空格需要时得用decode属性或写实体字符。第二wx:for{{list}}就是循环渲染列表里的每一项通过item变量访问这比在 JS 里拼字符串优雅太多了。4.2 数据绑定和列表渲染不要把页面写死静态结构写完接下来是核心中的核心数据驱动视图。打开 todo.js先给页面定义初始数据Page({ data: { list: [], inputValue: } })页面的数据都放在data对象里而 WXML 里凡是{{ }}包裹的东西都会去data里找对应的值。这种“写数据页面自动变”的思路对做过 Vue 或 React 的人来说很亲切但小程序有个关键区别你不能直接给 data 里的属性赋值来更新视图必须用this.setData()。比如下面这种写法是无效的this.data.list.push({ id: 1, name: 写代码 }) // 数据变了视图不动正确写法是这样的this.setData({ list: [...this.data.list, { id: Date.now(), name: 写代码 }] })setData会把你传入的新数据同步到逻辑层然后通知视图层重新渲染。第一周可以先把“视图更新必须走 setData”这句话背下来后面踩过的很多坑都是从这里来的。4.3 输入框和按钮的事件绑定从“看”到“动”静态列表没意思现在让它动起来。先给输入框绑定一个输入事件再给按钮绑定点击事件input classinput placeholder输入要做的事 value{{inputValue}} bindinputonInput / button classadd-btn sizemini bindtapaddItem添加/button对应的 JS 逻辑Page({ data: { list: [], inputValue: }, onInput(e) { this.setData({ inputValue: e.detail.value }) }, addItem() { const name this.data.inputValue.trim() if (!name) { return } this.setData({ list: [...this.data.list, { id: Date.now(), name }], inputValue: }) } })这里有几个细节值得注意。第一bindinput和bindtap是小程序自带的事件绑定写法不需要 addEventListener。第二事件处理函数里能拿到一个事件对象e而输入框的当前值是e.detail.value这个detail属性是理解组件事件的关键。第三Date.now()在这里作为列表项的 id虽然第一周不用考虑太复杂但wx:key必须给否则列表更新时可能出现渲染错乱也会在控制台看到警告。清空按钮就更好写了clearList() { this.setData({ list: [] }) }写到这里一个能输入、能添加、能清空的页面就跑通了。虽然丑但整套数据驱动逻辑你已经完整走了一遍。4.4 样式和 rpx为什么你的字号和手机上对不上很多新手写完 WXML马上开始写 WXSS然后遇到第一个玄学问题在 iPhone 模拟器上看着正好的字号换个安卓手机就变大了或者设计稿里是 750 宽自己照着写了width: 375px结果右边多出一大块空白。原因是 rpx 这个单位。小程序规定无论什么机型屏幕宽度都按 750rpx 来算。也就是750rpx 屏幕宽度。在 iPhone 6/7/8 这类逻辑宽度为 375px 的机型上1rpx 等于 0.5px在大屏安卓上1rpx 对应更多 px。所以你写width: 375rpx时它永远是屏幕宽度的一半而不是死死钉在 375 像素。第一周我把经验值给你设计稿按 750 宽来做写样式时直接用标注的 px 数值把单位换成 rpx 就行。例如设计稿里字体是 32px你就写font-size: 32rpx。这样开发效率最高也不用做复杂的换算。注意rpx 只适合用来定尺寸和间距。涉及边框、阴影这类需要精确保 1px 的场景建议用px或1rpx不然在某些低分辨率机型上边框会忽粗忽细。5. Debugger 和 Console第一周就学会看报错5.1 常见报错第一梯队路径没注册、组件不存在、AppID 不合法写代码不报错是不可能的。第一周遇到报错不可怕怕的是“对着屏幕发呆不知道去哪看原因”。我先把第一周最高频的三类报错列出来你可以直接对照着查第一类page not found或Please check your pages config。这种基本就是你新建了页面文件但忘了在 app.json 的pages数组里注册。解决方案就一句话把页面路径加进去保存重新编译。第二类Unknown component。这是你在 WXML 里写了小程序没有的组件名比如写了div、span、a或者拼错了组件名字。正确做法是全部换成小程序组件view、text、image、button、input等。第三类AppID 不合法或invalid appid。这是项目配置里的 AppID 和登录账号不匹配。如果你用的是测试号却在代码里调用了需要正式 AppID 的功能也会报这类错误。解决方法是打开 project.config.json 检查 appid 字段或者干脆“重新登录”开发者工具。不管报什么错第一件事都是看 Console。小程序开发者工具的 Console 和浏览器的几乎一样红色是错误、黄色是警告点开能看到详细堆栈。养成“一报错就看 Console”的习惯这个动作能帮你节省第一周至少一半的卡壳时间。5.2 Console 不只是看错用它验证你的每一个假设我见过不少新人Console 打开是用来“等报错”的不报错就不看。其实 Console 更大的价值是验证逻辑。第一周写“今日清单”的时候我建议你在关键位置打印日志onInput(e) { console.log(输入内容为, e.detail.value) this.setData({ inputValue: e.detail.value }) }这样你就能清楚看到每一次输入事件到底触发了没有、拿到的值是什么。很多“我写了代码但没反应”的问题本质都是“事件根本没绑定上”或“执行顺序和想象的不一样”一打印日志立刻现形。等你把事件、数据、渲染这个链路摸熟了自然会越来越依赖断言式的验证而不是靠肉眼看页面猜。5.3 用 Wxml 面板审查渲染结果Console 负责逻辑Wxml 面板负责看视图结构。点击调试器里的 Wxml 标签你会看到当前页面渲染出来的完整节点树。这个面板能帮你确认两件事一是数据是否真的渲染上去了二是节点结构是否符合预期。举个例子假设你wx:for写错页面一片空白但 Console 没有报错。这时候切到 Wxml 面板如果里面什么都看不到说明数据结构有问题如果看得到节点但文字空白说明是取值路径错了。这种“把问题二分”的排查思路第一周就要开始练。6. 第一周避坑清单五个让你卡到半夜的问题6.1 setData 过度传参页面卡得不能动新手刚学会 setData 之后很容易走另一个极端数据往 data 里堆setData 一次传一大堆。最典型的例子是把一个很大的表单对象甚至从接口拿来的整个列表原封不动 setData。小程序里 setData 每次调用都会做“逻辑层到视图层”的数据传输数据量越大、频率越高页面越卡。我给你的建议是三条能局部更新就不要整体更新和渲染无关的数据不要放 data频繁变化的数据比如拖拽坐标、动画参数尽量合并处理。第一周做今日清单完全碰不到性能瓶颈但提前养成这个习惯后面做复杂页面时你会感谢自己。6.2 wx:if 和 hidden 用混了wx:if和hidden都能控制元素显示隐藏但原理完全不同。wx:if是“条件不满足直接不渲染”hidden是“渲染了但藏起来”。如果需要频繁切换显示状态用hidden更合适因为不用反复创建销毁节点如果条件很少改变用wx:if更好省去初始渲染开销。第一周你只需要记住结论高频切换用 hidden低频切换用 wx:if。等第二周学性能优化时再回头探究这两者在渲染层上的差异都来得及。6.3 图片路径本地图还是网络图要分清楚小程序的 image 组件支持本地图片和网络图片但规则不一样。本地图片要放在项目目录下写相对路径或绝对路径都能用但要注意放在 CSS 里的本地图片路径某些情况下会失效比如背景图写在 WXSS 里且路径用了相对定位真机上报错是常有的事。网络图片则要求域名必须在小程序后台的“合法域名”里配置过否则线上环境加载不出来。第一周你如果只是想用图片优先把图片放到images目录在 WXML 里用/images/xxx.png这种绝对路径引用简单省事。6.4 页面 JSON 覆盖全局 window 时你觉得“改了没生效”还有一种常见状况在 app.json 里把导航栏标题改成了“我的小程序”跑起来发现某个页面的标题还是旧名字。问题出在页面自己的 json。如果你在页面的 json 里也配置了navigationBarTitleText它会把全局配置顶掉。小程序配置遵循“就近原则”页面级配置优先级高于全局配置。所以“为什么改了没生效”这个问题第一周出现时先去翻对应页面的 json 文件而不是怀疑编译器出 bug。等你习惯了这套覆盖规则这类问题基本就算绕过一大半了。6.5 生命周期光是听说过不知道从哪看起index.js 里默认写着onLoadlogs.js 里写着onLoad和onShow很多新手不太明白这些函数什么时候被调用。第一周你不用全都背只要理解一个最简单的顺序页面打开时先 onLoad再 onShow再 onReady页面被切入后台再回来会触发 onShow。像“今日清单”这个例子数据初始化写在 onLoad 里就行因为页面每次进入只创建一次。如果你想知道“这个生命周期到底触发没”和前面一样用 console.log 打印即可。实践中我发现把生命周期函数的调用时机用日志打出来比看十遍文档都管用。7. 第一周结束后下一步怎么走到了这里你已经具备了小程序开发的最基本骨架知道怎么建页面、怎么注册、怎么用 WXML 和 WXSS 拼界面、怎么用数据和事件让页面动起来、遇到报错知道去哪看。这周最重要的不是做出一个多完整的功能而是建立“数据驱动界面”的思维方式。接下来第二周我建议按这个顺序往下学先搞懂页面生命周期和组件传值也就是父组件怎么把数据传给子组件、子组件怎么把事件抛给父组件这是所有复杂页面交互的基础然后接触wx.request让页面能真的和服务器通信你会发现 list 不再只是写死在 data 里的假数据而是来自接口的真实内容再往后可以学习简单自定义组件把重复出现的页面片段抽出来复用这时你的模块化意识才算真正建立。第一周结束前给自己做个能力自检能不看文档说清app.json里pages数组的作用吗能解释为什么更新页面必须用setData吗能区分wx:for、wx:if和事件绑定的写法和用途吗如果都能下一周尽管放心往下冲。我自己的体会是小程序入门最难的一关其实不是语法而是“接受它的独特规则”。HTML 里那句话怎么说的用错误的方式也能写出看起来对的东西。小程序不行它的规则比网页开发严格得多。所以尽早把“为什么这套机制长这样”想通后面的路会顺很多。