成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

用RxJS和react開發(fā)mac地址輸入框

CastlePeaK / 2371人閱讀

摘要:項(xiàng)目簡介本次使用了和開發(fā)了一個(gè)地址輸入框,主要實(shí)現(xiàn)的功能有限制輸入符合條件的字符并每隔兩位可以自動添加用于分割的冒號。項(xiàng)目屏蔽了的事件處理,同時(shí)使用來手動控制光標(biāo)。繼承于和因此同時(shí)具有和兩者的方法。后面的和都是需要利用最新的來進(jìn)行判斷的。

項(xiàng)目簡介

本次使用了RxJS和react開發(fā)了一個(gè)mac地址輸入框,主要實(shí)現(xiàn)的功能有限制輸入符合條件的字符1-9,a-f,并每隔兩位可以自動添加用于分割的冒號。項(xiàng)目屏蔽了react的事件處理,同時(shí)使用setSelectionRange來手動控制光標(biāo)。可以查看項(xiàng)目的demo,項(xiàng)目地址

RxJS簡介

RxJS 是 Reactive Extensions 在 JavaScript 上的實(shí)現(xiàn),具體來說是一系列工具庫,包括事件處理,函數(shù)節(jié)流,延時(shí)等函數(shù),RxJS應(yīng)用了’流‘的思想,同時(shí)具有事件和時(shí)間的概念。RxJS也可以用于處理異步流程,比起Promise具有可取消和可延遲,重試等優(yōu)點(diǎn)。Promise vs Observable
RxJS中有兩個(gè)比較重要的概念,分別是Observable和observer。Observable可以使用create,of,from,fromEvent等方法來產(chǎn)生流,而Observer可以對流進(jìn)行觀察。最后兩者通過subscribe來結(jié)合,例子如下:

var Observable = Rx.Observable.create(observer => {
    observer.next(2);
    observer.complete();
    return  () => console.log("disposed");
});

var Observer = Rx.Observer.create(
    x => console.log("Next:", x),
    err => console.log("Error:", err),
    () => console.log("Completed")
);

var subscription = Observable.subscribe(Observer);

來自構(gòu)建流式應(yīng)用—RxJS詳解

更多關(guān)于RxJS,可以閱讀Introduction | RxJS - Javascript library for functional reactive programming.

項(xiàng)目結(jié)構(gòu)
    // 監(jiān)聽事件,發(fā)起流和處理流
    componentDidMount () {
    this.t = ReactDOM.findDOMNode(this.refs.t)
    let keydownValue = Rx.Observable.fromEvent(this.t,"keydown").map(e => e.key.toUpperCase())
    this.sa = keydownValue.filter(value => value.length === 1 && value.match(/[0-9A-F]/)).subscribe(value => {this.setColon("before");this.insertValue(value); this.setColon();this.setDomValue()})
    // 省略類似的部分
    }
    // 取消訂閱
    componentWillUnmount() 
    this.sa.dispose()
    // 類似的部分省略
    }
    
    // 一些用到的方法,這里省略
    
    
    // 取消原生的事件監(jiān)聽
    render() {
      return (
        
e.preventDefault()} ref="t"/>
); }
項(xiàng)目詳解

首先使用Rx.Observable.fromEvent來監(jiān)聽輸入框的按鍵事件,并獲取按鍵的key值,保存為keydownValue

 let keydownValue = Rx.Observable.fromEvent(this.t,"keydown")
 .map(e => e.key.toUpperCase())

接著首先考慮輸入字符的情況,在這里,顯示篩選出按鍵符合要求的情況,接著在subscribe中對數(shù)據(jù)進(jìn)行處理。在插入新的字符之前和之后,都需要判斷是否在前面加上冒號,最后使用setDomValue來讓保存在state中的value顯示到輸入框上。

    this.sa = keydownValue
        .filter(value => value.length === 1 && value.match(/[0-9A-F]/))
        .subscribe(value => {
          this.setColon("before");
          this.insertValue(value); 
          this.setColon();
          this.setDomValue()
        })

判斷是否需要插入冒號的函數(shù)setColon,需要排除前面沒有字符和周圍已經(jīng)有冒號的情況。

  setColon = type => this.state.value.length && 
      (type !== "before" ? !this.isNearColon() : !this.isLastColon()) && 
      !(this.state.value.slice(0, this.state.pos).replace(/:/g, "").length%2) && 
      this.insertValue(":")

插入新字符的函數(shù)。在記錄的光標(biāo)位置pos值上插入新的字符,然后改變光標(biāo)位置。如果在字符末尾有未完成的字符對(即1f:的形式)又在中間插入新的字符串且字符對已經(jīng)到達(dá)六個(gè),則刪掉最后一個(gè)字符對。

  insertValue = value => {
    if (this.state.value.length !== 17) {
      this.setState({
      ...this.state,
      value: this.state.value.slice(0, this.state.pos) + 
        value + this.state.value.slice(this.state.pos, this.state.value.length)
      })
      this.setPos(this.state.pos + 1)
      if (this.state.value.split(":").length === 7) {
        this.setState({
        ...this.state, 
        value: this.state.value.slice(0, this.state.value.lastIndexOf(":"))
        })
      }
  }}

