perf(ivy): apply [style]/[class] bindings directly to style/className (#33336)

This patch ensures that the `[style]` and `[class]` based bindings
are directly applied to an element's style and className attributes.

This patch optimizes the algorithm so that it...
- Doesn't construct an update an instance of `StylingMapArray` for
  `[style]` and `[class]` bindings
- Doesn't apply `[style]` and `[class]` based entries using
  `classList` and `style` (direct attributes are used instead)
- Doesn't split or iterate over all string-based tokens in a
  string value obtained from a `[class]` binding.

This patch speeds up the following cases:
- `<div [class]>` and `<div class="..." [class]>`
- `<div [style]>` and `<div style="..." [style]>`

The overall speec increase is by over 5x.

PR Close #33336
This commit is contained in:
Matias Niemelä
2019-10-22 15:18:40 -07:00
committed by Andrew Kushnir
parent ee4fc12e42
commit dcdb433b7d
13 changed files with 359 additions and 102 deletions

View File

@ -247,7 +247,7 @@ export function isStylingContext(value: any): boolean {
typeof value[1] !== 'string';
}
export function isStylingMapArray(value: TStylingContext | StylingMapArray | null): boolean {
export function isStylingMapArray(value: any): boolean {
// the StylingMapArray is in the format of [initial, prop, string, prop, string]
// and this is the defining value to distinguish between arrays
return Array.isArray(value) &&
@ -295,13 +295,18 @@ export function forceClassesAsString(classes: string | {[key: string]: any} | nu
return (classes as string) || '';
}
export function forceStylesAsString(styles: {[key: string]: any} | null | undefined): string {
export function forceStylesAsString(
styles: {[key: string]: any} | null | undefined, hyphenateProps: boolean): string {
let str = '';
if (styles) {
const props = Object.keys(styles);
for (let i = 0; i < props.length; i++) {
const prop = props[i];
str = concatString(str, `${prop}:${styles[prop]}`, ';');
const propLabel = hyphenateProps ? hyphenate(prop) : prop;
const value = styles[prop];
if (value !== null) {
str = concatString(str, `${propLabel}:${value}`, ';');
}
}
}
return str;
@ -463,4 +468,4 @@ export function splitOnWhitespace(text: string): string[]|null {
// `input('class') + classMap()` instructions.
export function selectClassBasedInputName(inputs: PropertyAliases): string {
return inputs.hasOwnProperty('class') ? 'class' : 'className';
}
}