Using Vuetify Core Functionality - JessicaOPRD/docs GitHub Wiki
Vuetify offers many compositional mixins that may be helpful to developers who already use the Vuetify library.
🟢 Well-designed and get a lot of use
🟢 Standardized approach for many needed behaviors
🟢 Custom components built on them will be consistent with Vuetify library
🟢 Can import and use with ES5+ or Typescript
🟢 Good training wheels for learning re-usable Vue patterns
🟢 Handle many accessibility/Section 508 needs
🔴 Officially a private API that could change, so you will need to keep up with changes (or create own repo or copy into your project)
🔴 If unfamiliar with TypeScript, need to learn to read it or refer to compiled ES5 (which is not on GitHub?)
🟡 Vuetify source uses pattern that may be different to many Vue developers (render
instead of <template>
), but mixins can be used regardless of pattern in many cases
🔴 If using ES5 import, may add to your build size – I need to explore this more
Read more about Vue's render function and related features in the Vue docs.
Remember also that Vuetify encapsulates helpful re-usable functionality in base components that can be wrapped and re-used to create more advanced components. These components are typically not used on their own, but are good building blocks. Using them circumvents accessing the internal private API directly. Some examples are:
- VInput
- VItem and VItemGroup (must be used together)
Mixin | Factory? | Dependencies | Description |
---|---|---|---|
Groupable | ✔️ | Extends Registrable | ⚪ Use on components that can be grouped such a VChip and VBtn ⚪ Manages isActive property and active classes for component (the child) ⚪ Registers component (the child) to a parent namespace |
Registrable | ⛔ | ⚪ Uses provide /inject Vue feature to register/unregister children to parent namespace ⚪ Simplifies parent-child communication that otherwise needs to happen through $parent , scoped slots, or possibly store |
|
Selectable | ⛔ | Extends VInput | ⚪ Uses model Vue feature to describe model property and event (inputValue and change ) ⚪ Use for elements that have a raw HTML value property that means something other than selected/unselected in group contexts (VCheckbox , VSwitch , VRadio ) ⚪ Manages true /false value, color, creation of internal HTML checkbox, etc ⚪ Does not seem to work with Groupable , use Toggleable instead or see VRadio . |
Toggleable | ✔️ | ⚪ Uses model Vue feature to describe model property and event (value and input by default) ⚪ Manages value Boolean update and emit ⚪ Also uses isActive to determine state from prop value ⚪ Used by VChip , VBtn , VListItem
|
You can extend
existing components (see VCheckbox
), however there is a learning curve to the rendering methods if you are accustomed to Vue or Angular templates. Mostly these make good examples for developing similar components from base mixins.
Component | Dependencies | Description |
---|---|---|
VInput | Validatable | ⚪ Creates and manages its own internalVaue based on an internal model event ('input' by default) ⚪ Creates and manages its own computedId (which I think is Vue's _uid per component instance) ⚪ Renders template |
VItem | Groupable mixin | ⚪ Maintains internal isActive property managed by own toggle method ⚪ Maintains active class for item ⚪ Renders template |
VItemGroup | Groupable mixin (for register /unregister of child items) |
⚪ Tracks and manages child items via registrable registration ⚪ Assesses value of child value and internalValue ⚪ Manages own group internalValue ⚪ Renders template |
import VCheckbox from 'vuetify/es5/components/VCheckbox/VCheckbox'
export default VCheckbox.extend({
name: 'op-jumbo-checkbox'
})
There are a few problematic or verbose ways to do this in Vue. The worst is probably to access the parent directly from the child:
mounted() {
// Attempt to register this with a grouping parent automagically
if (
this.$parent &&
this.$parent.$vnode.componentOptions.tag === 'op-photo-chip-group' &&
isFunction(this.$parent.register)
) {
this.$parent.register(this)
}
},
This works but is fragile, and requires a direct parent-child relationship (the child cannot be further nested in other elements).
Another way is do manual registration by passing a registration function via scoped slots. There may be cases where this makes sense, but it does require awkward passing.
mounted() {
// Allow manual registration signal
this.$emit('register', this)
},
In the parent template:
<v-input :error-messages="errors">
<slot :register="register"></slot>
</v-input>
register(item) {
// Append to internal items array
}
In use:
<op-large-chip-group #default="{ register }">
<op-large-chip @register="register($event)"></op-large-chip-group>
</op-large-chip-group>
Another way similar to the method above is to access the parent's API via $refs
to invoke the register method.
The least messy way is to make use of Vue's provide
/inject
feature. Vuetify's Registrable
mixin wraps this behavior. A namespace is provided by the parent:
provide() {
return {
photoChipGroup: this
}
},
Which the child uses:
<script>
import { factory as GroupableFactory } from 'vuetify/es5/mixins/groupable'
export default {
name: 'op-photo-chip',
mixins: [GroupableFactory('photoChipGroup')],
// Rest of component
}
</script>
Vuetify uses these internally, and it can be helpful to use similar conventions in custom components. I just love seeing how other developers name things. From the C# learning module: "A software developer once famously said 'The hardest part of software development is naming things.'"
Name of property or method | Description |
---|---|
internalValue |
What I had come to call localValue . This value is maintained inside the component as local state and emitted externally when appropriate. In VInput is an alias for lazyValue , which is set from value during setup. |
inputValue |
An alternative model value property name for selectable components where value has another meaning (such as "dog", "Silver Falls", etc). Compare to raw HTML value for checkboxes. This model indicates whether the component has been selected. |
isActive |
Whether or not the component is active. Used in Toggleable components. |
computedId |
Refers to unique internal ID for the component. May wrap the Vue _uid . This may also be the convention used to describe any computed value. I've often used translatedId or similar, but this makes good sense. |
isFocused |
The same I had come to use to determine if an input is in focus. |