RxJS 是一种非常流行的响应式编程库,它提供了许多操作符来帮助我们处理流式数据。其中一个非常有用的操作符就是 distinctUntilChanged
。本文将详细介绍该操作符的用法和应用场景。
什么是 distinctUntilChanged
distinctUntilChanged
操作符可以过滤掉连续的重复值,只输出与前一个值不同的值。这是一个很有用的操作符,例如在处理用户输入和状态更新等场景中,我们经常需要避免重复的操作和状态变化,同时保证输出结果的准确性。
如何使用 distinctUntilChanged
distinctUntilChanged
操作符可以在 Observable 上直接调用。它接受一个可选的比较函数,用于判断两个元素是否相等。如果未提供比较函数,则会使用默认的 ===
运算符进行比较。
// javascriptcn.com 代码示例 import { from } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; // 创建一个数字序列 const source$ = from([1, 2, 3, 3, 4, 5, 5, 6]); // 过滤连续的重复值 const distinct$ = source$.pipe(distinctUntilChanged()); // 输出结果:1, 2, 3, 4, 5, 6 distinct$.subscribe(console.log);
在上面的示例中,我们创建了一个数字序列,并使用 distinctUntilChanged
过滤出不重复的数字。由于数字 3 和数字 5 连续出现了两次,但是它们的前后顺序不同,因此它们都被保留了下来。
我们也可以使用比较函数来自定义判重的逻辑。例如,在处理复杂对象时,我们可能只关心某些属性的变化。
// javascriptcn.com 代码示例 import { from } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; // 创建一个用户序列 const source$ = from([ { id: 1, name: 'Tom' }, { id: 2, name: 'Jack' }, { id: 2, name: 'Kate' }, { id: 3, name: 'Jim' }, ]); // 按照 id 属性过滤重复的用户 const distinct$ = source$.pipe( distinctUntilChanged((a, b) => a.id === b.id) ); // 输出结果:{ id: 1, name: 'Tom' }, { id: 2, name: 'Jack' }, { id: 3, name: 'Jim' } distinct$.subscribe(console.log);
在上面的示例中,我们创建了一个用户序列,并使用 distinctUntilChanged
过滤出不重复的用户,按照 id 属性进行比较。由于用户 Jack 和 Kate 具有相同的 id,因此只保留了前者。
distinctUntilChanged 的应用场景
distinctUntilChanged
操作符的应用场景非常广泛,在前端开发中常常用于以下场景:
- 处理用户输入:例如,在输入框中搜索内容时,我们可能需要避免连续重复的搜索,以减少网络请求和渲染。
- 处理状态变化:例如,在 Redux 中,我们可能需要避免连续的状态更新导致组件多次渲染,以提高性能和用户体验。
- 处理滚动事件:例如,在处理滚动事件时,我们可能需要避免重复计算和渲染。
在使用 distinctUntilChanged
时,我们需要注意以下几点:
- 在比较复杂对象时,需要自定义比较函数,确保只比较关键属性。
- 在订阅时需要考虑异步操作的影响,例如在 useEffect 中。
- 在遇到有序序列时,需要注意顺序的影响,例如在使用 scan 操作符时。
综合示例
下面是一个综合示例,展示了如何使用 distinctUntilChanged
、debounceTime
和 switchMap
操作符,处理用户输入和请求数据的场景。
// javascriptcn.com 代码示例 import { fromEvent } from 'rxjs'; import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators'; const input = document.querySelector('input')!; const output = document.querySelector('ul')!; // 监听输入框中的文本变化 const input$ = fromEvent(input, 'input').pipe( debounceTime(500), distinctUntilChanged(), switchMap((event: Event) => { const query = (event.target as HTMLInputElement).value; return fetch(`https://api.github.com/search/repositories?q=${query}`).then(response => response.json()); }) ); // 订阅输出结果 input$.subscribe(data => { output.innerHTML = ''; for (let item of data.items) { const li = document.createElement('li'); li.textContent = item.full_name; output.appendChild(li); } });
在上面的示例中,我们监听输入框中的文本变化,并使用 debounceTime
实现 debounce 功能,以减少网络请求。使用 distinctUntilChanged
来避免连续的重复搜索,并使用 switchMap
实现取消前一个请求,只保留最后一个请求的结果。最后将请求结果渲染到 HTML 列表中。
总结
distinctUntilChanged
操作符是 RxJS 中一个非常有用的操作符,它可以过滤掉连续的重复值,保证输出结果的准确性。在处理用户输入和状态更新等场景中,非常适合使用该操作符,同时需要注意自定义比较函数、异步订阅和有序序列等问题。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6539d0b27d4982a6eb35ae52