<div id="test" x-data="{}" x-bind:test="foo" x-on:click="alert('ok')"></div>
const xAttrRE = /^x-(on|bind|data|text|html|model|if|for|show|cloak|transition|ref|spread)\b/
function isXAttr(attr) {
const name = replaceAtAndColonWithStandardSyntax(attr.name)
return xAttrRE.test(name)
}
function replaceAtAndColonWithStandardSyntax(name) {
if (name.startsWith('@')) {
return name.replace('@', 'x-on:')
} else if (name.startsWith(':')) {
return name.replace(':', 'x-bind:')
}
return name
}
function parseHtmlAttribute({ name, value }) {
const normalizedName = replaceAtAndColonWithStandardSyntax(name)
const typeMatch = normalizedName.match(xAttrRE)
const valueMatch = normalizedName.match(/:([a-zA-Z\-:]+)/)
const modifiers = normalizedName.match(/\.[^.\]]+(?=[^\]]*$)/g) || []
return {
type: typeMatch ? typeMatch[1] : null,
value: valueMatch ? valueMatch[1] : null,
modifiers: modifiers.map(i => i.replace('.', '')),
expression: value,
}
}
function getXAttrs(el, component, type) {
let directives = Array.from(el.attributes).filter(isXAttr).map(parseHtmlAttribute)
// Get an object of directives from x-spread.
let spreadDirective = directives.filter(directive => directive.type === 'spread')[0]
if (spreadDirective) {
let spreadObject = saferEval(spreadDirective.expression, component.$data)
// Add x-spread directives to the pile of existing directives.
directives = directives.concat(Object.entries(spreadObject).map(([name, value]) => parseHtmlAttribute({ name, value })))
}
if (type) return directives.filter(i => i.type === type)
return directives;
}
getXAttrs(document.getElementById('test'), {}, 'data')
const xAttrRE = /^x-(on|bind|data|text|html|model|if|for|show|cloak|transition|ref|spread)\b/
function isXAttr(attr) {
const name = replaceAtAndColonWithStandardSyntax(attr.name)
return xAttrRE.test(name)
}
function replaceAtAndColonWithStandardSyntax(name) {
if (name.startsWith('@')) {
return name.replace('@', 'x-on:')
} else if (name.startsWith(':')) {
return name.replace(':', 'x-bind:')
}
return name
}
function parseHtmlAttribute({ name, value }) {
const normalizedName = replaceAtAndColonWithStandardSyntax(name)
const typeMatch = normalizedName.match(xAttrRE)
const valueMatch = normalizedName.match(/:([a-zA-Z\-:]+)/)
const modifiers = normalizedName.match(/\.[^.\]]+(?=[^\]]*$)/g) || []
return {
type: typeMatch ? typeMatch[1] : null,
value: valueMatch ? valueMatch[1] : null,
modifiers: modifiers.map(i => i.replace('.', '')),
expression: value,
}
}
function getXAttrs(el, component, type) {
let directives = Array.from(el.attributes).filter(isXAttr).map(parseHtmlAttribute)
// Get an object of directives from x-spread.
let spreadDirective = directives.filter(directive => directive.type === 'spread')[0]
if (spreadDirective) {
let spreadObject = saferEval(spreadDirective.expression, component.$data)
// Add x-spread directives to the pile of existing directives.
directives = directives.concat(Object.entries(spreadObject).map(([name, value]) => parseHtmlAttribute({ name, value })))
}
return directives.filter(i => {
// If no type is passed in for filtering, bypass filter
if (! type) return true
return i.type === type
})
}
getXAttrs(document.getElementById('test'), {}, 'data')
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
PR #631 | |
v2.4.0 |
Test name | Executions per second |
---|---|
PR #631 | 159050.0 Ops/sec |
v2.4.0 | 159082.6 Ops/sec |
Measuring the performance of JavaScript microbenchmarks like TestGetXAttrs can be complex, so I'll break it down into understandable parts.
What is being tested?
The benchmark measures the performance of two functions: getXAttrs
. This function takes an element (el
), a component (component
), and an optional type as input. It returns an array of directives extracted from the element's attributes, including ones generated by the x-spread
feature.
Options being compared
The benchmark compares the performance of two versions of the getXAttrs
function:
true
without checking the type
property. This means that all directives are included in the output, even if they don't match the specified type.type
property.Pros and Cons of each approach
PR #631:
Pros:
Cons:
v2.4.0:
Pros:
Cons:
Other considerations
x-spread
feature is used to generate additional directives from the spread object in the getXAttrs
function. This adds complexity and potential overhead to the benchmark.saferEval
function is used to safely evaluate the expression of a directive, which can introduce additional overhead due to security checks.Alternative approaches
getXAttrs
in parallel could help reduce the overall execution time and provide more accurate results.Keep in mind that these are just suggestions, and the best approach depends on the specific requirements and constraints of your project.