黑马程序员技术交流社区
标题:
【上海校区】通过Observable解决搜索框问题
[打印本页]
作者:
不二晨
时间:
2018-10-23 09:38
标题:
【上海校区】通过Observable解决搜索框问题
观察者模式
观察者模式
也叫发布订阅模式. 最经典的用法就是在事件监听里面.
<button onClick = "handle()">确认</button> handle方法订阅了onClick事件,当用户点击(发布)onClick, handle方法触发复制代码大致提一下,网上对观察者模式的解释有很多. Observable就是基于观察者模式实现的
Observable方法的定义
基本特征:
是一个函数
接受一个
Observer
对象
返回一个具有
unsubscribe
功能的函数或者对象
let ob = new Observable(obser => { // 这个函数是“发布” obser.next()})// 订阅了console.log(12)动作ob.subscribe({ next(){console.log(12)}})注:只有subscribe方法执行了才会执行"发布"函数复制代码在core-js中已对observable做了扩展,通过import "core-js/es7/observable"可以使用Observable
实现Observable方法
便于理解,还是简单的实现一个Observable吧,代码如下
class SubscriptionObserver { constructor(ob, debounceTime){ this.ob = ob || {}; this.debounceTime = debounceTime; this.unSub = false; this.timeout = null; } next(value){ if (!this.unSub && this.ob.next){ clearTimeout(this.timeout) this.timeout = setTimeout(() => { !this.unSub &&this.ob.next(value); this.timeout = null; }, this.debounceTime) } else { this.ob.next(value); } } error(){ if (!this.unSub && this.ob.error){ this.ob.error(); } } complete(){ if (!this.unSub && this.complete){ this.ob.complete(); } } unsubcribe(){ this.unSub = true; }}class Observable { constructor(SubscriptionOb) { this.SubscriptionOb = SubscriptionOb; } subscribe(ob){ this.subOb = new SubscriptionObserver(ob, this.timeout); return this.SubscriptionOb(this.subOb); } unsubcribe(){ this.subOb.unsubcribe() return this; } debounceTime(timeout){ this.timeout = timeout; return this; }}复制代码
主要增加了
debounceTime
功能, 在
debounceTime
在lazy时间内只会执行最后一次
next
方法
搜索框的应用
搜索框的搜索主要是要解决2个问题
不能在用户输入每个字符的时候就触发搜索。
服务器的异步返回时间不一致,先搜索的字符可能数据可能返回比后搜索的慢
代码如下
export default class Tudos extends React.Component { state = { text:"" } // 搜索关键字接口 searchKeyWords(text){ return new Promise((resolve) => { setTimeout(() => { let list = [{...}...] resolve(list) }, 2000) }) } handleInput(dom) { let oba = new Observable(ob => { dom.oninput = e => { ob.next(e.target.value) } }).debounceTime(500).subscribe({ next(value){getList(value)} }) } render() { return (<div> <input ref = {dom => dom && this.handleInput(dom)}/> </div>) }}复制代码总会在用户输入完500毫秒后执行
next
函数。这个上述代码已实现. 第二个问题还未解决!
引入RxJS
安装
npm i @reactivex/rxjs --save;复制代码引入
import * as Rx from "@reactivex/rxjs";复制代码
RxJS
当做是用来处理事件的
Lodash
.像这种复杂的事件处理第一个就是想到使用
RxJS
具体的使用可以参考以下
官方文档
代码如下
export default class SimpleSortableList extends Component { componentDidMount() { } // 搜索关键字接口 searchKeyWords(text){ return new Promise((resolve) => { setTimeout(() => { let list = [{...}...] resolve(list) }, 2000) }) } handleInput(button){ Rx.Observable.fromEvent(button, 'input') .debounceTime(500) .switchMap(e => { return Rx.Observable.create(ob => { this.searchKeyWords(e.target.value).then(res => { ob.next(list) }) }); }) .subscribe(text => console.log(text)) } render() { return ( <div className={prefix}> <input ref = { dom => dom && this.handleInput(dom)} /> </div> ); }}复制代码
通过
debounceTime
延迟返回结果
通过
switchMap
丢弃上一个未及时返回的结果
而且整个代码显得如此短小精悍
【转载】
作者:fiveoneLei
链接:
https://juejin.im/post/5bc84b375188255c554728f1
作者:
小影姐姐
时间:
2018-10-25 09:46
作者:
不二晨
时间:
2018-10-25 10:48
作者:
魔都黑马少年梦
时间:
2018-11-1 16:57
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2