Skip to content

数据与事件

数据绑定与渲染

小程序使用 Page() 函数中 data 对象来管理页面的数据,并通过一种特殊的语法将数据与 WXML 绑定在一起,实现数据驱动视图。

数据绑定

使用双大括号 可以将 JavaScript 数据绑定到 WXML 中。

javascript
// index.js
Page({
  data: {
    message: "Hello World",
    count: 0,
    isLogin: true,
    userInfo: {
      name: "张三",
      age: 25
    },
    color: "red"
  }
})
html
<!-- index.wxml -->
<view>{{message}}</view>
<view>计数:{{count}}</view>
<view>用户名:{{userInfo.name}}</view>
<view>年龄:{{userInfo.age + 1}}</view> <!-- 支持简单运算 -->
<view style="color: {{color}};">动态样式</view>
<checkbox checked="{{isLogin}}"></checkbox> <!-- 属性绑定也需要 {{}} -->

关键点:

  • 内容、组件属性、控制属性、关键字都需要使用
  • 支持简单的 JavaScript 表达式(三元运算、算术运算、逻辑判断等)
  • 中可以直接引用 data 中的属性路径

条件渲染 wx:if

根据条件来决定是否渲染某个组件块。

html
<!-- 基本用法 -->
<view wx:if="{{condition}}">条件为真时显示</view>
<view wx:elif="{{anotherCondition}}">另一个条件为真时显示</view>
<view wx:else>以上条件都不满足时显示</view>

<!-- 实际示例 -->
<view wx:if="{{isLogin}}">
  <text>欢迎回来,{{userName}}!</text>
  <button>退出登录</button>
</view>
<view wx:else>
  <button bindtap="onLogin">点击登录</button>
</view>

<!-- 控制多个组件:使用 block -->
<block wx:if="{{isLoading}}">
  <view>加载中...</view>
  <view>请稍候</view>
</block>

wx:if vs hidden

  • wx:if:是惰性的,条件为假时组件不会被渲染,有更高的切换开销
  • hidden:组件始终会被渲染,只是通过样式控制显示/隐藏,有更高的初始渲染开销

使用建议:

  • 需要频繁切换时用 hidden
  • 运行时条件不大可能改变时用 wx:if

列表渲染 wx:for

根据数组数据循环渲染组件。

javascript
// index.js
Page({
  data: {
    students: [
      { id: 1, name: "小明", score: 85 },
      { id: 2, name: "小红", score: 92 },
      { id: 3, name: "小刚", score: 78 }
    ],
    numbers: [10, 20, 30, 40, 50]
  }
})
html
<!-- 基本用法 -->
<view wx:for="{{students}}" wx:key="id">
  索引:{{index}} - 姓名:{{item.name}} - 分数:{{item.score}}
</view>

<!-- 指定索引和项的变量名 -->
<view wx:for="{{numbers}}" wx:for-index="idx" wx:for-item="num" wx:key="*this">
  第{{idx + 1}}个数字是:{{num}}
</view>

<!-- 嵌套循环 -->
<view wx:for="{{classes}}" wx:key="classId">
  <text>班级:{{item.className}}</text>
  <view wx:for="{{item.students}}" wx:key="id" wx:for-index="studentIndex">
    学生{{studentIndex + 1}}:{{item.name}}
  </view>
</view>

