domc looks really interesting (although I did not get "v-for" working properly on list updates), which is why I am currently playing around with it.
In order to understand the underlying logic, I started implementing a "v-if" directive. It may be used as follows:
<tag v-if="scopeProp">...</tag> where scopeProp is the name of a (boolean) scope property. The <tag/> will be shown if scopeProp is true
<tag v-if="(args) => expr">...</tag> where args is an (optionally empty) comma-separated list of scope properties and expr an expression which must evaluate to true in order for <tag/> to be shown. When used in the expression, this refers to the local scope
<tag v-if="(args) => { statements }">...</tag> where args is an (optionally empty) comma-separated list of scope properties and statements the body of a function which should return true in order for <tag/> to be rendered. When used in the function body, this refers to the local scope
Source code follows below:
customDirectives['if'] = function setup (initialNode, Directive) {
if ((Directive == null) || (Directive.trim() === '')) {
Directive = '() => true'
}
const IdentifierPattern = /^\s*([_$a-z][_$a-z0-9]*)\s*$/i
const FunctionPattern = /^\s*\(\s*([_$a-z][_$a-z0-9]*(?:\s*,\s*[_$a-z][_$a-z0-9]*)*)?\s*\)\s*=>\s*([\s\S]+)$/i
let Match
Match = IdentifierPattern.exec(Directive)
if (Match != null) {
Match = [null, Match[1], `{ return (${Match[1]} == true) }`]
} else {
Match = FunctionPattern.exec(Directive)
if (Match == null) throw new Error(
'domc: invalid "v-if" condition given'
)
}
let [_,Parameters,Body] = Match
Parameters = (Parameters || '').trim().replace(/\s*,\s*/g,',').split(',')
if (Parameters[0] === '') { Parameters = [] }
Body = Body.trim()
switch (true) {
case (Body === ''):
Body = 'return true'
break
case Body.startsWith('{'):
Body = Body.slice(1).replace(/\}\s*$/,'').trim()
break
default:
Body = 'return ' + Body
}
let Predicate
try {
Predicate = new Function(Parameters.join(','),Body)
} catch (Signal) {
throw new Error(
'domc: could not compile "v-if" condition, reason: ' + Signal
)
}
const Template = domc(initialNode)
let renderedNode = initialNode
let isVisible = false
function update (Scope) {
let shouldBeVisible
try {
let ArgumentList = Parameters.map((Parameter) => Scope[Parameter])
shouldBeVisible = (Predicate.apply(Scope,ArgumentList) === true)
} catch (Signal) {
throw new Error(
'domc: could not evaluate "v-if" condition, reason: ' + Signal
)
}
if (shouldBeVisible) {
let localScope = Object.assign({},Scope)
if (isVisible) {
renderedNode.update(localScope)
} else {
renderedNode.replaceWith(
renderedNode = Template.createInstance(localScope)
)
}
} else {
if (isVisible) {
renderedNode.replaceWith(
renderedNode = document.createElement('div')
)
renderedNode.style.display = 'none'
}
}
isVisible = shouldBeVisible
}
return update
}
If it turns out to work reliably, I'll also create a Pull Request
Hello Pavel,
domc
looks really interesting (although I did not get "v-for" working properly on list updates), which is why I am currently playing around with it.In order to understand the underlying logic, I started implementing a "v-if" directive. It may be used as follows:
<tag v-if="scopeProp">...</tag>
wherescopeProp
is the name of a (boolean) scope property. The<tag/>
will be shown ifscopeProp
istrue
<tag v-if="(args) => expr">...</tag>
whereargs
is an (optionally empty) comma-separated list of scope properties andexpr
an expression which must evaluate totrue
in order for<tag/>
to be shown. When used in the expression,this
refers to the local scope<tag v-if="(args) => { statements }">...</tag>
whereargs
is an (optionally empty) comma-separated list of scope properties andstatements
the body of a function which should returntrue
in order for<tag/>
to be rendered. When used in the function body,this
refers to the local scopeSource code follows below:
If it turns out to work reliably, I'll also create a Pull Request