主题
数据绑定、渲染与表单(一)
本页对应 数据绑定、渲染与表单,共 8 段视频,约 1 小时 27 分。
学习目标
- 能够独立完成小程序项目的导入:正确选择项目根目录、将 AppID 替换为自己的账号 AppID,并成功编译运行导入的静态结构项目。
- 能够正确使用插值表达式完成内容绑定与属性绑定,并能诊断
checked="false"这类因缺少花括号导致字符串被转为布尔真值的问题,以及引号与花括号之间多余空格引发的绑定异常。 - 能够使用
model:value在input/textarea上实现简易双向绑定,并说明其仅支持data第一级数据、不支持嵌套对象属性的限制。 - 能够使用
wx:if/wx:else控制元素渲染与否,使用hidden属性控制显示隐藏,并解释hidden底层通过display:none实现、与v-show逻辑相反。 - 能够使用
wx:for渲染对象数组和简单数组,正确访问默认的item/index,按规则书写wx:key(对象属性名或*this),并在嵌套循环场景下用wx:for-item/wx:for-index完成重命名。 - 能够编写
wx.request发起网络请求,完成合法域名配置与项目配置刷新,在success回调中通过箭头函数保证this指向页面实例,并用setData将返回数据渲染到页面;能够说明手机端请求白屏时开启开发调试模式的排查方法。
知识点
导入小程序:先选对代码目录