wx:key 的重要性:

  • 用于标识列表项目的唯一性,提高渲染性能
  • 可以指定为数组项的某个属性(如 id
  • 如果数组项是简单类型,可以用 *this(表示数组项本身)

事件系统

事件是视图层到逻辑层的通信方式,用户的操作(点击、输入等)会触发相应的事件。

绑定事件 bindtap、bindinput 等

事件绑定的写法类似 HTML 的属性,以 bindcatch 开头,后面跟事件类型。

html
<!-- 点击事件 -->
<button bindtap="onButtonTap">点击我</button>

<!-- 输入事件 -->
<input bindinput="onInputChange" placeholder="请输入内容" />

<!-- 长按事件 -->
<view bindlongpress="onLongPress">长按我</view>

<!-- 触摸事件 -->
<view bindtouchstart="onTouchStart" bindtouchend="onTouchEnd">触摸我</view>

常见事件类型:

  • tap:点击
  • longpress:长按(推荐代替 longtap
  • input:输入
  • change:改变(如 picker, switch)
  • submit:表单提交
  • scroll:滚动

bind vs catch

  • bind:绑定的事件不会阻止事件冒泡
  • catch:绑定的事件会阻止事件冒泡
html
<!-- 点击 inner 会触发 onInnerTap 和 onOuterTap -->
<view bindtap="onOuterTap">
  <view bindtap="onInnerTap">inner (bind)</view>
</view>

<!-- 点击 inner 只会触发 onInnerTap,不会触发 onOuterTap -->
<view bindtap="onOuterTap">
  <view catchtap="onInnerTap">inner (catch)</view>
</view>

事件对象

当事件触发时,逻辑层绑定的处理函数会收到一个事件对象,包含丰富的属性。

javascript
Page({
  onButtonTap: function(event) {
    // 事件对象包含的信息:
    console.log('事件类型:', event.type); // "tap"
    console.log('时间戳:', event.timeStamp);
    console.log('触发组件:', event.target); // 触发事件的源组件
    console.log('当前组件:', event.currentTarget); // 绑定事件的当前组件
    console.log('触摸点信息:', event.touches); // 触摸事件特有的触摸点数组
    console.log('事件详情:', event.detail); // 额外信息,不同事件有不同的值
  },
  
  onInputChange: function(event) {
    // 对于 input 事件,detail.value 是输入的值
    console.log('输入的值:', event.detail.value);
    this.setData({
      inputValue: event.detail.value
    });
  }
})

event.detail 的常见值:

  • tap{x, y}(点击位置的坐标)
  • input{value, cursor}(输入的值和光标位置)
  • submit{value}(表单数据)
  • change:根据组件不同而不同(如 switch 返回 {value}

传递自定义参数 data-*

在组件中可以通过 data-* 属性传递自定义数据,在事件处理函数中通过 event.currentTarget.dataset 获取。

html
<!-- 传递单个参数 -->
<button 
  bindtap="onItemTap" 
  data-id="123" 
  data-name="张三"
>
  用户123
</button>

<!-- 在循环中传递当前项的数据 -->
<view wx:for="{{students}}" wx:key="id">
  <button 
    bindtap="onStudentTap"
    data-student="{{item}}"  <!-- 传递整个对象 -->
    data-index="{{index}}"
  >
    {{item.name}}
  </button>
</view>

<!-- 也可以传递到子组件 -->
<navigator 
  url="/pages/detail/detail" 
  bindtap="onNavTap"
  data-from="homepage"
  data-type="product"
>
  跳转到详情
</navigator>
javascript
Page({
  onItemTap: function(event) {
    const dataset = event.currentTarget.dataset;
    console.log('ID:', dataset.id); // "123"
    console.log('姓名:', dataset.name); // "张三"
    
    // 可以跳转到详情页,携带参数
    wx.navigateTo({
      url: `/pages/detail/detail?id=${dataset.id}`
    });
  },
  
  onStudentTap: function(event) {
    const dataset = event.currentTarget.dataset;
    console.log('索引:', dataset.index);
    console.log('学生信息:', dataset.student); // 整个学生对象
    
    // 注意:通过 data- 传递的对象会被转成 JSON 字符串
    // 接收时又会被转回对象,但会失去方法
  },
  
  onNavTap: function(event) {
    console.log('来源:', event.currentTarget.dataset.from); // "homepage"
    console.log('类型:', event.currentTarget.dataset.type); // "product"
  }
})

data-* 的命名规则:

  • 在 WXML 中:data-xxx-yyy
  • 在 JS 中:通过 dataset.xxxYyy 访问(驼峰命名)
  • 例如:data-user-iddataset.userId

示例:

html
<!-- 一个简单的计数器 -->
<view>
  <text>当前计数:{{count}}</text>
  <button bindtap="onIncrement" data-amount="1">+1</button>
  <button bindtap="onIncrement" data-amount="5">+5</button>
  <button bindtap="onReset">重置</button>
</view>
javascript
Page({
  data: {
    count: 0
  },
  
  onIncrement: function(event) {
    const amount = parseInt(event.currentTarget.dataset.amount);
    this.setData({
      count: this.data.count + amount
    });
  },
  
  onReset: function() {
    this.setData({
      count: 0
    });
  }
})
编程洪同学服务平台是一个广泛收集编程相关内容和资源,旨在满足编程爱好者和专业开发人员的需求的网站。无论您是初学者还是经验丰富的开发者,都可以在这里找到有用的信息和资料,我们将助您提升编程技能和知识。
专业开发
高端定制
售后无忧
站内资源均为本站制作或收集于互联网等平台,如有侵权,请第一时间联系本站,敬请谅解!本站资源仅限于学习与参考,严禁用于各种非法活动,否则后果自行负责,本站概不承担!