Wix日期范围日历Button onClick事件触发次数翻倍问题排查
问题:日历按钮点击事件执行次数翻倍
在Wix平台基于JavaScript类开发日期范围日历,功能基本正常,但每次点击按钮时,onClick事件处理函数的执行次数会翻倍(第一次点击执行1次,第二次2次,第三次4次,以此类推)。怀疑问题出在onClick触发的函数内的回调调用,但不确定原因,也希望在保持代码DRY的前提下修复程序。
点击触发的selectDate函数
export async function selectDate(date, id) { console.log("clicked") const dates = await calender.pickDate(date) if(dates.checkIn && dates.checkOut) { $w("#text18").text = `${dates.checkIn} - ${dates.checkOut}` $w("#group1").hide("slide", {"direction": "top", "duration": 500}) timeline.reverse() const newDates = await calender.renderCalender() await refreshCalender(newDates) } else if(dates.message) { const newDates = await calender.renderCalender() await refreshCalender(newDates) } else { const newDates = await calender.renderCalender() await refreshCalender(newDates) $w(`#${id}`).style.backgroundColor = "#0E1F58" $w(`#${id}`).style.color = "#FFFFFF" $w(`#${id}`).style.borderColor = "#ffba00" $w(`#${id}`).onMouseIn(() => $w(`#${id}`).style.backgroundColor = "#0E1F58") $w(`#${id}`).onMouseOut(() => { $w(`#${id}`).style.backgroundColor = "#0E1F58" $w(`#${id}`).style.color = "#FFF" }) if(Number(id) + 7 < 38) { for(let i = 1; i < 8; i++) { let button = $w(`#${Number(id) + i}`) button.style.backgroundColor = "#BBC8F4" i === 3 || i === 4 || i === 7 ? button.style.borderColor = "#ffba00" : "" } } } return }
类中的renderCalender函数
renderCalender() { let date = new Date(this.date) let calenderDays = [] let dayOfTheWeek = date.getDay() let countForeward = 0 let countBackwards = dayOfTheWeek for(let i = 0; i <= 38; i++) { let day = new Date(date) if(countBackwards >= 0) { calenderDays.push(new Date(day.setDate(day.getDate() - countBackwards))) countBackwards-- } else { countForeward ++ calenderDays.push(new Date(day.setDate(day.getDate() + countForeward))) } } return calenderDays }
refreshCalender函数
export function refreshCalender(dates) { console.log(dates) for(let i = 0; i < dates.length; i++) { let button = $w(`#${i}`) let current = dates[i] button.label = (current.getDate()).toString() if(current.getMonth() <= currentDate.getMonth() && current.getFullYear() <= currentDate.getFullYear() && currentDate.getTime() >= current.getTime()) { button.disable() } else { button.enable() button.style.color = "#0E1F58" button.style.backgroundColor = "#FFFFFF" button.style.borderColor = current.getMonth() === calender.date.getMonth() ? "#000000" : "#B0AAA9" button.onClick(() => selectDate(current, button.id)) button.onMouseIn(() => { button.style.backgroundColor = "#0E1F58" button.style.color = "#FFFFFF" }) button.onMouseOut(() => { button.style.backgroundColor = "#FFFFFF" button.style.color = "#0E1F58" }) } } return null }
问题原因与修复方案
核心原因
每次调用refreshCalender时,都会给按钮重新绑定onClick、onMouseIn、onMouseOut事件。而Wix的事件绑定是累加式的——旧的事件处理函数不会被覆盖,而是和新的函数一起保留。每次点击就会触发所有绑定过的处理函数,导致执行次数翻倍。
修复步骤
- 先清除旧事件,再绑定新事件
在refreshCalender中,给按钮绑定新事件前,先清除原有事件。如果Wix支持off方法,直接调用清除;否则可以绑定空函数覆盖:
export function refreshCalender(dates) { console.log(dates) for(let i = 0; i < dates.length; i++) { let button = $w(`#${i}`) let current = dates[i] button.label = (current.getDate()).toString() // 清除原有事件绑定 button.off("click") button.off("mouseIn") button.off("mouseOut") if(current.getMonth() <= currentDate.getMonth() && current.getFullYear() <= currentDate.getFullYear() && currentDate.getTime() >= current.getTime()) { button.disable() } else { button.enable() button.style.color = "#0E1F58" button.style.backgroundColor = "#FFFFFF" button.style.borderColor = current.getMonth() === calender.date.getMonth() ? "#000000" : "#B0AAA9" button.onClick(() => selectDate(current, button.id)) button.onMouseIn(() => { button.style.backgroundColor = "#0E1F58" button.style.color = "#FFFFFF" }) button.onMouseOut(() => { button.style.backgroundColor = "#FFFFFF" button.style.color = "#0E1F58" }) } } return null }
- 移除
selectDate中的重复事件绑定
在selectDate的else分支里,无需重新绑定鼠标事件,直接修改样式即可——refreshCalender已经处理了默认的鼠标行为,选中状态的样式可以直接设置,避免再次累加事件:
// 替换selectDate中else分支的事件绑定代码 $w(`#${id}`).style.backgroundColor = "#0E1F58" $w(`#${id}`).style.color = "#FFFFFF" $w(`#${id}`).style.borderColor = "#ffba00" // 移除以下两行事件绑定代码 // $w(`#${id}`).onMouseIn(...) // $w(`#${id}`).onMouseOut(...)
- DRY原则优化
- 抽离样式设置逻辑为单独函数,比如
setButtonDefaultStyle(button)、setButtonSelectedStyle(button),减少重复代码。 - 将事件绑定逻辑封装为
bindButtonEvents(button, date),在refreshCalender中统一调用。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

