Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit bf60182

Browse files
committed
perf(jqLite): avoid repeated add/removeAttribute in jqLiteRemoveClass
Fixes #16078 Closes #16131
1 parent 8f61cf6 commit bf60182

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

src/jqLite.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -420,13 +420,15 @@ function jqLiteHasClass(element, selector) {
420420

421421
function jqLiteRemoveClass(element, cssClasses) {
422422
if (cssClasses && element.setAttribute) {
423+
var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
424+
.replace(/[\n\t]/g, ' ');
425+
423426
forEach(cssClasses.split(' '), function(cssClass) {
424-
element.setAttribute('class', trim(
425-
(' ' + (element.getAttribute('class') || '') + ' ')
426-
.replace(/[\n\t]/g, ' ')
427-
.replace(' ' + trim(cssClass) + ' ', ' '))
428-
);
427+
cssClass = trim(cssClass);
428+
existingClasses = existingClasses.replace(' ' + cssClass + ' ', ' ');
429429
});
430+
431+
element.setAttribute('class', trim(existingClasses));
430432
}
431433
}
432434

test/jqLiteSpec.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,23 @@ describe('jqLite', function() {
914914
});
915915

916916

917+
// JQLite specific implementation/performance tests
918+
if (_jqLiteMode) {
919+
it('should only get/set the attribute once when multiple classes added', function() {
920+
var fakeElement = {
921+
nodeType: 1,
922+
setAttribute: jasmine.createSpy(),
923+
getAttribute: jasmine.createSpy().and.returnValue('')
924+
};
925+
var jqA = jqLite(fakeElement);
926+
927+
jqA.addClass('foo bar baz');
928+
expect(fakeElement.getAttribute).toHaveBeenCalledOnceWith('class');
929+
expect(fakeElement.setAttribute).toHaveBeenCalledOnceWith('class', 'foo bar baz');
930+
});
931+
}
932+
933+
917934
it('should not add duplicate classes', function() {
918935
var jqA = jqLite(a);
919936
expect(a.className).toBe('');
@@ -1031,6 +1048,23 @@ describe('jqLite', function() {
10311048
jqA.removeClass('foo baz noexistent');
10321049
expect(a.className).toBe('bar');
10331050
});
1051+
1052+
1053+
// JQLite specific implementation/performance tests
1054+
if (_jqLiteMode) {
1055+
it('should get/set the attribute once when removing multiple classes', function() {
1056+
var fakeElement = {
1057+
nodeType: 1,
1058+
setAttribute: jasmine.createSpy(),
1059+
getAttribute: jasmine.createSpy().and.returnValue('foo bar baz')
1060+
};
1061+
var jqA = jqLite(fakeElement);
1062+
1063+
jqA.removeClass('foo baz noexistent');
1064+
expect(fakeElement.getAttribute).toHaveBeenCalledOnceWith('class');
1065+
expect(fakeElement.setAttribute).toHaveBeenCalledOnceWith('class', 'bar');
1066+
});
1067+
}
10341068
});
10351069
});
10361070

0 commit comments

Comments
 (0)