UNPKG

@muban/muban

Version:

Writing components for server-rendered HTML

104 lines (103 loc) 3.48 kB
/* eslint-disable @typescript-eslint/naming-convention,@typescript-eslint/no-explicit-any */ import { unref } from '@vue/reactivity'; import { watch } from '@vue/runtime-core'; import { getCurrentComponentInstance } from '../Component'; import { applyBindings } from './applyBindings'; /// // Component functions // These are called from within your components' setup function, and return the response from one of the // `BindXXX` functions below, wrapped through the refDefinitions they apply to. // The `getBindingDefinition` just forwards the props, but passes long the target Elements/Components // inside a `ref` so they can be updated when the DOM changes /// export function bind(target, // make sure that if we bind props onto multiple components, // we only allow setting props that exist on all of them props) { return target.getBindingDefinition(props); } export function bindMap(target, getProps) { const instance = getCurrentComponentInstance(); if (instance) { // If we pass an array of refs instead of a refCollection, // these are only set up once if (Array.isArray(target)) { return target.map((ref, index) => bind(ref, getProps(ref, index))); } // target.getRefs() is reactive and triggers this watchEffect to update // as soon as the underlying ref array updates when the items in the DOM // are updated const disposeWatch = watch(() => target.getRefs(), (refs, oldValue, onInvalidate) => { const bindings = refs.map((ref, index) => bind(ref, getProps(ref, index))); const removeBindingList = applyBindings(bindings, instance) || []; onInvalidate(() => { removeBindingList.forEach((binding) => binding === null || binding === void 0 ? void 0 : binding()); }); }, { immediate: true }); return [ { type: 'bindMap', getElements: () => [], props: {}, dispose() { disposeWatch(); }, }, ]; } return []; } export function BindTemplate(props) { return { type: 'template', props, getElements() { var _a; return ((_a = props.ref) === null || _a === void 0 ? void 0 : _a.element) ? [props.ref.element] : []; }, }; } export function bindTemplate(target, onUpdate, options = {}) { return BindTemplate(Object.assign({ ref: target, onUpdate }, options)); } export function bindElement(ref, props) { return { ref, type: 'element', props, getElements() { return ref.value ? [ref.value] : []; }, }; } export function bindCollection(ref, props) { return { ref, type: 'collection', props, getElements() { return ref.value.map((r) => unref(r)); }, }; } export function BindComponent(ref, props) { return { ref, type: 'component', props, getElements() { var _a; return ((_a = ref.value) === null || _a === void 0 ? void 0 : _a.element) ? [ref.value.element] : []; }, }; } export function bindComponentCollection(ref, props) { return { ref, type: 'componentCollection', props, getElements() { return ref.value.map((refItem) => refItem.value.element); }, }; }