You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的事件绑定是累加式的——旧的事件处理函数不会被覆盖,而是和新的函数一起保留。每次点击就会触发所有绑定过的处理函数,导致执行次数翻倍。

修复步骤

  1. 先清除旧事件,再绑定新事件
    在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
}
  1. 移除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(...)
  1. DRY原则优化
  • 抽离样式设置逻辑为单独函数,比如setButtonDefaultStyle(button)、setButtonSelectedStyle(button),减少重复代码。
  • 将事件绑定逻辑封装为bindButtonEvents(button, date),在refreshCalender中统一调用。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 07:11:05