为什么需要:这一节不是从 0 到 1 新建项目,而是接手现成 demo 或公司项目。导入动作的本质,是让微信开发者工具把一个已经存在的目录识别为小程序项目。
怎么想:导入成功不成功,第一看目录选得对不对,第二看 AppID 能不能用。目录决定项目根目录,AppID 决定你有没有这个项目的开发身份。
怎么做:打开微信开发者工具,点击“导入项目”,也可以点界面上的导入图标;在第二天资料里找到提前搭好基本结构的项目文件夹(转写稿中提到的 MPde/demo 目录),进入项目目录后再选择该文件夹,不要只选最外层资料目录。选好后点确定,等待工具加载到能看见界面。
易错点:如果选到最外层,工具可能加载不到根目录下的资源;导入外部项目时,工具可能像 VS Code 一样弹出信任提示,点“信任”即可。导入后能看到页面和 tabBar 切换,说明基本跑起来了。
项目配置文件:appid 与 projectname
为什么需要:工具需要通过项目配置识别“这是哪个小程序”“项目显示叫什么”。笔记里明确列出两个字段:
text
appid 当前小程序的 AppID
projectname 当前小程序的项目名称怎么想:appid 是小程序账号的唯一标识,转写稿里把它比作“小程序的身份证”;projectname 只是项目名称,主要影响工具里的项目显示,不是运行身份。
怎么做:导入后查看项目配置,确认 appid 是当前要使用的小程序 AppID,projectname 是当前项目名称。若是自己的练习项目,就把 appid 换成自己的。
易错点:不要把 projectname 当成 AppID;也不要以为只改项目名就能获得开发权限。真正决定身份的是 appid。
变更 AppID:没有开发权限时换成个人 AppID
为什么需要:素材或公司项目默认带着别人的 AppID。一个账号注册后就有唯一 AppID,默认情况下你没有这个账号的开发权限,直接用会报错。笔记也写了“视情况而定,如果没有开发权限时需要变更成个人的 AppID”。
怎么想:AppID 相当于账号身份证,别人的身份证你默认用不了,除非对方授权。导入时如果 AppID 处报错,先判断是不是权限问题,而不是怀疑目录或代码。
怎么做:在导入界面或项目配置里,把 AppID 切换成自己的 AppID,点确定,等待重新加载。转写稿的调试过程是:选择项目文件夹后 AppID 处出现报错,因为当前账号不是该 AppID 的开发者;切换成自己的 AppID 后确定,最终成功看到界面。
易错点:不要忽略 AppID 报错直接往下做;切换后要确认工具重新加载成功。若弹出信任框,点信任;若没看到界面,先检查目录和 AppID,而不是急着重写代码。
导入后的验证与参考项目
为什么需要:导入不是“文件存在”就结束,而是要确认工具能编译、能显示页面。转写稿还提到第三天素材是已写好的作业参考项目,方便对照布局。
怎么想:验证标准是界面能出现、tabBar 能切换、页面结构能加载。参考项目同样通过“导入项目”查看,不需要从零复制。
怎么做:等待加载完成,看到页面后点一下 tabBar 切换;需要看作业参考时,再导入第三天素材项目。转写稿还提醒:设计稿里导航标题的加粗不用纠结,小程序原生标题不能靠普通样式随意改,真正需要自己写布局的是中间内容区;首页圆角上跨可用负 margin-top 调整。
易错点:不要把“导入参考项目”误当成新建项目;不要在设计稿标题样式上耗太久;导入动作本身不难,关键是“找对文件夹、换对 AppID、确认能运行”。
模板语法与数据绑定:先理解“指令”
小程序的模板语法,本质上就是“把 data 渲染到页面”的语法。Vue 里叫指令,小程序里更多体现为 wx: 开头的控制属性和 {{}} 插值。为什么需要先讲这个?因为后面条件渲染、列表渲染都绕不开数据绑定;怎么想?先记住一条:小程序模板里但凡要绑定数据,无论是内容还是属性,都要写 {{}}。怎么做?内容绑定用插值,属性绑定也写进引号内的 {{}}。易错点:属性值不写 {{}} 时,它只是字符串,不是布尔值或数字。
笔记中的演示代码如下:
xml
<!-- 数据绑定 -->
<view class="binding">
<!-- 开关组件 -->
<switch checked="{{isOpen}}"/>
<!-- 双向数据绑定 -->
<input type="text" model:value="{{message}}" />
<view class="message">{{message}}</view>
</view>javascript
Page({
data: {
isOpen: true,
message: 'hello world!'
}
})课堂调试时先写 <switch checked="false" />,发现开关仍然是选中状态。原因不是组件坏了,而是 "false" 是字符串;字符串非空,转成布尔就是 true。改成 checked="{{false}}" 后才是真正的布尔 false。同理,引号和花括号之间不要留多余空格,例如 checked=" {{false}}" 可能把空格带进字符串,仍可能被转成真值。这里要纠正一个常见口误:不是“划括号”,是“花括号” {{}}。
简易双向绑定:model:value 的适用范围
为什么需要双向绑定?因为表单输入后要同步回 data,否则页面改了、数据没变。怎么想?Vue 用 v-model,小程序用 model:value,但它是“简易双向绑定”。怎么做?在 input、textarea 的 value 前加 model:,写成 model:value="{{message}}"。易错点:它目前只支持 input 和 textarea;只支持 data 第一级数据,不能绑定 form.name 这类嵌套对象;使用时可能出现“未定义事件处理函数”的警告,课堂演示中官方暂未消除,可忽略。调试时在输入框输入内容,观察 AppData 里 message 是否同步变化;不加 model: 时只是单向显示。
条件渲染:wx:if / wx:else 与 hidden
为什么需要条件渲染?因为登录/未登录、加载中/加载完成要按状态显示不同结构。怎么想?要“创建或销毁结构”用 wx:if;只控制显示隐藏用 hidden。怎么做?wx:if="{{isLogin}}" 为真渲染,wx:else 紧跟在 wx:if 后,不能单独使用;hidden="{{loaded}}" 为真时隐藏,底层是属性选择器 [hidden] { display: none; }。易错点:hidden 与 Vue 的 v-show 逻辑相反,v-show 为真显示,hidden 为真隐藏;实际写加载状态时常用取反思路。课堂调试时把 isLogin 改成 false,页面从“大师兄”切到“游客”;把 loaded 改成 true,“正在加载...”消失。
xml
<!-- 条件渲染 wx:if 和 wx:else -->
<view class="welcome">
<text wx:if="{{isLogin}}">大师兄</text>
<text wx:else>游客</text>你好:
</view>
<!-- 条件渲染 hidden -->
<view class="loading">
<!-- 可以单独使用 -->
<!-- <text wx:if="{{!loaded}}">正在加载...</text> -->
<text hidden="{{loaded}}">正在加载...</text>
</view>javascript
Page({
data: {
isOpen: true,
message: 'hello world!',
isLogin: true,
loaded: false
}
})列表渲染:wx:for、wx:key 与默认变量
为什么需要列表渲染?因为数组数据要重复生成结构。怎么想?Vue 用 v-for,小程序用 wx:for;默认变量名是 item 和 index,可直接使用。怎么做?写 wx:for="{{students}}",内部用 item.name、item.age,索引用 index。wx:key 不要写 {{}}:对象数组写属性名,如 wx:key="id";简单数组推荐 wx:key="*this"。易错点:不写 wx:key 会有性能警告;写成 wx:key="item.id" 会提示写法不对;简单数组写 wx:key="item" 可能不报错,但并不是官方推荐写法。课堂调试时先渲染 item.id、item.name,再观察警告,改成 wx:key="id" 后警告消失。
xml
<!-- 列表渲染 -->
<view class="students">
<view class="item">
<text>序号</text>
<text>姓名</text>
<text>年龄</text>
<text>性别</text>
<text>级别</text>
</view>
<view class="item">
<text>1</text>
<text>贺洋</text>
<text>20</text>
<text>男</text>
<text>菜鸟</text>
</view>
</view>
<!-- 简单数组 -->
<view class="history">
<text>小米</text>
</view>javascript
Page({
data: {
isOpen: true,
message: 'hello world!',
isLogin: true,
loaded: false,
students: [
{id: 1, name: '贺洋', age: 20, gender: '男', level: '菜鸟'},
{id: 2, name: '唐刚', age: 18, gender: '女', level: '笨鸟'},
{id: 3, name: '常超', age: 20, gender: '女', level: '老鸟'}
],
history: ['苹果', '华为', 'OPPO', '三星']
}
})列表渲染补充:改名与嵌套循环
为什么需要改名?因为嵌套循环时内外层都叫 item、index 会冲突。怎么想?只有嵌套循环才需要改,普通列表不用改。怎么做?用 wx:for-item="stu" 改单元变量名,用 wx:for-index="idx" 改索引名;改名时只写名称,不要写 {{}}。易错点:改名后原来的 item、index 就失效了,内部要全部换成新名字;写成 wx:for-item="{{stu}}" 反而变成绑定变量,容易出错。调试时先把 wx:for-item 改成 stu,页面数据不显示,说明原变量名已失效;再把内部 item.name 改成 stu.name,数据恢复。这样就能理解“改名不是装饰,而是作用域变量替换”。
课件图示








