Skip to content

数据绑定、渲染与表单(一) ​

本页对应 数据绑定、渲染与表单,共 8 段视频,约 1 小时 27 分。

学习目标 ​

  1. 能够独立完成小程序项目的导入:正确选择项目根目录、将 AppID 替换为自己的账号 AppID,并成功编译运行导入的静态结构项目。
  2. 能够正确使用插值表达式完成内容绑定与属性绑定,并能诊断 checked="false" 这类因缺少花括号导致字符串被转为布尔真值的问题,以及引号与花括号之间多余空格引发的绑定异常。
  3. 能够使用 model:value 在 input/textarea 上实现简易双向绑定,并说明其仅支持 data 第一级数据、不支持嵌套对象属性的限制。
  4. 能够使用 wx:if/wx:else 控制元素渲染与否,使用 hidden 属性控制显示隐藏,并解释 hidden 底层通过 display:none 实现、与 v-show 逻辑相反。
  5. 能够使用 wx:for 渲染对象数组和简单数组,正确访问默认的 item/index,按规则书写 wx:key(对象属性名或 *this),并在嵌套循环场景下用 wx:for-item/wx:for-index 完成重命名。
  6. 能够编写 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="&#123;&#123;false&#125;&#125;" 后才是真正的布尔 false。同理,引号和花括号之间不要留多余空格,例如 checked=" &#123;&#123;false&#125;&#125;" 可能把空格带进字符串,仍可能被转成真值。这里要纠正一个常见口误:不是“划括号”,是“花括号” &#123;&#123;&#125;&#125;。

简易双向绑定:model:value 的适用范围 ​

为什么需要双向绑定?因为表单输入后要同步回 data,否则页面改了、数据没变。怎么想?Vue 用 v-model,小程序用 model:value,但它是“简易双向绑定”。怎么做?在 input、textarea 的 value 前加 model:,写成 model:value="&#123;&#123;message&#125;&#125;"。易错点:它目前只支持 input 和 textarea;只支持 data 第一级数据,不能绑定 form.name 这类嵌套对象;使用时可能出现“未定义事件处理函数”的警告,课堂演示中官方暂未消除,可忽略。调试时在输入框输入内容,观察 AppData 里 message 是否同步变化;不加 model: 时只是单向显示。

条件渲染:wx:if / wx:else 与 hidden ​

