微信小程序事件传值

小程序中通过事件传递数据的几种方式

问题

微信小程序中,如何在事件触发时传递自定义数据?

解答

方式一:data-* 自定义属性

最常用的方式,通过 data-* 属性传值,在事件对象的 currentTarget.dataset 中获取。

<!-- index.wxml -->
<view 
  wx:for="{{list}}" 
  wx:key="id"
  data-id="{{item.id}}"
  data-name="{{item.name}}"
  bindtap="handleTap"
>
  {{item.name}}
</view>
// index.js
Page({
  data: {
    list: [
      { id: 1, name: '苹果' },
      { id: 2, name: '香蕉' }
    ]
  },

  handleTap(e) {
    // 通过 dataset 获取传递的数据
    const { id, name } = e.currentTarget.dataset
    console.log(id, name) // 1, '苹果'
  }
})

方式二:mark 传值

mark 会包含从触发事件的节点到根节点上所有的 mark: 属性值,适合嵌套组件传值。

<!-- index.wxml -->
<view mark:parentId="100" bindtap="handleTap">
  <button mark:childId="200">点击</button>
</view>
// index.js
Page({
  handleTap(e) {
    // mark 会收集事件路径上所有节点的 mark 数据
    console.log(e.mark) // { parentId: 100, childId: 200 }
  }
})

方式三:传递索引值

在列表中常用,传递当前项的索引。

<!-- index.wxml -->
<view 
  wx:for="{{list}}" 
  wx:key="id"
  data-index="{{index}}"
  bindtap="handleDelete"
>
  {{item.name}}
  <text>删除</text>
</view>
// index.js
Page({
  data: {
    list: [
      { id: 1, name: '任务1' },
      { id: 2, name: '任务2' }
    ]
  },

  handleDelete(e) {
    const { index } = e.currentTarget.dataset
    const list = this.data.list.filter((_, i) => i !== index)
    this.setData({ list })
  }
})

target 与 currentTarget 的区别

<view data-parent="父元素" bindtap="handleTap">
  <text data-child="子元素">点击我</text>
</view>
Page({
  handleTap(e) {
    // target: 触发事件的源头元素
    console.log(e.target.dataset) // { child: '子元素' }
    
    // currentTarget: 绑定事件的元素
    console.log(e.currentTarget.dataset) // { parent: '父元素' }
  }
})

关键点

  • data-* 属性名会转为小写,data-userId 变成 dataset.userid
  • 使用 currentTarget.dataset 获取绑定事件元素的数据,target.dataset 获取触发事件元素的数据
  • mark 会向上收集所有父节点的 mark 数据,适合嵌套场景
  • 传递对象时需要用 {{item}},不能直接写字符串