vuejs / rfcs

RFCs for substantial changes / feature additions to Vue core
4.85k stars 549 forks source link

Add impassive event modifier !passive #572

Closed wangf1978 closed 9 months ago

wangf1978 commented 1 year ago

What problem does this feature solve?

In modern browsers, for some events, for example, wheel, touchstart and so on, if you want to add event listener to it, passive option with true or false need to be specified explicitly, otherwise browser will report some warnings like as:

image

In some scenario, this default behavior has to be prevented like as using the below code

    <div v-if="img.focused == true && img.selected == false" class="photo_selection" 
            v-on:click="on_toggle_photo_checkbox(img, true, $event, imgTypePos + start_list_idx_in_vw)"
            v-on:touchstart.prevent="on_toggle_photo_checkbox(img, true, $event, imgTypePos + start_list_idx_in_vw)">

but there is no way to specify passive: false to vue runtime-dom https://github.com/vuejs/core/tree/main/packages/runtime-dom/src/modules)/events.ts

image

tons of warnings will be reported by the latest chrome and edge console

What does the proposed API look like?

https://github.com/vuejs/core/tree/main/packages/runtime-dom/src/modules)/events.ts

@[touchstart|wheel....].prevent.!passive
v-on:[touchstart|wheel....].prevent.!passive

const optionsModifierRE = /(?:Once|Passive|!Passive|Capture)$/

function parseName(name: string): [string, EventListenerOptions | undefined] {
  let options: EventListenerOptions | undefined
  if (optionsModifierRE.test(name)) {
    options = {}
    let m
    while ((m = name.match(optionsModifierRE))) {
      name = name.slice(0, name.length - m[0].length)
      if (m[0][0] === '!')
         ;(options as any)[m[0].slice(1).toLowerCase()] = false
      else
        ;(options as any)[m[0].toLowerCase()] = true
    }
  }
  const event = name[2] === ':' ? name.slice(3) : hyphenate(name.slice(2))
  return [event, options]
}
redblobgames commented 1 year ago

If you're referring to https://chromestatus.com/feature/5093566007214080 it sounds like it only applies when touchstart is added to the document, not when its added to a div. I've been trying to come up with a reproduction with a vue div that will trigger that warning, but haven't been able to. Do you have a reproduction e.g. sfc.vuejs.org ? Here's what I tried:

https://sfc.vuejs.org/#eNptks9OAyEQxl9lQkzUaFmjt7X1z8HEB/DIQUqnuygLBGZrms2+uwO17cVNljB8A/xmPibxGqPcjShascwm2UiQkcb4pDyAHWJIBFPC7QzbFAa45NTLIpXfIYELHayAE66UUOL6KG1Hb8gGX/S3HXq6wjJew1RU3ho6udNuRLhZwWfVWriY6kTSPuIMNoPR3qDTa4fPJ/G8NivlP8txs/LL5gDP2BwQDtFpwlrEcmN38GKcNd8rJY48TFtB+HuhMJo+k04kY6q3/J+Yae+QpbU2310Ko9+0YPbaP0KPtuu5ggccHuHHbqhv4f6uBGPGtMjo0LDsg0clKhXAOyYsRWpgQAkfaQ9nEODWDSgrf8N63VN5clsXGfRpmhhynpdNCUoPTnWLW3HwbjHoKL9y8Oxvbb36E7IS7dEMJdjVEivRE8XcNk3emvIqvrIMqWt4JtPoyTIS5mGxTuGH6+KDD91hA2Yx/wLqBsgX

When I add touchstart to the document, .cancelable is false (meaning it's passive). But touchstart on the div has .cancelable true (meaning it's active)

sodatea commented 9 months ago

I can reproduce the warning with the above playground link: image