为什么需要条件渲染?因为登录/未登录、加载中/加载完成要按状态显示不同结构。怎么想?要“创建或销毁结构”用 wx:if;只控制显示隐藏用 hidden。怎么做?wx:if="&#123;&#123;isLogin&#125;&#125;" 为真渲染,wx:else 紧跟在 wx:if 后,不能单独使用;hidden="&#123;&#123;loaded&#125;&#125;" 为真时隐藏,底层是属性选择器 [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="&#123;&#123;students&#125;&#125;",内部用 item.name、item.age,索引用 index。wx:key 不要写 &#123;&#123;&#125;&#125;:对象数组写属性名,如 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" 改索引名;改名时只写名称,不要写 &#123;&#123;&#125;&#125;。易错点:改名后原来的 item、index 就失效了,内部要全部换成新名字;写成 wx:for-item="&#123;&#123;stu&#125;&#125;" 反而变成绑定变量,容易出错。调试时先把 wx:for-item 改成 stu,页面数据不显示,说明原变量名已失效;再把内部 item.name 改成 stu.name,数据恢复。这样就能理解“改名不是装饰,而是作用域变量替换”。

课件图示 ​

课件第2页:多⼀句没有,少⼀句不⾏,用更短时间,教会更实用的技术! ⾼级软件⼈才培训专家 l

课件第6页:多⼀句没有,少⼀句不⾏,用更短时间,教会更实用的技术! ⾼级软件⼈才培训专家 l

课件第8页:多⼀句没有,少⼀句不⾏,用更短时间,教会更实用的技术! ⾼级软件⼈才培训专家 l

课件第5页:多⼀句没有,少⼀句不⾏,用更短时间,教会更实用的技术! ⾼级软件⼈才培训专家 本

课件第7页:多⼀句没有,少⼀句不⾏,用更短时间,教会更实用的技术! ⾼级软件⼈才培训专家 本

课件第9页:多⼀句没有,少⼀句不⾏,用更短时间,教会更实用的技术! ⾼级软件⼈才培训专家 本

课件第10页:多⼀句没有,少⼀句不⾏,用更短时间,教会更实用的技术! ⾼级软件⼈才培训专家 l

课件第11页:多⼀句没有,少⼀句不⾏,用更短时间,教会更实用的技术! ⾼级软件⼈才培训专家 小

代码示例 ​

示例 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="&#123;&#123;isOpen&#125;&#125;":小程序里属性和内容一样都要用 &#123;&#123;&#125;&#125;,写 checked="false" 只是字符串 'false',非空字符串会被转成布尔 true,开关反而是选中的;必须写 checked="&#123;&#123;false&#125;&#125;"。
  • 引号与花括号之间不要留空格:checked="&#123;&#123; false &#125;&#125;" 里的空格会被当成内容一起参与转换,最终又变成 true。
  • model:value="&#123;&#123;message&#125;&#125;" 是简易双向绑定,等价于 value + input 事件的简写;只支持 input 和 textarea,且只支持 data 的第一级数据,model:value="&#123;&#123;form.name&#125;&#125;" 这种嵌套写法不生效。
  • 使用 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="&#123;&#123;loaded&#125;&#125;"(加载完成就隐藏)。
  • 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="&#123;&#123;students&#125;&#125;" 直接写数组本身,不像 Vue 那样写 item in students;item(循环项)和 index(下标,从 0 开始)是默认变量名,可直接使用。
  • wx:key 不写花括号:对象数组写属性名 wx:key="id",写成 wx:key="&#123;&#123;item.id&#125;&#125;" 会收到警告;简单数组用保留关键字 wx:key="*this" 表示用元素本身作唯一标识。
  • 不写 wx:key 会给出性能提示警告,加上后数据更新时可最大化复用原有节点。
  • 只有循环嵌套才需要改名:wx:for-item="stu"、wx:for-index="idx",改名后原来的 item / index 在该层失效;改名时只写名称,不要写 &#123;&#123;&#125;&#125;。
  • 小程序没有 table 标签,表格式布局只能靠 flex 等样式自己实现。

常见错误 ​

  1. 导入后编译报错 / 无法预览,AppID 处飘红 现象:点击导入后项目打不开,或提示无权限、无法真机预览。 原因:素材里的 appid 是别人的(的账号),你不在该小程序的开发者列表中,AppID 相当于账号身份证,默认无权使用。 修法:导入时或导入后在「详情 → 基本信息」把 AppID 换成自己的;确实没有权限时改用测试号 / 无 AppID 模式。

  2. 导入后页面空白、找不到 app.json 或资源 404 现象:工具提示找不到入口文件,图片、样式全部丢失。 原因:选择目录时选到了项目的上一级(如选了「第二天资料」而不是里面的 mp-demo),导致读不到根目录下的配置和资源。 修法:重新导入,目录要选到含 app.json 的那一层,确认左侧文件树里直接能看到 app.json、pages 再点确定。

  3. <switch checked="false" /> 依然是打开状态 现象:明明写了 false,开关却是选中的。 原因:没有用 &#123;&#123;&#125;&#125; 绑定,"false" 是非空字符串,转布尔后为 true;同理 checked="&#123;&#123;false&#125;&#125; "(花括号与引号间多一个空格)也会变成 "false " 而恒为真。 修法:写成 checked="&#123;&#123;false&#125;&#125;",并检查花括号内外不要留多余空格。

  4. wx:if="isLogin" 永远为真,wx:else 从不出现 现象:改数据后视图不切换,wx:else 分支永远不显示。 原因:小程序无论属性绑定还是内容绑定都必须写 &#123;&#123;&#125;&#125;,不写就是字符串,非空字符串恒为真;另外 wx:else 必须紧跟 wx:if,中间不能插别的节点。 修法:改成 wx:if="&#123;&#123;isLogin&#125;&#125;",wx:else 紧贴上一行书写。

  5. 列表渲染报警告,或 wx:key 写了却不生效 现象:控制台提示需要 wx:key;或写了 wx:key="&#123;&#123;item.id&#125;&#125;"、wx:key="item" 依旧警告。 原因:wx:key 里不加花括号,且对象数组只写属性名(如 id),简单数组要用保留字 *this;写 item / index / 任意单词都不会报错但属于无效写法。 修法:对象数组 wx:key="id",字符串数组 wx:key="*this"。

  6. model:value="&#123;&#123;form.name&#125;&#125;" 视图不更新 现象:输入框能打字,但页面数据不跟着变。 原因:小程序是简易双向绑定,只支持 data 的第一级字段,不支持对象嵌套。 修法:把字段提到 data 一级(如 message),或退回 value + bindinput 手动 setData。

  7. 嵌套循环里内外层 item 打架,取不到外层数据 现象:两层 wx:for 时,内层拿到的永远是内层数据,外层数据取不到。 原因:item / index 是默认变量名,内层循环把它们覆盖了。 修法:用 wx:for-item / wx:for-index 改名,只写名称不加 &#123;&#123;&#125;&#125;,如 wx:for-item="stu"。

练习 ​

  1. 导入第二天的素材项目:先用默认 AppID 观察报错信息,再切换为自己的 AppID 成功运行;然后用同样的方式导入第三天的参考项目,说出两次导入时你选择目录的判断依据。

  2. 在页面中放一个 <switch> 和一个 <input>:要求开关的初始状态为关闭(用数据绑定控制),输入框用 model:value 与页面文字实时同步;写完后故意把 checked="&#123;&#123;isOpen&#125;&#125; " 加一个空格,观察现象并解释原因,再改回来。

  3. 用 wx:if / wx:else 实现「已登录显示用户名、未登录显示游客」,再用 hidden 实现同一效果的「正在加载…」提示块;对比两种方式在元素是否被创建上的差别(用调试器 Elements 面板验证)。

  4. 把 students 数组渲染成表格,要求:序号用索引 +1 显示、wx:key 使用唯一标识;再把 history 简单数组渲染成列表并写出正确的 wx:key。

  5. 给列表加上一层嵌套:外层循环班级、内层循环学生,通过 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

小结 ​

  1. 导入他人项目 = 选对根目录(含 app.json)+ 换成自己的 AppID,两步缺一不可。
  2. 小程序没有指令的 v- 前缀,统一换成 wx:,并且属性绑定也必须写 &#123;&#123;&#125;&#125;,这是从 Vue 迁移过来最容易翻车的地方。
  3. 布尔属性只认真正的布尔值,字符串 "false" 和带空格的 "false " 都会变成真,写完顺手检查花括号与引号的间距。
  4. wx:if 控制「创建/销毁」,hidden 只控制 display: none,前者当 v-if、后者当 v-show 的反向理解来用。
  5. wx:for 默认提供 item / index,wx:key 不写花括号、对象数组写属性名、简单数组写 *this。
  6. 循环嵌套时必须用 wx:for-item / wx:for-index 改名,且改名处同样不加 &#123;&#123;&#125;&#125;。
  7. model:value 只是「简易」双向绑定,仅限 input / textarea 且只能绑 data 一级字段,出现警告属官方已知问题,忽略即可。
  8. 语法差异只是表层,真正要练的是「数据结构 → 视图结构」的映射思维,写法记不住就查文档、看编辑器悬停提示。