You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When you're writing composition functions, you'll inevitably find yourself in situations where you need to bind data to an element, update classes or styles, or add an event listener to an element.
Example:
In a WAI-ARIA compliant listbox/combobox, the list of options (e.g. ul element) should have an aria-activedescendant attribute whose value is the HTML id of the active list option (e.g. li element).
In turn, each option in the list should have an aria-selected attribute whose value is true or false based on whether or not they are the active descendant.
It would be great to handle this logic inside a composition function by doing the following:
Creating a ref for the id of the active option
Creating a ref for the list of options' DOM elements
Using watchEffect to watch the idref, and when it changes, patch the aria-activedescendant value and all the aria-selected values on the DOM elements
Returning the DOM element refs from the composition function, so that end users can attach them where they need to go in the template. Code example below to illustrate the developer experience:
Inside watchEffect, the ideal solution is to patch attributes using the same logic that Vue uses internally to support v-bind in single file components.
The problem is that there is no way to access/import that logic from Vue's API.
If I'm not mistaken, that logic is implemented in patchProp:
For some projects I'm currently working on, I re-implemented that logic as additional composition functions in a package I maintain:
useBindings for binding attributes, classes, and styles (both static and reactive bindings)
useListeners for adding event listeners, and removing before the component unmounts
But I personally would prefer if Vue exposed their implementation of that logic, since it would allow composition function authors to avoid third party rewrites of code that is getting shipped in every Vue app regardless.
What does the proposed API look like?
import{ref,onMounted,watchEffect,patchProp}from'vue'exportdefaultfunctionuseListbox(...){constactiveDescendantId=ref(''),listElement=ref(null),optionsElements=ref([]),updateActiveDescendantId=(newId)=>{// Update activeDescendantId per WAI-ARIA specifications}onMounted(()=>{watchEffect(()=>{patchProp(listElement.value,'aria-activedescendant',activeDescendantId.value)optionsElements.forEach(element=>{constisSelected=activeDescendantId.value===element.idpatchProp(element,'aria-selected',isSelected)})})})return{list: {ref: listElement},options: {// Since the options ref gets bound to a v-for, it's required to be a function ref// with a little extra logic inside.// // https://v3.vuejs.org/guide/composition-api-template-refs.html#usage-inside-v-forref(el){optionsEls.value=[...optionsEls.value,el]},}}}
Found another great use case for patching props inside composition functions! I was recently writing a composition function inspired by Nuxt's Vue Meta to handle SEO-related reactive updates to pages' head content. Here's a small sample of its use:
In that use case, it would be useful to access Vue's internal methods for adding nodes (since meta and link tags need to be created on the fly, based on user input) and for patching attributes on those nodes.
Looking back at my original comment here, I'm unsure if patchProps from @vue/runtime-dom is the correct code to expose. Is there a lower level implementation that patches VNodes instead of DOM nodes? If so, it would be awesome to access that implementation inside composition functions to make sure updates are efficiently scheduled, and to make sure code is reusable across different renderers.
And for a much more thorough and interesting example of how I'm patching DOM nodes from inside functions, see this composition function for a keyboard-accessible "tablist" widget with reactive ARIA roles for accessibility:
What problem does this feature solve?
When you're writing composition functions, you'll inevitably find yourself in situations where you need to bind data to an element, update classes or styles, or add an event listener to an element.
Example:
In a WAI-ARIA compliant listbox/combobox, the list of options (e.g.
ul
element) should have anaria-activedescendant
attribute whose value is the HTMLid
of the active list option (e.g.li
element).In turn, each option in the list should have an
aria-selected
attribute whose value istrue
orfalse
based on whether or not they are the active descendant.It would be great to handle this logic inside a composition function by doing the following:
ref
for theid
of the active optionref
for the list of options' DOM elementswatchEffect
to watch theid
ref
, and when it changes, patch thearia-activedescendant
value and all thearia-selected
values on the DOM elementsref
s from the composition function, so that end users can attach them where they need to go in the template. Code example below to illustrate the developer experience:Inside
watchEffect
, the ideal solution is to patch attributes using the same logic that Vue uses internally to supportv-bind
in single file components.The problem is that there is no way to access/import that logic from Vue's API.
If I'm not mistaken, that logic is implemented in
patchProp
:https://github.com/vuejs/vue-next/blob/425335c28bdb48f2f48f97021fc0a77eaa89ec34/packages/runtime-dom/src/patchProp.ts
For some projects I'm currently working on, I re-implemented that logic as additional composition functions in a package I maintain:
useBindings
for binding attributes, classes, and styles (both static and reactive bindings)useListeners
for adding event listeners, and removing before the component unmountsBut I personally would prefer if Vue exposed their implementation of that logic, since it would allow composition function authors to avoid third party rewrites of code that is getting shipped in every Vue app regardless.
What does the proposed API look like?
For a more complete example of why it's useful to bind attributes and handle event listeners inside composition functions, see this source code for a composition-function-powered, fully WAI-ARIA compliant listbox/combobox widget.
The text was updated successfully, but these errors were encountered: