refactor(ivy): Add style reconciliation algorithm (#34004)
This change introduces class/style reconciliation algorithm for DOM elements. NOTE: The code is not yet hooked up, it will be used by future style algorithm. Background: Styling algorithm currently has [two paths](https://hackmd.io/@5zDGNGArSxiHhgvxRGrg-g/rycZk3N5S) when computing how the style should be rendered. 1. A direct path which concatenates styling and uses `elemnent.className`/`element.style.cssText` and 2. A merge path which uses internal data structures and uses `element.classList.add/remove`/`element.style[property]`. The situation is confusing and hard to follow/maintain. So a future PR will remove the merge-path and do everything with direct-path. This however breaks when some other code adds class or style to the element without Angular's knowledge. If this happens instead of switching from direct-path to merge-path algorithm, this change provides a different mental model whereby we always do `direct-path` but the code which writes to the DOM detects the situation and reconciles the out of bound write. The reconciliation process is as follows: 1. Detect that no one has modified `className`/`cssText` and if so just write directly (fast path). 2. If out of bounds write did occur, switch from writing using `className`/`cssText` to `element.classList.add/remove`/`element.style[property]`. This does require that the write function computes the difference between the previous Angular expected state and current Angular state. (This requires a parser. The advantage of having a parser is that we can support `style="width: {{exp}}px" kind of bindings.`) Compute the diff and apply it in non destructive way using `element.classList.add/remove`/`element.style[property]` Properties of approach: - If no out of bounds style modification: - Very fast code path: Just concatenate string in right order and write them to DOM. - Class list order is preserved - If out of bounds style modification detected: - Penalty for parsing - Switch to non destructive modification: `element.classList.add/remove`/`element.style[property]` - Switch to alphabetical way of setting classes. PR Close #34004
This commit is contained in:

committed by
Miško Hevery

parent
ef95da6d3b
commit
76698d38f7
@ -5,6 +5,7 @@
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {CharCode} from '../../util/char_code';
|
||||
import {AttributeMarker, TAttributes} from '../interfaces/node';
|
||||
import {CssSelector} from '../interfaces/projection';
|
||||
import {ProceduralRenderer3, RElement, Renderer3, isProceduralRenderer} from '../interfaces/renderer';
|
||||
@ -103,5 +104,5 @@ export function isAnimationProp(name: string): boolean {
|
||||
// Perf note: accessing charCodeAt to check for the first character of a string is faster as
|
||||
// compared to accessing a character at index 0 (ex. name[0]). The main reason for this is that
|
||||
// charCodeAt doesn't allocate memory to return a substring.
|
||||
return name.charCodeAt(0) === 64; // @
|
||||
return name.charCodeAt(0) === CharCode.AT_SIGN;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {unwrapSafeValue} from '../../sanitization/bypass';
|
||||
import {CharCode} from '../../util/char_code';
|
||||
import {PropertyAliases, TNodeFlags} from '../interfaces/node';
|
||||
import {LStylingData, StylingMapArray, StylingMapArrayIndex, TStylingContext, TStylingContextIndex, TStylingContextPropConfigFlags, TStylingNode} from '../interfaces/styling';
|
||||
import {NO_CHANGE} from '../tokens';
|
||||
@ -431,7 +432,7 @@ export function splitOnWhitespace(text: string): string[]|null {
|
||||
let foundChar = false;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const char = text.charCodeAt(i);
|
||||
if (char <= 32 /*' '*/) {
|
||||
if (char <= CharCode.SPACE) {
|
||||
if (foundChar) {
|
||||
if (array === null) array = [];
|
||||
array.push(text.substring(start, i));
|
||||
|
Reference in New Issue
Block a user