diff --git a/html5/runtime/utils.js b/html5/runtime/utils.js
index 9bb69172d9..c2ab10f02d 100644
--- a/html5/runtime/utils.js
+++ b/html5/runtime/utils.js
@@ -52,3 +52,20 @@ export function base64ToBuffer (base64) {
})
return array.buffer
}
+
+/**
+ * Detect if the param is falsy or empty
+ * @param {any} any
+ */
+export function isEmpty (any) {
+ if (!any || typeof any !== 'object') {
+ return true
+ }
+
+ for (const key in any) {
+ if (Object.prototype.hasOwnProperty.call(any, key)) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/html5/runtime/vdom/Element.js b/html5/runtime/vdom/Element.js
index 712b925503..5ba05ba05c 100644
--- a/html5/runtime/vdom/Element.js
+++ b/html5/runtime/vdom/Element.js
@@ -28,7 +28,7 @@ import {
moveIndex,
removeIndex
} from './operation'
-import { uniqueId } from '../utils'
+import { uniqueId, isEmpty } from '../utils'
import { getWeexElement, setElement } from './WeexElement'
const DEFAULT_TAG_NAME = 'div'
@@ -303,15 +303,23 @@ export default class Element extends Node {
* @param {boolean} silent
*/
setAttrs (batchedAttrs, silent) {
- // TODO: validate batched attributes
- Object.assign(this.attr, batchedAttrs)
- const taskCenter = getTaskCenter(this.docId)
- if (!silent && taskCenter) {
- taskCenter.send(
- 'dom',
- { action: 'updateAttrs' },
- [this.ref, batchedAttrs]
- )
+ if (isEmpty(batchedAttrs)) return
+ const mutations = {}
+ for (const key in batchedAttrs) {
+ if (this.attr[key] !== batchedAttrs[key]) {
+ this.attr[key] = batchedAttrs[key]
+ mutations[key] = batchedAttrs[key]
+ }
+ }
+ if (!isEmpty(mutations)) {
+ const taskCenter = getTaskCenter(this.docId)
+ if (!silent && taskCenter) {
+ taskCenter.send(
+ 'dom',
+ { action: 'updateAttrs' },
+ [this.ref, mutations]
+ )
+ }
}
}
@@ -344,15 +352,23 @@ export default class Element extends Node {
* @param {boolean} silent
*/
setStyles (batchedStyles, silent) {
- // TODO: validate batched styles
- Object.assign(this.style, batchedStyles)
- const taskCenter = getTaskCenter(this.docId)
- if (!silent && taskCenter) {
- taskCenter.send(
- 'dom',
- { action: 'updateStyle' },
- [this.ref, batchedStyles]
- )
+ if (isEmpty(batchedStyles)) return
+ const mutations = {}
+ for (const key in batchedStyles) {
+ if (this.style[key] !== batchedStyles[key]) {
+ this.style[key] = batchedStyles[key]
+ mutations[key] = batchedStyles[key]
+ }
+ }
+ if (!isEmpty(mutations)) {
+ const taskCenter = getTaskCenter(this.docId)
+ if (!silent && taskCenter) {
+ taskCenter.send(
+ 'dom',
+ { action: 'updateStyle' },
+ [this.ref, mutations]
+ )
+ }
}
}
diff --git a/html5/test/unit/runtime/utils.js b/html5/test/unit/runtime/utils.js
new file mode 100644
index 0000000000..64807057c7
--- /dev/null
+++ b/html5/test/unit/runtime/utils.js
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 { expect } from 'chai'
+import * as utils from '../../../runtime/utils'
+
+describe('utils', () => {
+ it('isEmpty', () => {
+ expect(utils.isEmpty()).to.be.true
+ expect(utils.isEmpty(0)).to.be.true
+ expect(utils.isEmpty(null)).to.be.true
+ expect(utils.isEmpty(undefined)).to.be.true
+ expect(utils.isEmpty(false)).to.be.true
+ expect(utils.isEmpty(true)).to.be.true
+ expect(utils.isEmpty(NaN)).to.be.true
+ expect(utils.isEmpty([])).to.be.true
+ expect(utils.isEmpty({})).to.be.true
+ expect(utils.isEmpty(Object.create(null))).to.be.true
+ expect(utils.isEmpty(Object.create({}))).to.be.true
+ expect(utils.isEmpty(Object.create({ x: '' }))).to.be.true
+
+ expect(utils.isEmpty({ abc: '' })).to.be.false
+ expect(utils.isEmpty([0])).to.be.false
+ })
+})