Skip to content

Commit 67a77d2

Browse files
committed
refactor v-bind:class
- revert class update mechanism due to perf regression - normalize array of (string|object) and objects into array of strings. this simplifies the scenario for the rest of the code.
1 parent fee414f commit 67a77d2

File tree

2 files changed

+47
-48
lines changed

2 files changed

+47
-48
lines changed

src/directives/internal/class.js

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,75 @@ import {
22
addClass,
33
removeClass,
44
isArray,
5-
isPlainObject
5+
isObject
66
} from '../../util/index'
77

88
export default {
99

1010
deep: true,
1111

1212
update (value) {
13-
if (value && typeof value === 'string') {
14-
this.handleObject(stringToObject(value))
15-
} else if (isPlainObject(value)) {
16-
this.handleObject(value)
17-
} else if (isArray(value)) {
18-
this.handleArray(value)
19-
} else {
13+
if (!value) {
2014
this.cleanup()
15+
} else if (typeof value === 'string') {
16+
this.setClass(value.trim().split(/\s+/))
17+
} else {
18+
this.setClass(normalize(value))
2119
}
2220
},
2321

24-
handleObject (value) {
25-
this.cleanup(value)
26-
this.prevKeys = Object.keys(value)
27-
setObjectClasses(this.el, value)
28-
},
29-
30-
handleArray (value) {
22+
setClass (value) {
3123
this.cleanup(value)
3224
for (var i = 0, l = value.length; i < l; i++) {
3325
var val = value[i]
34-
if (val && isPlainObject(val)) {
35-
setObjectClasses(this.el, val)
36-
} else if (val && typeof val === 'string') {
37-
addClass(this.el, val)
26+
if (val) {
27+
apply(this.el, val, addClass)
3828
}
3929
}
40-
this.prevKeys = value.slice()
30+
this.prevKeys = value
4131
},
4232

4333
cleanup (value) {
44-
if (!this.prevKeys) return
45-
46-
var i = this.prevKeys.length
34+
const prevKeys = this.prevKeys
35+
if (!prevKeys) return
36+
var i = prevKeys.length
4737
while (i--) {
48-
var key = this.prevKeys[i]
38+
var key = prevKeys[i]
4939
if (!key) continue
50-
51-
var keys = isPlainObject(key) ? Object.keys(key) : [key]
52-
for (var j = 0, l = keys.length; j < l; j++) {
53-
toggleClasses(this.el, keys[j], removeClass)
40+
if (key && (!value || value.indexOf(key) < 0)) {
41+
apply(this.el, key, removeClass)
5442
}
5543
}
5644
}
5745
}
5846

59-
function setObjectClasses (el, obj) {
60-
var keys = Object.keys(obj)
61-
for (var i = 0, l = keys.length; i < l; i++) {
62-
var key = keys[i]
63-
if (!obj[key]) continue
64-
toggleClasses(el, key, addClass)
65-
}
66-
}
47+
/**
48+
* Normalize objects and arrays (potentially containing objects)
49+
* into array of strings.
50+
*
51+
* @param {Object|Array<String|Object>} value
52+
* @return {Array<String>}
53+
*/
6754

68-
function stringToObject (value) {
69-
var res = {}
70-
var keys = value.trim().split(/\s+/)
71-
for (var i = 0, l = keys.length; i < l; i++) {
72-
res[keys[i]] = true
55+
function normalize (value) {
56+
const res = []
57+
if (isArray(value)) {
58+
for (var i = 0, l = value.length; i < l; i++) {
59+
const key = value[i]
60+
if (key) {
61+
if (typeof key === 'string') {
62+
res.push(key)
63+
} else {
64+
for (var k in key) {
65+
if (key[k]) res.push(k)
66+
}
67+
}
68+
}
69+
}
70+
} else if (isObject(value)) {
71+
for (var key in value) {
72+
if (value[key]) res.push(key)
73+
}
7374
}
7475
return res
7576
}
@@ -85,14 +86,12 @@ function stringToObject (value) {
8586
* @param {Function} fn
8687
*/
8788

88-
function toggleClasses (el, key, fn) {
89+
function apply (el, key, fn) {
8990
key = key.trim()
90-
9191
if (key.indexOf(' ') === -1) {
9292
fn(el, key)
9393
return
9494
}
95-
9695
// The key contains one or more space characters.
9796
// Since a class name doesn't accept such characters, we
9897
// treat it as multiple classes.

test/unit/specs/directives/internal/class_spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ describe(':class', function () {
1212
var dir = _.extend({ el: el }, def)
1313
dir.update('bar')
1414
expect(el.className).toBe('foo bar')
15-
dir.update('baz')
16-
expect(el.className).toBe('foo baz')
15+
dir.update('baz qux')
16+
expect(el.className).toBe('foo baz qux')
1717
dir.update('qux')
1818
expect(el.className).toBe('foo qux')
1919
dir.update()
@@ -52,7 +52,7 @@ describe(':class', function () {
5252
dir.update(['b', 'c'])
5353
expect(el.className).toBe('a b c')
5454
dir.update(['d', 'c'])
55-
expect(el.className).toBe('a d c')
55+
expect(el.className).toBe('a c d')
5656
dir.update()
5757
expect(el.className).toBe('a')
5858
// test mutating array
@@ -71,7 +71,7 @@ describe(':class', function () {
7171
dir.update(['f', {z: true}])
7272
expect(el.className).toBe('a f z')
7373
dir.update(['l', 'f', {n: true, z: true}])
74-
expect(el.className).toBe('a l f n z')
74+
expect(el.className).toBe('a f z l n')
7575
dir.update(['x', {}])
7676
expect(el.className).toBe('a x')
7777
dir.update()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy