gridsome
Version:
A JAMstack framework for building blazing fast websites with Vue.js
97 lines (78 loc) • 2.63 kB
JavaScript
import { stringifyClass } from '../utils/class'
// @vue/component
export default {
functional: true,
props: {
src: { type: [Object, String], required: true },
width: { type: String, default: '' },
height: { type: String, default: '' },
quality: { type: String, default: '' },
fit: { type: String, default: '' },
position: { type: String, default: '' },
background: { type: String, default: '' },
blur: { type: String, default: '' },
immediate: { type: Boolean, default: false },
imageWidths: { type: String, default: undefined }
},
render: (h, { data, props }) => {
const classNames = [data.class, 'g-image']
const noscriptClassNames = [data.staticClass, classNames.slice()]
const isImmediate = props.immediate
const directives = data.directives || []
const attrs = data.attrs || {}
const hook = data.hook || {}
const res = []
switch (typeof props.src) {
case 'string':
attrs.src = props.src
break
case 'object': {
const { src, srcset, size, dataUri } = props.src
const isLazy = !isImmediate && dataUri
const sizes = attrs.sizes || props.src.sizes
attrs.src = isLazy ? dataUri : src
attrs.width = size.width
if (isLazy) attrs['data-src'] = src
if (srcset.length) attrs[`${isLazy ? 'data-' : ''}srcset`] = Array.isArray(srcset) ? srcset.join(', ') : srcset
if (sizes) attrs[`${isLazy ? 'data-' : ''}sizes`] = sizes
if (isLazy) {
directives.push({ name: 'g-image' })
}
break
}
}
hook.update = (oldVnode, vnode) => {
const { attrs: oldAttrs = {}} = oldVnode.data
const { attrs = {}} = vnode.data
if (attrs['data-src'] && attrs.src !== oldAttrs.src) {
// clear srcset and sizes to show the dataUri image
vnode.elm.srcset = ''
vnode.elm.sizes = ''
}
}
res.push(h('img', {
...data,
class: classNames,
directives,
props,
attrs,
hook
}))
if (attrs['data-src']) {
classNames.push('g-image--lazy')
classNames.push('g-image--loading')
noscriptClassNames.push('g-image--loaded')
// must render as innerHTML to make hydration work
res.push(h('noscript', {
domProps: {
innerHTML: `` +
`<img src="${props.src.src}" class="${stringifyClass(noscriptClassNames)}"` +
(attrs.width ? ` width="${attrs.width}"`: '') +
(attrs.alt ? ` alt="${attrs.alt}"` : '') +
`>`
}
}))
}
return res
}
}