Skip to content

Commit

Permalink
feat: use vue 3 global and composition api in ix-img
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
luqven committed Jul 8, 2021
1 parent eb7e1ad commit 0e05aa9
Showing 1 changed file with 43 additions and 43 deletions.
86 changes: 43 additions & 43 deletions src/plugins/vue-imgix/ix-img.tsx
Original file line number Diff line number Diff line change
@@ -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,
});
},
});

0 comments on commit 0e05aa9

Please sign in to comment.