接著是講解關(guān)于刪除的流,篩選按鍵值為"BACKSPACE"的流,執(zhí)行deleteValue方法和setDomValue

    this.sb = keydownValue.filter(value => value === "BACKSPACE")
    .subscribe(() => {
      this.deleteValue()
      this.setDomValue()
    })

deleteValue,在value和位置都大于零時(shí)才執(zhí)行,如果刪除后字符后,新的最后一個(gè)字符是冒號,則自動刪掉該冒號。

  deleteValue = () => {
    if (this.state.value.length && this.state.pos) {
      this.setState({
      ...this.state, 
      value: this.state.value.slice(0, this.state.pos - 1) + 
      this.state.value.slice(this.state.pos, this.state.value.length)
      })
      this.setPos(this.state.pos - 1)
      if (this.isLastColon()) {
        this.deleteValue()
      }
    }
  }

接著是訂閱了左右方向鍵移動的流,比較簡單,就不詳細(xì)解釋了。

    this.sc = keydownValue
        .filter(value => value === "ARROWLEFT")
        .subscribe(() => this.moveLeft())
    this.sd = keydownValue
        .filter(value => value === "ARROWRIGHT")
        .subscribe(() => this.moveRight())
 
      moveLeft = () => this.state.pos > 0 && 
      this.setState({...this.state, pos: this.state.pos - 1})
      moveRight = () => this.state.pos !== this.state.value.length && 
      this.setState({...this.state, pos: this.state.pos + 1})

最后是讓光標(biāo)跳到pos的處理,setSelectionRange本用于文字的選擇,但如果前兩個(gè)參數(shù)為一樣的數(shù)值,可以達(dá)到讓光標(biāo)跳到指定位置的效果。

    this.se = keydownValue.subscribe(() => this.goPos())
    goPos = () => this.t.setSelectionRange(this.state.pos, this.state.pos)
170624更新

原本的模式跟react關(guān)系較少,因此修改調(diào)整了一下,主要的變化是啟用了Subject,setStateAsync,在這里先介紹一下。

Rx.Subject

Subject繼承于Obserable和Observer,因此同時(shí)具有Obserable和Observer兩者的方法。通過來自于Observable的multicast方法可以掛載subject,并得到擁有相同執(zhí)行環(huán)境的多路的新的Observable,關(guān)于他的訂閱實(shí)際上是掛載在subject上。最后需要手動connect。 RxJS 核心概念之Subject,30 天精通 RxJS(24): Observable operators - multicast, refCount, publish, share

var source = Rx.Observable.from([1, 2, 3]);
var multicasted = source.multicast(new Rx.Subject())

// 通過`subject.subscribe({...})`訂閱Subject的Observer:
multicasted.subscribe({
  next: (v) => console.log("observerA: " + v)
});
multicasted.subscribe({
  next: (v) => console.log("observerB: " + v)
});

// 讓Subject從數(shù)據(jù)源訂閱開始生效:
multicasted.connect();

其實(shí)可以用refCount來避免connect,用publish來代替 multicast(new Rx.Subject()),最后用share代替publish 和 refCount,因此代碼可以寫成

var multicasted = source.share()
setStateAsync

組件改為受控組件之后,setState中的異步特性展示了出來,setState后的下一步獲取setState并不是最新的state,影響了程序的正常使用。
例如之前的新增函數(shù)的訂閱。后面的inserValue和setColon都是需要利用最新的state來進(jìn)行判斷的。

    this.sa = keydownValue
      .filter(value => value.length === 1 && value.match(/[0-9A-F]/))
        .subscribe(value => {
          this.setColon("before");
          this.insertValue(value); 
          this.setColon();
          this.setDomValue()
        })

可以在setState的第二個(gè)參數(shù)中傳入回調(diào)函數(shù)來解決這個(gè)問題,于是函數(shù)變成了這樣,一層又一層的回調(diào),十分不美觀

this.sa = keydownValue
  .filter(value => value.length === 1 && value.match(/[0-9A-F]/))
    .subscribe(value => {
      this.setColon("before", () => {
        this.insertValue(value, () => {
          this.setColon()
        })
      })
    })
    

接著在網(wǎng)上找到了setStateAsync的函數(shù),原理就是將setState轉(zhuǎn)換成promise的形式,接著就能愉快的使用async await的語法來修改state了。React中setState同步更新策略

  setStateAsync = state => new Promise(resolve => this.setState(state,resolve))
實(shí)際的調(diào)整

在componentDidMount中把keydownValue設(shè)置為同時(shí)具有Observable和Observe的方法的Subject,他一方面可以使用Observer的onNext方法來添加新的數(shù)據(jù),另一方面可以繼續(xù)使用Observable的操作符來對數(shù)據(jù)進(jìn)行處理。

