alpinejs
Version:
The rugged, minimal JavaScript framework
61 lines (42 loc) • 1.54 kB
JavaScript
import { evaluateLater } from '../evaluator'
import { addScopeToNode } from '../scope'
import { directive } from '../directives'
import { initTree, destroyTree } from '../lifecycle'
import { mutateDom } from '../mutation'
import { warn } from "../utils/warn"
import { skipDuringClone } from '../clone'
directive('if', skipDuringClone((el, { expression }, { effect, cleanup }) => {
if (el.tagName.toLowerCase() !== 'template') warn('x-if can only be used on a <template> tag', el)
let evaluate = evaluateLater(el, expression)
let show = () => {
if (el._x_currentIfEl) return el._x_currentIfEl
let clone = el.content.cloneNode(true).firstElementChild
addScopeToNode(clone, {}, el)
mutateDom(() => {
el.after(clone)
initTree(clone)
})
el._x_currentIfEl = clone
// Mark the last rendered element so morph can skip
// past it instead of trying to diff it...
el._x_lastRenderedEl = clone
el._x_undoIf = () => {
mutateDom(() => {
destroyTree(clone)
clone.remove()
})
delete el._x_currentIfEl
delete el._x_lastRenderedEl
}
return clone
}
let hide = () => {
if (! el._x_undoIf) return
el._x_undoIf()
delete el._x_undoIf
}
effect(() => evaluate(value => {
value ? show() : hide()
}), { priority: 'structural' })
cleanup(() => el._x_undoIf && el._x_undoIf())
}))