A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

观察者模式观察者模式也叫发布订阅模式. 最经典的用法就是在事件监听里面.
    <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



4 个回复

倒序浏览
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马