同时使用Mousedown和TouchStart更改按钮内容类,反之亦然

发布于 2025-01-26 06:54:11 字数 2519 浏览 1 评论 0原文

我有一个包含子组件的按钮,该按钮由一个由Div制成的圆圈组成。当用户用鼠标单击或触摸屏幕时,我希望圆圈更改颜色。我尝试了 this 有点不错,但是有些不对劲,因为只有touchstart事件并没有导致类改变。

我尝试在父母和子女中记录flag的值,甚至手动检查元素以查看类是否更改。奇怪的是,记录到控制台的值是正确的。当我触摸按钮时,flag是TRUE,color.valuegreen,但在检查时(通过按F12),Child DOM中的组件类是RED

我尝试使用由SVG构建的不同的儿童组件,并且发生了同样的事情。问题必须与事件有关。我在某个地方了解到,touchstart/touchend事件将首先触发,然后是mousedown/mouseup然后单击。因此,我正在考虑仅响应Mousedown/MouseUp,同样的问题正在发生。

我还尝试评论//建议的解决方案,均适用于Mousedown和TouchStart,但是对于触摸start,颜色更改和按钮反应(本机按钮按动画)之间存在

延迟我发生了什么事?以及如何使按钮在触摸并单击时对其进行反应和更改其内容样式?

感谢任何评论或帮助。非常感谢。

我的按钮组件

<template>
<button class="slot-header slot-header-btn"
   ref="btn"
   @mousedown="cb"
   @mouseup="cbEnd"
>
        <Child :flag="pressed"/>
</button>
</template>

<script>
import { ref } from "vue"
import Child from './assets/Child.vue'

const pressed = ref<boolean>(false)

function cb(event: any) {
  // Suggested solution
  console.log("Mouse down")
  if(event.handled === false) return
  event.stopPropagation()
  event.preventDefault()
  event.handled = true

  // My own logic
  pressed.value = true
}
function cbEnd(event: any) {
  // Suggested solution
  console.log("Mouse up")
  if(event.handled === false) return
  event.stopPropagation()
  event.preventDefault()
  event.handled = true

  // My own logic
  pressed.value = false
}
</script>

我的孩子组件

<template>
  <div :class="`circle ${color}`">

  </div>
</template>

<script setup lang="ts">
import { computed, PropType, toRefs, watch } from 'vue';


const props = defineProps({
  flag: {
    type: Boolean as PropType<boolean>,
    required: false,
    default: () => false
  }
})


const { flag } = toRefs(props)

const color = computed<string>(() => flag.value ? "green" : "red")

watch(() => flag.value, (newValue, oldValue) => {
  console.log(`Child color.value: ${color.value}`)
  console.log(`Child flag.value: ${newValue}`)
})

</script>

<style scoped>
.circle {
  width: 20px;
  height: 20px;
  border-radius: 50%;
}

.red {
  background-color: red;
}

.green {
  background-color: greenyellow;
}
</style>

I have a button containing a child component which consists of a circle made with a div. I want the circle to change color when the user clicks with a mouse or touches the screen. I tried this and it kinda works but something is wrong because only the touchstart event is not causing the class to change.

I tried logging the value of flag in both the parent and child and even inspected the element manually to see if the class changed. The weird thing is, the values logged to the console are correct. When I touch-and-hold the button, flag is true and color.value is green but upon inspection (by pressing F12), Child component's class in the DOM is still red.

I tried using a different child component which is built from SVG and the same thing happens. The problem must be with the events. I learnt somewhere that touchstart/touchend events will be triggered first, followed by mousedown/mouseup then click. So I was thinking of just responding to mousedown/mouseup, to which the same problem is occuring.

I also tried commenting out the // Suggested solutions which worked for both mousedown and touchstart but for touchstart there was a delay between the color change and the button reacting(the native button press animation)

Can someone explain to me what is going on? And how I can enable the button to react and change its content's styles upon touch and click?

Would appreciate any comments or help. Thank you very much.

My Button component

<template>
<button class="slot-header slot-header-btn"
   ref="btn"
   @mousedown="cb"
   @mouseup="cbEnd"
>
        <Child :flag="pressed"/>
</button>
</template>

<script>
import { ref } from "vue"
import Child from './assets/Child.vue'

const pressed = ref<boolean>(false)

function cb(event: any) {
  // Suggested solution
  console.log("Mouse down")
  if(event.handled === false) return
  event.stopPropagation()
  event.preventDefault()
  event.handled = true

  // My own logic
  pressed.value = true
}
function cbEnd(event: any) {
  // Suggested solution
  console.log("Mouse up")
  if(event.handled === false) return
  event.stopPropagation()
  event.preventDefault()
  event.handled = true

  // My own logic
  pressed.value = false
}
</script>

My Child component

<template>
  <div :class="`circle ${color}`">

  </div>
</template>

<script setup lang="ts">
import { computed, PropType, toRefs, watch } from 'vue';


const props = defineProps({
  flag: {
    type: Boolean as PropType<boolean>,
    required: false,
    default: () => false
  }
})


const { flag } = toRefs(props)

const color = computed<string>(() => flag.value ? "green" : "red")

watch(() => flag.value, (newValue, oldValue) => {
  console.log(`Child color.value: ${color.value}`)
  console.log(`Child flag.value: ${newValue}`)
})

</script>

<style scoped>
.circle {
  width: 20px;
  height: 20px;
  border-radius: 50%;
}

.red {
  background-color: red;
}

.green {
  background-color: greenyellow;
}
</style>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文