!127 【类Web范式】CSS选择器能力增强

Merge pull request !127 from Yao.inhome/baihe_css_selector_0118
This commit is contained in:
openharmony_ci
2022-02-10 06:43:11 +00:00
committed by Gitee
3 changed files with 620 additions and 18 deletions
+155 -5
View File
@@ -41,7 +41,9 @@ import {
bindSubVm,
bindSubVmAfterInitialized,
newWatch,
bindDir
bindDir,
updateTagCounter,
setAttributeStyle
} from './directive';
import {
createBlock,
@@ -58,6 +60,7 @@ import Vm from './index';
import Element from '../../vdom/Element';
import Comment from '../../vdom/Comment';
import Node from '../../vdom/Node';
import Document from '../../vdom/Document';
import { VmOptions } from './vmOptions';
export interface FragBlockInterface {
@@ -125,6 +128,13 @@ export function build(vm: Vm) {
const opt: any = vm._vmOptions || {};
const template: any = opt.template || {};
compile(vm, template, vm._parentEl);
// foreach vm
const doc: Document = vm._app.doc;
const body: Node = doc.body;
compileVm(vm, body);
compileCounter(vm, body);
compileElementAndElement(vm, body);
compileAttrStyle(vm, body);
Log.debug(`"OnReady" lifecycle in Vm(${vm._type}).`);
vm.$emit('hook:onReady');
if (vm._parent) {
@@ -184,6 +194,149 @@ function compile(vm: Vm, target: TemplateInterface, dest: FragBlockInterface | E
compileNativeComponent(vm, target, dest, type);
}
function compileVm(vm: Vm, body: Node): void {
if (body.nodeType === Node.NodeType.Element) {
const node: Element = body as Element;
let count = 0;
node.children.forEach((child: Node) => {
const el = child as Element;
const tag = child.type;
if (count === 0) {
setTagStyle(vm, el, tag, true, false, false);
} else if (count === node.children.length - 1) {
setTagStyle(vm, el, tag, false, true, false);
}
count++;
compileVmChild(vm, child);
});
}
}
function compileVmChild(vm: Vm, body: Node): void {
if (body.nodeType === Node.NodeType.Element) {
const node: Element = body as Element;
let count = 0;
node.children.forEach((child: Node) => {
const el = child as Element;
const tag = child.type;
if (count === 0) {
setTagStyle(vm, el, tag, true, false, false);
} else if (count === node.children.length - 1) {
setTagStyle(vm, el, tag, false, true, false);
}
count++;
compileVm(vm, child);
});
}
}
function compileCounter(vm: Vm, body: Node): void {
if (body.nodeType === Node.NodeType.Element) {
const node: Element = body as Element;
let count = {};
node.children.forEach((child: Node) => {
const el = child as Element;
const tag = child.type;
if (count[tag] === undefined) {
count[tag] = 1;
} else {
count[tag] = count[tag] + 1;
}
const css = vm._css || {};
if (css) {
const data = css[tag] || {};
if (data) {
const counterIncrement = data['counterIncrement'];
if (counterIncrement !== undefined) {
updateTagCounter(el, count[tag]);
}
}
}
compileCounterChild(vm, child);
});
}
}
function compileCounterChild(vm: Vm, body: Node): void {
if (body.nodeType === Node.NodeType.Element) {
const node: Element = body as Element;
let count = {};
node.children.forEach((child: Node) => {
const el = child as Element;
const tag = child.type;
if (count[tag] === undefined) {
count[tag] = 1;
} else {
count[tag] = count[tag] + 1;
}
const css = vm._css || {};
if (css) {
const data = css[tag] || {};
if (data) {
const counterIncrement = data['counterIncrement'];
if (counterIncrement !== undefined) {
updateTagCounter(el, count[tag]);
}
}
}
compileCounter(vm, child);
});
}
}
function compileAttrStyle(vm: Vm, body: Node): void {
if (body.nodeType === Node.NodeType.Element) {
const node: Element = body as Element;
node.children.forEach((child: Node) => {
const el = child as Element;
setAttributeStyle(vm, el);
compileAttrStyleChild(vm, child);
});
}
}
function compileAttrStyleChild(vm: Vm, body: Node): void {
if (body.nodeType === Node.NodeType.Element) {
const node: Element = body as Element;
node.children.forEach((child: Node) => {
const el = child as Element;
setAttributeStyle(vm, el);
compileAttrStyle(vm, child);
});
}
}
function compileElementAndElement(vm: Vm, body: Node): void {
if (body.nodeType === Node.NodeType.Element) {
const node: Element = body as Element;
node.children.forEach((child: Node) => {
if (child.nextSibling) {
const el = child.nextSibling as Element;
const tag = child.type + '+' + child.nextSibling.type;
setTagStyle(vm, el, tag, false, false, false);
}
compileElementAndElementChild(vm, child);
});
}
}
function compileElementAndElementChild(vm: Vm, body: Node): void {
if (body.nodeType === Node.NodeType.Element) {
const node: Element = body as Element;
node.children.forEach((child: Node) => {
if (child.nextSibling) {
const el = child.nextSibling as Element;
const tag = child.type + '+' + child.nextSibling.type;
setTagStyle(vm, el, tag, false, false, false);
}
compileElementAndElement(vm, child);
});
}
}
/**
* Compile a dynamic component.
* @param {Vm} vm - Vm object needs to be compiled.
@@ -494,7 +647,7 @@ function resetElementStyle(vm: Vm, element: Element): void {
}
setUniversalStyle(vm, element);
if (element.type) {
setTagStyle(vm, element, element.type);
setTagStyle(vm, element, element.type, false, false, false);
}
if (element.id) {
setIdStyle(vm, element, element.id);
@@ -568,7 +721,6 @@ function compileNativeComponent(vm: Vm, template: TemplateInterface, dest: FragB
if (!vm._rootEl) {
vm._rootEl = element;
// Bind event earlier because of lifecycle issues.
const binding: any = vm._externalBinding || {};
const target = binding.template;
@@ -685,7 +837,6 @@ function bindRepeat(vm: Vm, target: TemplateInterface, fragBlock: FragBlockInter
}
trackMap[key] = item;
});
// Remove unused element foreach old item.
const reusedList: any[] = [];
const cacheList: any[] = [];
@@ -705,7 +856,6 @@ function bindRepeat(vm: Vm, target: TemplateInterface, fragBlock: FragBlockInter
});
}
});
// Create new element for each new item.
children.length = 0;
vms.length = 0;
+373 -11
View File
@@ -57,9 +57,20 @@ const SETTERS = {
event: 'addEvent',
idStyle: 'setIdStyle',
tagStyle: 'setTagStyle',
universalStyle: 'setUniversalStyle'
attrStyle: 'setAttrStyle',
tagAndTagStyle: 'setTagAndTagStyle',
tagAndIdStyle: 'setTagAndIdStyle',
universalStyle: 'setUniversalStyle',
firstOrLastChildStyle: 'setFirstOrLastChildStyle'
};
enum ContentType {Content_String, Content_Open_Quote, Content_Close_Quote, Content_Attr, Content_Counter};
interface ContentObject {
value: string,
contentType: ContentType
}
let finallyItems: Array <ContentObject> = [];
/**
* Bind id, attr, classnames, style, events to an element.
* @param {Vm} vm - Vm object.
@@ -109,7 +120,8 @@ export function bindElement(vm: Vm, el: Element, template: TemplateInterface, pa
setStyle(vm, el, template.style);
setIdStyle(vm, el, template.id);
setClass(vm, el, template.classList);
setTagStyle(vm, el, template.type);
setTagStyle(vm, el, template.type, false, false, true);
setTagAndIdStyle(vm, el, template.type, template.id);
setUniversalStyle(vm, el);
applyStyle(vm, el);
@@ -464,6 +476,11 @@ function selectIdStyle(css: object, id: string, vm: Vm): any {
return selectStyle(css, key, vm);
}
function selectTagAndIdStyle(css: object, tag: string, id: string, vm: Vm): any {
const key = tag + '#' + id;
return selectStyle(css, key, vm);
}
/**
* Replace style.
* @param {*} oStyle - Current style.
@@ -668,7 +685,7 @@ export function setIdStyle(vm: Vm, el: Element, id: Function | string): void {
* @param {*} css - Css style.
* @param {string} name - Bind by name.
*/
function doSetStyle(vm: Vm, el: Element, style: any, css: any, name: string): void {
function doSetStyle(vm: Vm, el: Element, style: any, css: any, name: string, isFirst?: boolean, isLast?: boolean, isSetContent?: boolean): void {
if (!style) {
return;
}
@@ -676,7 +693,7 @@ function doSetStyle(vm: Vm, el: Element, style: any, css: any, name: string): vo
Object.assign(typeStyle, style);
setAnimation(typeStyle, css);
setFontFace(typeStyle, css);
bindDir(vm, el, name, typeStyle);
bindDir(vm, el, name, typeStyle, isFirst, isLast, isSetContent);
}
/**
@@ -714,10 +731,23 @@ function setAnimation(style: any, css: any): void {
* @param {Element} el - ELement component.
* @param {string} tag - Tag.
*/
export function setTagStyle(vm: Vm, el: Element, tag: string): void {
export function setTagStyle(vm: Vm, el: Element, tag: string, isFirst?: boolean, isLast?: boolean, isSetContent?: boolean): void {
const css = vm._css || {};
if (tag && typeof tag === 'string') {
doSetStyle(vm, el, selectStyle(css, tag, vm), css, 'tagStyle');
let tagStyle = 'tagStyle';
if (tag.indexOf('+') > 0) {
tagStyle = 'tagAndTagStyle';
}
doSetStyle(vm, el, selectStyle(css, tag, vm), css, tagStyle, isFirst, isLast, isSetContent);
}
}
export function setTagAndIdStyle(vm: Vm, el: Element, tag: string, id: Function | string): void {
const css = vm._css || {};
if (typeof id === 'string') {
if (tag && typeof tag === 'string') {
doSetStyle(vm, el, selectTagAndIdStyle(css, tag, id, vm), css, 'tagAndIdStyle');
}
}
}
@@ -788,26 +818,71 @@ function bindEvents(vm: Vm, el: Element, events: object, eventType?: string): vo
* @param {string} name - Method name.
* @param {Object} data - Data that needed.
*/
export function bindDir(vm: Vm, el: Element, name: string, data: object): void {
export function bindDir(vm: Vm, el: Element, name: string, data: object, isFirst?: boolean, isLast?: boolean, isSetContent?: boolean): void {
if (!data) {
return;
}
const keys = Object.keys(data);
let keys = Object.keys(data);
let i = keys.length;
if (!i) {
return;
}
const methodName = SETTERS[name];
const method = el[methodName];
let methodName = SETTERS[name];
let method = el[methodName];
const isSetStyle = methodName === 'setStyle';
if (methodName === 'setIdStyle') {
for (const id in el.idStyle) {
el.idStyle[id] = '';
}
}
if (name === 'tagStyle' || name === 'tagAndIdStyle') {
let j: number = 0;
let k: number = 0;
let temp: string = null;
for (j = 0; j < i - 1; j++) {
for (k = 0; k < i - 1 - j; k++) {
if (keys[k] > keys[k + 1]) {
temp = keys[k + 1];
keys[k + 1] = keys[k];
keys[k] = temp;
}
}
}
}
while (i--) {
const key = keys[i];
let key = keys[i];
const value = data[key];
if (name === 'tagStyle') {
if (key.endsWith(':first-child') || key.endsWith(':last-child')) {
methodName = SETTERS['firstOrLastChildStyle'];
} else {
methodName = SETTERS[name];
}
if (key.endsWith(':first-child') && isFirst) {
key = key.replace(':first-child', '');
} else if (key.endsWith(':last-child') && isLast) {
key = key.replace(':last-child', '');
}
if (isSetContent && (key === 'content::before' || key === 'content::after')) {
finallyItems = [];
splitItems(value);
let newValue = setContent(el, key);
methodName = SETTERS['attr'];
method = el[methodName];
method.call(el, 'value', newValue);
continue;
}
}
if (name === 'tagAndIdStyle') {
const newValue = updateTagAndIdStyle(el, key, value);
methodName = SETTERS['attr'];
method = el[methodName];
method.call(el, 'value', newValue);
continue;
}
method = el[methodName];
if (key === 'ref') {
vm.$refs[value] = el;
}
@@ -914,3 +989,290 @@ function applyStyle(vm: Vm, el: Element): void {
function isArray(params: any): params is Array<string> {
return Array.isArray(params);
}
function splitItems(valueStr: string): void {
let i: number;
let item: string = '';
let startQuote: boolean = false;
let itemList: string[] = [];
const len = valueStr.length;
for (i = 0; i < len; i++) {
if (!startQuote) {
if (valueStr[i] === '"') {
const itemLength = item.length;
if (itemLength > 0) {
const itemListLength = itemList.length;
itemList[itemListLength] = item;
}
item = '"';
startQuote = true;
continue;
} else {
item = item + valueStr[i];
if (i === len - 1) {
const itemListLength = itemList.length;
itemList[itemListLength] = item;
}
continue;
}
} else {
if (valueStr[i] === '"') {
item = item + valueStr[i];
startQuote = false;
const itemListLength = itemList.length;
itemList[itemListLength] = item;
item = '';
continue;
} else {
item = item + valueStr[i];
continue;
}
}
}
doSplitItem(itemList);
}
function doSplitItem(itemList: string[]): void {
let i: number;
let itemListLength = itemList.length;
for (i = 0; i < itemListLength; i++ ) {
let item = itemList[i].trim();
if (item.indexOf('"') === 0) {
item = item.replace('"', '');
item = item.replace('"', '');
const contentObject: ContentObject = {
value: item,
contentType: ContentType.Content_String
};
const finallyItemsLength = finallyItems.length;
finallyItems[finallyItemsLength] = contentObject;
} else {
splitItem(item.trim());
if (finallyItems.length > 0) {
continue;
} else {
return;
}
}
}
}
function splitItem(item: string): void{
if (item.length === 0) {
return;
}
let finallyItemsLength = finallyItems.length;
if (item.indexOf('open-quote') === 0) {
const subItem = item.substr(0, 10);
const contentObject: ContentObject = {
value: subItem,
contentType: ContentType.Content_Open_Quote
};
finallyItems[finallyItemsLength] = contentObject;
splitItem(item.substr(10).trim());
} else if (item.indexOf('close-quote') === 0) {
const subItem = item.substr(0, 11);
const contentObject: ContentObject = {
value: subItem,
contentType: ContentType.Content_Close_Quote
};
finallyItems[finallyItemsLength] = contentObject;
splitItem(item.substr(11).trim());
} else if (item.indexOf('attr') === 0) {
const fromIndex = item.indexOf('(');
const toIndex = item.indexOf(')');
const subLen = toIndex - fromIndex - 1;
const subItem = item.substr(fromIndex + 1, subLen).trim();
const contentObject: ContentObject = {
value: subItem,
contentType: ContentType.Content_Attr
};
finallyItems[finallyItemsLength] = contentObject;
splitItem(item.substr(toIndex + 1).trim());
} else if (item.indexOf('counter') === 0) {
const toIndex = item.indexOf(')');
const subItem = 'counter(0)';
const contentObject: ContentObject = {
value: subItem,
contentType: ContentType.Content_Counter
};
finallyItems[finallyItemsLength] = contentObject;
splitItem(item.substr(toIndex + 1).trim());
} else {
finallyItems = [];
}
}
function setContent(el: Element, key: string): string {
const itemLength = finallyItems.length;
let contentValue = '';
let newValue = '';
if (itemLength > 0) {
let i: number;
for (i = 0; i < itemLength; i++) {
const contentType = finallyItems[i].contentType;
switch (contentType) {
case ContentType.Content_String:
contentValue = contentValue + getContentString(finallyItems[i].value);
break;
case ContentType.Content_Open_Quote:
contentValue = contentValue + getContentOpenQuote(el, key);
break;
case ContentType.Content_Close_Quote:
contentValue = contentValue + getContentCloseQuote(el, key);
break;
case ContentType.Content_Attr:
contentValue = contentValue + getContentAttr(el, finallyItems[i].value);
break;
case ContentType.Content_Counter:
contentValue = contentValue + finallyItems[i].value;
break;
}
}
const oldValue = el.attr['value'];
if (key === 'content::before') {
newValue = contentValue + oldValue;
} else if (key === 'content::after') {
newValue = oldValue + contentValue;
}
}
return newValue;
}
function getContentString(value: string): string {
let contentValue = value.replace('\"', '');
contentValue = contentValue.replace('\"', '');
return contentValue;
}
function getContentOpenQuote(el: Element, key: string): string {
let contentValue = '';
if (el.isOpen) {
contentValue = '\'';
} else {
contentValue = '\"';
el.isOpen = true;
}
if (key === 'content::before') {
el.hasBefore = true;
}
return contentValue;
}
function getContentCloseQuote(el: Element, key: string): string {
let contentValue = '';
if (el.isOpen) {
contentValue = '\"';
} else {
contentValue = '';
}
if (el.isOpen && key === 'content::after') {
el.hasAfter = true;
}
return contentValue;
}
function getContentAttr(el: Element, value: string): string {
let contentValue = el.attr[value];
if (contentValue === undefined) {
contentValue = '';
}
return contentValue;
}
export function updateTagCounter(el: Element, counter: number): void {
let value = el.attr['value'];
if (value !== undefined) {
let fromIndex = value.indexOf('counter');
if (fromIndex !== -1) {
value = value.replace('counter(0)', counter);
const methodName = SETTERS['attr'];
const method = el[methodName];
method.call(el, 'value', value);
}
}
}
function updateTagAndIdStyle(el: Element, key: string, value: string): string {
let newValue = '';
let contentValue = '';
let oldValue = el.attr['value'];
if (key === 'content::before') {
if (value === 'open-quote' || value === 'close-quote') {
if (value === 'open-quote' && key === 'content::before') {
contentValue = '\"';
if (el.hasBefore) {
oldValue = oldValue.substr(1, oldValue.length);
}
newValue = contentValue + oldValue;
oldValue = newValue;
} else if (el.hasBefore && value === 'close-quote' && key === 'content::before') {
el.hasBefore = false;
oldValue = oldValue.substr(1, oldValue.length);
newValue = oldValue;
}
}
} else if (key === 'content::after') {
if (value === 'open-quote' && key === 'content::after') {
contentValue = '\"';
if (el.hasBefore) {
contentValue = '\'';
}
if (el.hasAfter) {
oldValue = oldValue.substr(0, oldValue.length - 1);
}
newValue = oldValue + contentValue;
} else if (value === 'close-quote' && key === 'content::after' && el.hasBefore) {
contentValue = '\"';
if (el.hasAfter) {
oldValue = oldValue.substr(0, oldValue.length - 1);
}
newValue = oldValue + contentValue;
}
}
if (value === 'no-open-quote' || value === 'no-close-quote') {
newValue = oldValue;
if (key === 'content::before' && value === 'no-open-quote') {
if (el.hasBefore) {
newValue = oldValue.substr(1);
}
}
if (key === 'content::after') {
if (el.hasAfter) {
newValue = oldValue.substr(0, oldValue.length - 1);
}
}
}
return newValue;
}
export function setAttributeStyle(vm: Vm, el: Element): void {
const css = vm._css;
if (css) {
const keys = Object.keys(css);
if (keys !== undefined || keys !== null) {
const i = keys.length;
let j: number = 0;
for (j; j < i; j++) {
let cssKey = keys[j].trim();
if (cssKey.indexOf('[') === 0) {
cssKey = cssKey.substr(1, cssKey.length - 2);
let equalIndex = cssKey.indexOf('=');
if (equalIndex !== -1) {
const attrId = cssKey.substr(0, equalIndex).trim();
let attrValue = cssKey.substr(equalIndex + 1).trim();
if (attrValue.indexOf('\"') !== -1) {
attrValue = attrValue.replace('"', '').trim();
attrValue = attrValue.replace('"', '').trim();
}
const elValue = el.attr[attrId];
if (elValue !== undefined && elValue === attrValue) {
let newKey = keys[j];
bindDir(vm, el, 'attrStyle', css[newKey]);
}
}
}
}
}
}
}
+92 -2
View File
@@ -47,6 +47,9 @@ class Element extends Node {
private _event: any;
private _idStyle: any;
private _tagStyle: any;
private _attrStyle: any;
private _tagAndTagStyle: any;
private _firstOrLastChildStyle: any;
private _universalStyle: any;
private _id: string | null;
private _classList: any[];
@@ -55,6 +58,9 @@ class Element extends Node {
private _isCustomComponent: boolean;
private _inheritedStyle: object;
private _target:TemplateInterface;
private _hasBefore: boolean;
private _hasAfter: boolean;
private _isOpen: boolean;
protected _children: Node[];
protected _pureChildren: Element[];
@@ -104,6 +110,9 @@ class Element extends Node {
this._event = {};
this._idStyle = {};
this._tagStyle = {};
this._attrStyle = {};
this._tagAndTagStyle = {};
this._firstOrLastChildStyle = {};
this._universalStyle = {};
this._id = null;
this._classList = [];
@@ -171,6 +180,30 @@ class Element extends Node {
this._vm = newVm;
}
public get hasBefore() {
return this._hasBefore;
}
public set hasBefore(hasBefore: boolean) {
this._hasBefore = hasBefore;
}
public get hasAfter() {
return this._hasAfter;
}
public set hasAfter(hasAfter: boolean) {
this._hasAfter = hasAfter;
}
public get isOpen() {
return this._isOpen;
}
public set isOpen(isOpen: boolean) {
this._isOpen = isOpen;
}
/**
* Class style object of this Element, which keys is style name, and values is style values.
* @type {JSON}
@@ -777,7 +810,7 @@ class Element extends Node {
return;
}
// If inline id class style has define return.
if (this.style[key] || this._idStyle[key] || this._classStyle[key]) {
if (this.style[key] || this._idStyle[key] || this._attrStyle[key] || this._classStyle[key] || this._firstOrLastChildStyle[key] || this._tagAndTagStyle[key]) {
return;
}
this._tagStyle[key] = value;
@@ -789,12 +822,63 @@ class Element extends Node {
}
}
public setAttrStyle(key: string, value: string | number, silent: boolean = false): void {
if (this._attrStyle[key] === value && silent !== false) {
return;
}
// If inline id style define return.
if (this.style[key] || this._idStyle[key]) {
return;
}
this._attrStyle[key] = value;
const taskCenter = this.getTaskCenter(this.docId);
if (!silent && taskCenter) {
const result = {};
result[key] = value;
taskCenter.send('dom', { action: 'updateStyle' }, [this.ref, result]);
}
}
public setTagAndTagStyle(key: string, value: string | number, silent: boolean = false): void {
if (this._tagAndTagStyle[key] === value && silent !== false) {
return;
}
// If inline id class style has define return.
if (this.style[key] || this._idStyle[key] || this._attrStyle[key] || this._classStyle[key] || this._firstOrLastChildStyle[key]) {
return;
}
this._tagAndTagStyle[key] = value;
const taskCenter = this.getTaskCenter(this.docId);
if (!silent && taskCenter) {
const result = {};
result[key] = value;
taskCenter.send('dom', { action: 'updateStyle' }, [this.ref, result]);
}
}
public setFirstOrLastChildStyle(key: string, value: string | number, silent: boolean = false): void {
if (this._firstOrLastChildStyle[key] === value && silent !== false) {
return;
}
// If inline id class style has define return.
if (this.style[key] || this._idStyle[key] || this._attrStyle[key]) {
return;
}
this._firstOrLastChildStyle[key] = value;
const taskCenter = this.getTaskCenter(this.docId);
if (!silent && taskCenter) {
const result = {};
result[key] = value;
taskCenter.send('dom', { action: 'updateStyle' }, [this.ref, result]);
}
}
public setUniversalStyle(key: string, value: string | number, silent: boolean = false): void {
if (this._universalStyle[key] === value && silent !== false) {
return;
}
// If inline id class style has define return.
if (this.style[key] || this._idStyle[key] || this._classStyle[key] || this._tagStyle[key]) {
if (this.style[key] || this._idStyle[key] || this._classStyle[key] || this._tagStyle[key] || this._tagAndTagStyle[key]) {
return;
}
this._universalStyle[key] = value;
@@ -881,7 +965,10 @@ class Element extends Node {
const style = Object.assign({}, this._inheritedStyle);
this.assignStyle(style, this._universalStyle);
this.assignStyle(style, this._tagStyle);
this.assignStyle(style, this._tagAndTagStyle);
this.assignStyle(style, this._classStyle);
this.assignStyle(style, this._attrStyle);
this.assignStyle(style, this._firstOrLastChildStyle);
this.assignStyle(style, this._idStyle);
this.assignStyle(style, this.style);
return style;
@@ -983,6 +1070,9 @@ class Element extends Node {
this._event = {};
this._idStyle = {};
this._tagStyle = {};
this._attrStyle = {};
this._tagAndTagStyle = {};
this._firstOrLastChildStyle = {};
this._universalStyle = {};
this._classList.length = 0;