this.keydownValue = new Rx.Subject()
let multicasted = this.keydownValue.map(e => e.key.toUpperCase()).share()
this.sa = multicasted
  .filter(value => value.length === 1 && value.match(/[0-9A-F]/))
    .subscribe(async value => {
    await this.setColon("before")
    await this.insertValue(value)
    await this.setColon()
    this.goPos()
  })
//下略    

組件的render函數(shù)修改為

  

handleE函數(shù)繼續(xù)禁止默認(rèn)事件,調(diào)用了新設(shè)置的Subject(keydownValue)的onNext方法,可以使得綁定在keydownValue上的訂閱獲得數(shù)據(jù)

  handleE = e => {e.preventDefault();this.keydownValue.onNext(e)}

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94223.html

相關(guān)文章

  • Rxjs 響應(yīng)式編程-第六章 使Cycle.js的響應(yīng)式Web應(yīng)程序

    摘要:我們將使用,這是一個(gè)現(xiàn)代,簡單,漂亮的框架,在內(nèi)部使用并將響應(yīng)式編程概念應(yīng)用于前端編程。驅(qū)動程序采用從我們的應(yīng)用程序發(fā)出數(shù)據(jù)的,它們返回另一個(gè)導(dǎo)致副作用的。我們將使用來呈現(xiàn)我們的應(yīng)用程序。僅采用長度超過兩個(gè)字符的文本。 Rxjs 響應(yīng)式編程-第一章:響應(yīng)式Rxjs 響應(yīng)式編程-第二章:序列的深入研究Rxjs 響應(yīng)式編程-第三章: 構(gòu)建并發(fā)程序Rxjs 響應(yīng)式編程-第四章 構(gòu)建完整的We...

    EastWoodYang 評論0 收藏0
  • 大廠前端面試考什么?

    摘要:面試流程如果你時(shí)間緊張或是在職,大部分大公司是支持第一輪電話面試的,而騰訊,阿里的面試基本前兩輪都是電話面。組員面總體來說考察的東西較基礎(chǔ)。也有會問你設(shè)計(jì)模式,各種繼承方法的對于大廠的面試來說,重要性可能比還要高。 背景 我最近一個(gè)月面試了20來個(gè)公司,其中有你們應(yīng)該都聽過的bat,今日頭條,京東,網(wǎng)易,大疆,oppo,還有shopee,招商金科,有贊等比較不錯的公司,收獲了六個(gè)off...

    jubincn 評論0 收藏0
  • 使 AVA 做自動化測試

    摘要:單元測試,測試一個(gè)簡單的組件。接口測試,用戶信息接口測試。學(xué)習(xí)借鑒,一些使用做測試的開源項(xiàng)目。這里使用到的內(nèi)置斷言斷言結(jié)果值等于我們想要的預(yù)期值,則測試通過。在里放入一個(gè)函數(shù),函數(shù)自動執(zhí)行,里面執(zhí)行的結(jié)果必須拋出錯誤,則測試通過。 目錄 1、為什么選擇 AVA ?2、API 概覽。3、準(zhǔn)備工作。4、單元測試,測試一個(gè)簡單的工具函數(shù)。5、使用 Promise、Async/await、Ob...

    Cruise_Chan 評論0 收藏0
  • FCC 成都社區(qū)·前端周刊 第 11 期

    摘要:正式發(fā)布已正式發(fā)布,新版本重點(diǎn)關(guān)注工具鏈以及工具鏈在中的運(yùn)行速度問題。文章內(nèi)容包括什么是內(nèi)存,內(nèi)存生命周期,中的內(nèi)存分配,內(nèi)存釋放,垃圾收集,種常見的內(nèi)存泄漏以及如何處理內(nèi)存泄漏的技巧。 1. Angular 6 正式發(fā)布 Angular 6.0.0 已正式發(fā)布,新版本重點(diǎn)關(guān)注工具鏈以及工具鏈在 Angular 中的運(yùn)行速度問題。Angular v6 是統(tǒng)一整體框架、Material ...

    lentrue 評論0 收藏0
  • FCC 成都社區(qū)·前端周刊 第 11 期

    摘要:正式發(fā)布已正式發(fā)布,新版本重點(diǎn)關(guān)注工具鏈以及工具鏈在中的運(yùn)行速度問題。文章內(nèi)容包括什么是內(nèi)存,內(nèi)存生命周期,中的內(nèi)存分配,內(nèi)存釋放,垃圾收集,種常見的內(nèi)存泄漏以及如何處理內(nèi)存泄漏的技巧。 1. Angular 6 正式發(fā)布 Angular 6.0.0 已正式發(fā)布,新版本重點(diǎn)關(guān)注工具鏈以及工具鏈在 Angular 中的運(yùn)行速度問題。Angular v6 是統(tǒng)一整體框架、Material ...

    NusterCache 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<