Open AlexVipond opened 3 years ago
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:
useHead({
title: computed(() => context.article.frontMatter.title),
metas: [
{
property: 'og:title',
content: computed(() => context.article.frontMatter.title)
},
{
property: 'og:description',
content: computed(() => context.article.frontMatter.summary ?? '')
},
{
property: 'og:image',
content: computed(() => context.article.frontMatter.image ?? '')
},
{
property: 'og:url',
content: computed(() => route.fullPath),
},
]
})
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.
Here's a link to my useHead
composition function in case anyone is curious how I'm hacking around this reactive SEO problem: https://github.com/baleada/vue-features/blob/main/src/features/useHead.js
And here's a full collection of DOM patching behavior that I've reimplented for use across my composition functions: https://github.com/baleada/vue-features/tree/main/src/affordances
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.