代码示例
示例 1:数据绑定与简易双向绑定(pages/binding/index.wxml / .js / .wxss)
xml
<!-- pages/binding/index.wxml -->
<view class="binding">
<!-- 开关组件:属性绑定必须写 {{}} -->
<switch checked="{{isOpen}}" />
<!-- 简易双向绑定:只能用在 input / textarea -->
<input type="text" model:value="{{message}}" />
<!-- 内容绑定 -->
<view class="message">{{message}}</view>
</view>javascript
// pages/binding/index.js
Page({
data: {
isOpen: true,
message: 'hello world!'
}
})css
/* pages/binding/index.wxss */
.binding {
padding: 30rpx;
}
.message {
margin-top: 20rpx;
font-size: 32rpx;
color: #333;
}要点解释与易错点
checked="{{isOpen}}":小程序里属性和内容一样都要用{{}},写checked="false"只是字符串'false',非空字符串会被转成布尔true,开关反而是选中的;必须写checked="{{false}}"。- 引号与花括号之间不要留空格:
checked="{{ false }}"里的空格会被当成内容一起参与转换,最终又变成true。 model:value="{{message}}"是简易双向绑定,等价于value+input事件的简写;只支持input和textarea,且只支持 data 的第一级数据,model:value="{{form.name}}"这种嵌套写法不生效。- 使用
model:value时控制台会提示缺少事件处理函数,这是官方未修复的已知警告,直接忽略即可。
示例 2:条件渲染与 hidden 隐藏(pages/condition/index.wxml / .js / .wxss)
xml
<!-- pages/condition/index.wxml -->
<!-- wx:if / wx:else:控制结构是否渲染 -->
<view class="welcome">
<text>你好:</text>
<text wx:if="{{isLogin}}">大师兄</text>
<text wx:else>游客</text>
</view>
<!-- hidden:结构一定渲染,靠样式隐藏 -->
<view class="loading">
<text hidden="{{loaded}}">正在加载...</text>
</view>javascript
// pages/condition/index.js
Page({
data: {
isLogin: true,
loaded: false
}
})css
/* pages/condition/index.wxss */
[hidden] {
display: none;
}
.loading {
margin-top: 20rpx;
font-size: 28rpx;
color: #999;
}要点解释与易错点
wx:if必须写花括号:wx:if="false"拿到的是字符串'false',非空字符串为真,内容仍会渲染。wx:else不能单独使用,且必须紧跟在wx:if之后,中间不能插入其他节点。hidden与v-show的语义相反:v-show是“为真显示”,hidden是“为真隐藏”,所以控制加载态时通常写成hidden="{{loaded}}"(加载完成就隐藏)。hidden底层就是[hidden] { display: none; }这一条属性选择器样式,元素本身仍存在于结构中,需要频繁切换显示隐藏时用它,需要彻底销毁/重建时用wx:if。
示例 3:列表渲染与 wx:key(pages/list/index.wxml / .js / .wxss)
xml
<!-- pages/list/index.wxml -->
<view class="students">
<!-- 表头 -->
<view class="item">
<text>序号</text>
<text>姓名</text>
<text>年龄</text>
<text>性别</text>
<text>级别</text>
</view>
<!-- 对象数组:wx:key 只写属性名,不加 {{}} -->
<view class="item" wx:for="{{students}}" wx:key="id">
<text>{{index + 1}}</text>
<text>{{item.name}}</text>
<text>{{item.age}}</text>
<text>{{item.gender}}</text>
<text>{{item.level}}</text>
</view>
</view>
<!-- 简单数组:wx:key 用保留关键字 *this -->
<view class="history">
<text wx:for="{{history}}" wx:key="*this">{{item}}</text>
</view>
<!-- 循环嵌套时改名:wx:for-item / wx:for-index -->
<view class="students" wx:for="{{students}}" wx:key="id" wx:for-item="stu" wx:for-index="idx">
<text>{{idx + 1}} - {{stu.name}}</text>
</view>javascript
// pages/list/index.js
Page({
data: {
students: [
{ id: 1, name: '贺洋', age: 20, gender: '男', level: '菜鸟' },
{ id: 2, name: '唐刚', age: 18, gender: '女', level: '笨鸟' },
{ id: 3, name: '常超', age: 20, gender: '女', level: '老鸟' }
],
history: ['苹果', '华为', 'OPPO', '三星']
}
})css
/* pages/list/index.wxss */
.item {
display: flex;
padding: 16rpx 0;
border-bottom: 1rpx solid #eee;
font-size: 28rpx;
}
.item text {
flex: 1;
text-align: center;
}
.history {
margin-top: 20rpx;
font-size: 28rpx;
}要点解释与易错点
wx:for="{{students}}"直接写数组本身,不像 Vue 那样写item in students;item(循环项)和index(下标,从 0 开始)是默认变量名,可直接使用。wx:key不写花括号:对象数组写属性名wx:key="id",写成wx:key="{{item.id}}"会收到警告;简单数组用保留关键字wx:key="*this"表示用元素本身作唯一标识。- 不写
wx:key会给出性能提示警告,加上后数据更新时可最大化复用原有节点。 - 只有循环嵌套才需要改名:
wx:for-item="stu"、wx:for-index="idx",改名后原来的item/index在该层失效;改名时只写名称,不要写{{}}。 - 小程序没有
table标签,表格式布局只能靠 flex 等样式自己实现。
常见错误
导入后编译报错 / 无法预览,AppID 处飘红 现象:点击导入后项目打不开,或提示无权限、无法真机预览。 原因:素材里的
appid是别人的(的账号),你不在该小程序的开发者列表中,AppID 相当于账号身份证,默认无权使用。 修法:导入时或导入后在「详情 → 基本信息」把 AppID 换成自己的;确实没有权限时改用测试号 / 无 AppID 模式。导入后页面空白、找不到 app.json 或资源 404 现象:工具提示找不到入口文件,图片、样式全部丢失。 原因:选择目录时选到了项目的上一级(如选了「第二天资料」而不是里面的
mp-demo),导致读不到根目录下的配置和资源。 修法:重新导入,目录要选到含app.json的那一层,确认左侧文件树里直接能看到app.json、pages再点确定。<switch checked="false" />依然是打开状态 现象:明明写了false,开关却是选中的。 原因:没有用{{}}绑定,"false"是非空字符串,转布尔后为true;同理checked="{{false}} "(花括号与引号间多一个空格)也会变成"false "而恒为真。 修法:写成checked="{{false}}",并检查花括号内外不要留多余空格。wx:if="isLogin"永远为真,wx:else从不出现 现象:改数据后视图不切换,wx:else分支永远不显示。 原因:小程序无论属性绑定还是内容绑定都必须写{{}},不写就是字符串,非空字符串恒为真;另外wx:else必须紧跟wx:if,中间不能插别的节点。 修法:改成wx:if="{{isLogin}}",wx:else紧贴上一行书写。列表渲染报警告,或
wx:key写了却不生效 现象:控制台提示需要wx:key;或写了wx:key="{{item.id}}"、wx:key="item"依旧警告。 原因:wx:key里不加花括号,且对象数组只写属性名(如id),简单数组要用保留字*this;写item/index/ 任意单词都不会报错但属于无效写法。 修法:对象数组wx:key="id",字符串数组wx:key="*this"。model:value="{{form.name}}"视图不更新 现象:输入框能打字,但页面数据不跟着变。 原因:小程序是简易双向绑定,只支持data的第一级字段,不支持对象嵌套。 修法:把字段提到data一级(如message),或退回value+bindinput手动setData。嵌套循环里内外层
item打架,取不到外层数据 现象:两层wx:for时,内层拿到的永远是内层数据,外层数据取不到。 原因:item/index是默认变量名,内层循环把它们覆盖了。 修法:用wx:for-item/wx:for-index改名,只写名称不加{{}},如wx:for-item="stu"。
练习
导入第二天的素材项目:先用默认 AppID 观察报错信息,再切换为自己的 AppID 成功运行;然后用同样的方式导入第三天的参考项目,说出两次导入时你选择目录的判断依据。
在页面中放一个
<switch>和一个<input>:要求开关的初始状态为关闭(用数据绑定控制),输入框用model:value与页面文字实时同步;写完后故意把checked="{{isOpen}} "加一个空格,观察现象并解释原因,再改回来。用
wx:if/wx:else实现「已登录显示用户名、未登录显示游客」,再用hidden实现同一效果的「正在加载…」提示块;对比两种方式在元素是否被创建上的差别(用调试器 Elements 面板验证)。把
students数组渲染成表格,要求:序号用索引 +1 显示、wx:key使用唯一标识;再把history简单数组渲染成列表并写出正确的wx:key。给列表加上一层嵌套:外层循环班级、内层循环学生,通过
wx:for-item/wx:for-index改名后,在每一项前同时显示「班级名 + 学生名 + 外层序号 + 内层序号」。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 反馈-复习-学习目标 | 15:31 |
| 2 | 导入小程序 | 08:40 |
| 3 | 数据绑定和简易双向绑定 | 11:49 |
| 4 | 条件渲染和样式隐藏 | 09:59 |
| 5 | 列表渲染-核心语法 | 14:59 |
| 6 | 列表渲染-改变量名补充 | 04:41 |
| 7 | 网络请求-基本语法和服务器配置 | 13:11 |
| 8 | 网络请求-渲染数据 | 08:11 |
小结
- 导入他人项目 = 选对根目录(含
app.json)+ 换成自己的 AppID,两步缺一不可。 - 小程序没有指令的
v-前缀,统一换成wx:,并且属性绑定也必须写{{}},这是从 Vue 迁移过来最容易翻车的地方。 - 布尔属性只认真正的布尔值,字符串
"false"和带空格的"false "都会变成真,写完顺手检查花括号与引号的间距。 wx:if控制「创建/销毁」,hidden只控制display: none,前者当v-if、后者当v-show的反向理解来用。wx:for默认提供item/index,wx:key不写花括号、对象数组写属性名、简单数组写*this。- 循环嵌套时必须用
wx:for-item/wx:for-index改名,且改名处同样不加{{}}。 model:value只是「简易」双向绑定,仅限input/textarea且只能绑data一级字段,出现警告属官方已知问题,忽略即可。- 语法差异只是表层,真正要练的是「数据结构 → 视图结构」的映射思维,写法记不住就查文档、看编辑器悬停提示。