Learning: In a pure vanilla JS client-side filtering loop, grouping multiple boolean conditions (like matchesSemester && matchesClass && matchesCategory && matchesSearch) forces all conditions to be evaluated for every item, even if the first condition fails. Furthermore, doing string manipulations (like .toLowerCase()) on multiple properties inside the filter callback on every keystroke causes significant CPU overhead for large lists.
Action: Always use explicit early returns (if (!condition) return false;) to short-circuit the loop as soon as possible. Move expensive string processing out of the render loop by calculating a derived _searchStr property once during the initial data load, reducing the per-keystroke filter to a simple, pre-computed substring check.