From 0e05aa90d2c1b448dce4fd780f6a24255fc5feea Mon Sep 17 00:00:00 2001 From: Luis Ball Date: Fri, 2 Jul 2021 11:53:32 -0700 Subject: [PATCH] feat: use vue 3 global and composition api in ix-img This commit refactors the component into a functional component to remove the vue-class-component dependency. This is necessary because the dependency has not updated their release candidate for vue 3 support in months. Furthermore, functional components are quickly becoming the more idiomatic way to write components in vue 3. This commit also refactors the component to use the new global defineComponent api and h composition api. The defineComponent api exposes a new function, the setup function, that replaces a lot of the functionality previously done in the render function. Setup can accepts props as an argument. Setup can also return its own render function. The new render function for defineComponent does not accept arguments. And, rather than aliasing createElement to h, vue now directly exports h as a function which can be used inside the render function. --- src/plugins/vue-imgix/ix-img.tsx | 86 ++++++++++++++++---------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/plugins/vue-imgix/ix-img.tsx b/src/plugins/vue-imgix/ix-img.tsx index fb359293..97cd4977 100644 --- a/src/plugins/vue-imgix/ix-img.tsx +++ b/src/plugins/vue-imgix/ix-img.tsx @@ -1,67 +1,67 @@ -import { ensureVueImgixClientSingleton, IVueImgixClient } from './vue-imgix'; -import Vue, { CreateElement } from 'vue'; -import Component from 'vue-class-component'; +import { ensureVueImgixClientSingleton } from './vue-imgix'; +import { h, defineComponent } from 'vue'; -const IxImgProps = Vue.extend({ - props: { - src: { - type: String, - required: true, - }, - fixed: Boolean, - imgixParams: Object, - width: [String, Number], - height: [String, Number], - attributeConfig: Object, - disableVariableQuality: Boolean, +const IxImgProps = { + src: { + type: String, + required: true, }, -}); + fixed: Boolean, + imgixParams: Object, + width: [String, Number], + height: [String, Number], + attributeConfig: Object, + disableVariableQuality: Boolean, + sizes: [String], + // TODO(luis): remove dataTestId props in favor of a better solution + dataTestId: { + type: String, + required: false, + } +}; const defaultAttributeMap = { src: 'src', srcset: 'srcset', }; -@Component -export class IxImg extends IxImgProps { - // Using !: here because we ensure it is set in created() - private vueImgixSingleton!: IVueImgixClient; - - created() { - this.vueImgixSingleton = ensureVueImgixClientSingleton(); - } +export const IxImg = defineComponent({ + props: IxImgProps, - render(createElement: CreateElement) { + setup(props) { + const vueImgixSingleton = ensureVueImgixClientSingleton(); const imgixParamsFromImgAttributes = { - ...(this.fixed && { - ...(this.width != null ? { w: this.width } : {}), - ...(this.height != null ? { h: this.height } : {}), + ...(props.fixed && { + ...(props.width != null ? { w: props.width } : {}), + ...(props.height != null ? { h: props.height } : {}), }), }; - const { src, srcset } = this.vueImgixSingleton.buildUrlObject( - this.src, + const { src, srcset } = vueImgixSingleton.buildUrlObject( + props.src as string, { ...imgixParamsFromImgAttributes, - ...this.imgixParams, + ...props.imgixParams, }, { - disableVariableQuality: Boolean(this.disableVariableQuality), + disableVariableQuality: Boolean(props.disableVariableQuality), }, ); const attributeConfig = { ...defaultAttributeMap, - ...this.attributeConfig, + ...props.attributeConfig, }; - return createElement('img', { - attrs: { - [attributeConfig.src]: src, - [attributeConfig.srcset]: srcset, - width: this.width, - height: this.height, - }, - }); - } -} + return () => + h('img', { + [attributeConfig.src]: src, + [attributeConfig.srcset]: srcset, + width: props.width, + height: props.height, + sizes: props.sizes, + // TODO(luis): remove dataTestId props in favor of a better solution + ['data-testid']: props.dataTestId || undefined, + }); + }, +});