feat(hippy-vue): perf attribute update

This commit is contained in:
zoomchan-cxj
2022-08-16 20:25:44 +08:00
committed by Zoom Chan
parent 689bce49fd
commit fef30e7cd8
4 changed files with 52 additions and 26 deletions
+26 -20
View File
@@ -245,18 +245,20 @@ class ElementNode extends ViewNode {
setAttribute(key, value, options = {}) {
try {
let propKey = key;
let propValue = value;
// detect expandable attrs for boolean values
// See https://vuejs.org/v2/guide/components-props.html#Passing-a-Boolean
if (typeof (this.attributes[key]) === 'boolean' && value === '') {
value = true;
if (typeof (this.attributes[propKey]) === 'boolean' && propValue === '') {
propValue = true;
}
if (key === undefined) {
if (propKey === undefined) {
!options.notToNative && updateChild(this);
return;
}
switch (key) {
switch (propKey) {
case 'class': {
const newClassList = new Set(value.split(' ').filter(x => x.trim()));
const newClassList = new Set(propValue.split(' ').filter(x => x.trim()));
if (setsAreEqual(this.classList, newClassList)) {
return;
}
@@ -266,10 +268,10 @@ class ElementNode extends ViewNode {
return;
}
case 'id':
if (value === this.id) {
if (propValue === this.id) {
return;
}
this.id = value;
this.id = propValue;
// update current node and child nodes
!options.notToNative && updateWithChildren(this);
return;
@@ -278,51 +280,55 @@ class ElementNode extends ViewNode {
case 'value':
case 'defaultValue':
case 'placeholder': {
if (typeof value !== 'string') {
if (typeof propValue !== 'string') {
try {
value = value.toString();
propValue = propValue.toString();
} catch (err) {
throw new TypeError(`Property ${key} must be string:${err.message}`);
throw new TypeError(`Property ${propKey} must be string:${err.message}`);
}
}
if (!options || !options.textUpdate) {
value = value.trim().replace(/( |Â)/g, ' ');
propValue = propValue.trim().replace(/( |Â)/g, ' ');
}
this.attributes[key] = unicodeToChar(value);
propValue = unicodeToChar(propValue);
break;
}
case 'numberOfRows':
this.attributes[key] = value;
if (Native.Platform !== 'ios') {
return;
}
break;
case 'caretColor':
case 'caret-color':
this.attributes['caret-color'] = Native.parseColor(value);
propKey = 'caret-color';
propValue = Native.parseColor(propValue);
break;
case 'break-strategy':
this.attributes.breakStrategy = value;
propKey = 'breakStrategy';
break;
case 'placeholderTextColor':
case 'placeholder-text-color':
this.attributes.placeholderTextColor = Native.parseColor(value);
propKey = 'placeholderTextColor';
propValue = Native.parseColor(propValue);
break;
case 'underlineColorAndroid':
case 'underline-color-android':
this.attributes.underlineColorAndroid = Native.parseColor(value);
propKey = 'underlineColorAndroid';
propValue = Native.parseColor(propValue);
break;
case 'nativeBackgroundAndroid': {
const nativeBackgroundAndroid = value;
const nativeBackgroundAndroid = propValue;
if (typeof nativeBackgroundAndroid.color !== 'undefined') {
nativeBackgroundAndroid.color = Native.parseColor(nativeBackgroundAndroid.color);
}
this.attributes.nativeBackgroundAndroid = nativeBackgroundAndroid;
propKey = 'nativeBackgroundAndroid';
propValue = nativeBackgroundAndroid;
break;
}
default:
this.attributes[key] = value;
}
if (this.attributes[propKey] === propValue) return;
this.attributes[propKey] = propValue;
if (typeof this.filterAttribute === 'function') {
this.filterAttribute(this.attributes);
}
@@ -1,4 +1,22 @@
// TODO: Add UIManagerModule mock module to verify result correction.
/*
* Tencent is pleased to support the open source community by making
* Hippy available.
*
* Copyright (C) 2017-2022 THL A29 Limited, a Tencent company.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import test, { before } from 'ava';
import { registerBuiltinElements } from '../../../elements';
@@ -383,9 +401,6 @@ test('ul numberOfRows test', (t) => {
parentNode.appendChild(childNode2);
const nativeLanguage2 = renderToNativeWithChildren(ROOT_VIEW_ID, parentNode);
t.is(nativeLanguage2[0].props.numberOfRows, 2);
parentNode.setAttribute('numberOfRows', 10);
const nativeLanguage3 = renderToNativeWithChildren(ROOT_VIEW_ID, parentNode);
t.is(nativeLanguage3[0].props.numberOfRows, 10);
});
test('img attributeMaps test --debug mode', (t) => {
@@ -37,8 +37,10 @@ function updateAttrs(oldVNode, vNode) {
vNode.data.attrs = attrs;
}
Object.keys(oldAttrs).forEach((key) => {
const oldPropValue = oldAttrs[key];
const newPropValue = attrs[key];
if (newPropValue === null || newPropValue === undefined) {
if ((oldPropValue !== null && oldPropValue !== undefined)
&& (newPropValue === null || newPropValue === undefined)) {
updatePayload[key] = undefined;
}
});
@@ -58,8 +58,11 @@ function updateStyle(oldVNode, vNode) {
const batchedStyles = {};
// Remove the removed styles at first
Object.keys(oldStyle).forEach((name) => {
const oldStyleValue = oldStyle[name];
const newStyleValue = style[name];
if (newStyleValue === undefined || newStyleValue === null) {
if (
(oldStyleValue !== undefined && oldStyleValue !== null)
&& (newStyleValue === undefined || newStyleValue === null)) {
batchedStyles[normalize(name)] = undefined;
}
});