v-once
не является «настоящей» директивой.Компилятор шаблонов Vue сгенерирует код, который кэширует vnodes шаблонов, помеченных v-once
.
Поскольку вы пишете функцию рендера вручную, вам придется позаботиться о кэшировании vnode, сгенерированных вашим рендером.function.
Вы можете попробовать что-то вроде этого (непроверенное и, вероятно, имеет проблемы):
const cache = new WeakMap()
export default {
functional: true,
render(h, ctx) {
// Get cache map from parent component instance
if (!cache.has(ctx.parent)) {
cache.set(ctx.parent, new Map())
}
const vnodeCache = cache.get(ctx.parent)
// Determine the cache key from the props (we only use one prop here)
const cacheKey = ctx.props.fill
// Get the cached vnode
let vnode = vnodeCache.get(cacheKey)
if (!vnode) {
// Render
vnode = h('div', `Fill is ${ctx.props.fill}`)
// This is necessary so Vue will reuse the previous DOM elements during patch
vnode.isStatic = true
vnode.isOnce = true
// Store in cache
vnodeCache.set(cacheKey, vnode)
}
return vnode
}
}
Я не могу гарантировать, что приведенный выше код будет работать правильно во всех ситуациях, так как он довольнонизкий уровень, и я не знаю, можно ли / нужно кэшировать vnodes таким образом.Код кэширования может быть более или менее сложным, чем приведенный выше, в зависимости от ваших требований.
Интересно, что использование v-once
в функциональном компоненте не помешает выполнению кода рендеринга этого поддерева шаблона в полном объеме (это то, чего вы хотите избежать в своем вопросе), хотя vnode имеет isStatic
и isOnce
, помеченные как true, Vue будет использовать предыдущий рендеринг при исправлении DOM.
В целом, этоэто довольно излишне, и я рекомендую вам не беспокоиться о v-once
и кэшировании, если только вы не определили, что это проблема с производительностью после профилирования.