Vue充甚、Type escript和RxJS與Vue-Rx的結(jié)合

目前我正在寫這篇文章以政,有很多方法來解決一個具體的問題。">目前我正在寫這篇文章伴找,有很多方法來解決一個具體的問題盈蛮。</trans>

在本文中,我想給您一個靈感技矮,它可能會改變您在應(yīng)用程序中使用的當(dāng)前方法抖誉。">在本文中,我想給您一個靈感衰倦,它可能會改變您在應(yīng)用程序中使用的當(dāng)前方法袒炉。</trans>

可能與非常復(fù)雜的實(shí)現(xiàn)、測試和維護(hù)相關(guān)樊零。">RxJS可能與非常復(fù)雜的實(shí)現(xiàn)我磁、測試和維護(hù)相關(guān)。

如果我告訴您驻襟,集成夺艰、實(shí)現(xiàn)和測試實(shí)際上非常容易,即使是在一個通用的(小型沉衣、中型郁副、大型)VueJS應(yīng)用程序中也是如此呢?(247, 238, 255);">如果我告訴您厢蒜,集成、實(shí)現(xiàn)和測試實(shí)際上非常容易烹植,即使是在一個通用的(小型斑鸦、中型、大型)VueJS應(yīng)用程序中也是如此呢草雕?

在本文中巷屿,我將演示如何將VueJS、type escript和RxJS結(jié)合起來墩虹。我真的相信這是一個很棒的組合嘱巾,還有一個插件憨琳,它真的很有用:">在本文中,我將演示如何將VueJS旬昭、type escript和RxJS結(jié)合起來篙螟。我真的相信這是一個很棒的組合,還有一個插件问拘,它真的很有用.

你為什么要安裝和使用這個插件遍略?">你為什么要安裝和使用這個插件?

因?yàn)樗卺尫拍愕膽?yīng)用程序的超能力骤坐,它正在創(chuàng)造整個體驗(yàn)绪杏。">因?yàn)樗卺尫拍愕膽?yīng)用程序的超能力,它正在創(chuàng)造整個體驗(yàn)纽绍。略顯更流暢蕾久,作為初級或高級開發(fā)人員。">更流暢拌夏,作為初級或高級開發(fā)人員僧著。

有了一個通用應(yīng)用程序,第一個開始的命令如下:">有了一個通用應(yīng)用程序辖佣,第一個開始的命令如下

npm install vue-rx rxjs --save</pre>

很明顯霹抛,這將Vue-Rx和RxJS安裝到項(xiàng)目的依賴項(xiàng)中。">很明顯卷谈,這將Vue-Rx和RxJS安裝到項(xiàng)目的依賴項(xiàng)中杯拐。

當(dāng)然,我們需要告訴VueJS安裝它(在全球范圍內(nèi)世蔗,是的):">當(dāng)然端逼,我們需要告訴VueJS安裝它(在全球范圍內(nèi),是的)

import Vue from 'vue'
import VueRx from 'vue-rx'

Vue.use(VueRx)</pre>

它導(dǎo)入最小數(shù)量的Rx操作符污淋,并確保小的包大小顶滩。">它導(dǎo)入最小數(shù)量的Rx操作符,并確保小的包大小寸爆。
我親自確認(rèn)礁鲁。">我親自確認(rèn)。

一旦所有的一切都設(shè)置好了赁豆,你就可以使用這個偉大的插件所暴露的任何東西了仅醇。如果我們深入研究類型記錄定義,您就可以快速看到將添加到VueJS中的內(nèi)容:">一旦所有的一切都設(shè)置好了魔种,你就可以使用這個偉大的插件所暴露的任何東西了析二。如果我們深入研究類型記錄定義,您就可以快速看到將添加到VueJS中的內(nèi)容:</trans>

declare module* "vue/types/vue" {
  *interface* Vue {
    $observables: Observables;
    $watchAsObservable(expr: *string*, options?: WatchOptions): Observable<WatchObservable<*any*>>
    $watchAsObservable<T>(fn: (*this*: *this*) => T, options?: WatchOptions): Observable<WatchObservable<T>>
    $eventToObservable(event: *string*): Observable<{name: *string*, msg: *any*}>
    $subscribeTo<T>(
      observable: Observable<T>,
      next: (t: T) => *void*,
      error?: (e: *any*) => *void*,
      complete?: () => *void*): *void* $fromDOMEvent(selector: *string* | *null*, event: *string*): Observable<Event>
    $createObservableMethod(methodName: *string*): Observable<*any*>
  }
}

這看起來可能有點(diǎn)奇怪,但我將很快突出這些特性:">這看起來可能有點(diǎn)奇怪叶摄,但我將很快突出這些特性:
美元可觀測值它將指出已登記的訂閱属韧;">它將指出已登記的訂閱;</trans>
例如蛤吓,一個可觀察的功能可以幫助應(yīng)用于該屬性的流更改宵喂,而不是讓一個泛型函數(shù)監(jiān)視一個反應(yīng)性屬性;">
例如柱衔,一個可觀察的功能可以幫助應(yīng)用于該屬性的流更改樊破,而不是讓一個泛型函數(shù)監(jiān)視一個反應(yīng)性屬性;</trans>
可以將自定義事件處理程序或生命周期掛鉤轉(zhuǎn)換為可觀察的唆铐;">:可以將自定義事件處理程序或生命周期掛鉤轉(zhuǎn)換為可觀察的哲戚;</trans>
這是另一種很好的轉(zhuǎn)換DOM事件的方法(例如,鍵向上艾岂,輸入顺少,點(diǎn)擊等等)變成可觀察的;">:這是另一種很好的轉(zhuǎn)換DOM事件的方法(例如王浴,鍵向上脆炎,輸入,點(diǎn)擊等等)變成可觀察的
這也是一個很好的特性氓辣;如果將一個方法轉(zhuǎn)換為一個可觀察的值并將接收到的值處理為一個反應(yīng)流(例如回調(diào))秒裕,這將很有幫助;">*這也是一個很好的特性钞啸;如果將一個方法轉(zhuǎn)換為一個可觀察的值并將接收到的值處理為一個反應(yīng)流(例如回調(diào))几蜻,這將很有幫助;
它提供了手動注冊一個可觀察到的(聲明下一個錯誤体斩、完全回調(diào))的機(jī)會梭稚,VueRx將管理注冊并在不再有用的情況下處理它(例如已銷毀的組件)。">:它提供了手動注冊一個可觀察到的(聲明下一個錯誤絮吵、完全回調(diào))的機(jī)會弧烤,VueRx將管理注冊并在不再有用的情況下處理它(例如已銷毀的組件)。

在上面蹬敲,這個插件公開了一個">在上面暇昂,這個插件公開了一個=流指令">可與以下內(nèi)容相結(jié)合

DOM事件
很酷,但是如何正確地使用它呢伴嗡?">很酷急波,但是如何正確地使用它呢?

在很多情況下闹究,可以使用上述特性幔崖,在本文中食店,我將介紹一個簡單的案例:一個泛型輸入字段渣淤,它觸發(fā)對給定端點(diǎn)執(zhí)行搜索的請求赏寇。在這種情況下,有很多事情和特性需要考慮:">在很多情況下价认,可以使用上述特性嗅定,在本文中,我將介紹一個簡單的案例:一個泛型輸入字段用踩,它觸發(fā)對給定端點(diǎn)執(zhí)行搜索的請求渠退。在這種情況下,有很多事情和特性需要考慮:

它可以避免每次輸入新字符時發(fā)送大量請求脐彩;">它可以避免每次輸入新字符時發(fā)送大量請求碎乃;
并發(fā)請求呢?哪一個應(yīng)該優(yōu)先考慮惠奸?">并發(fā)請求呢梅誓?哪一個應(yīng)該優(yōu)先考慮?
如果響應(yīng)包含的數(shù)據(jù)可能不包含我們所需要的所有信息呢佛南?我們在哪里處理梗掰?">如果響應(yīng)包含的數(shù)據(jù)可能不包含我們所需要的所有信息呢?我們在哪里處理嗅回?

這是一個基本的場景及穗。在一個特定的項(xiàng)目中,你可能會有另外萬億的分?jǐn)?shù)绵载。你是如何組合/處理它們的埂陆?你如何確保所有的東西都是聲明性的和良好的閱讀?另外尘分,單元測試呢猜惋?">這是一個基本的場景堪遂。在一個特定的項(xiàng)目中昔榴,你可能會有另外萬億的分?jǐn)?shù)懈涛。你是如何組合/處理它們的软棺?你如何確保所有的東西都是聲明性的和良好的閱讀嫂沉?另外翩腐,單元測試呢纵揍?

讓我們開始為我們的組件實(shí)現(xiàn)基本代碼:">讓我們開始為我們的組件實(shí)現(xiàn)基本代碼

 <label *for=*"search">Search for something:</label>
 <input *type=*"text" *id=*"search" *class=*"input-field">
 </div>
</template>

<script *lang=*"ts">
  *import* { Component, Vue }  *from* 'vue-property-decorator';
 @Component
  *export default class* Search *extends* Vue {}
</script>

<style *scoped*>
 .input-field {
 ...
 }
</style></pre>

因?yàn)槲覀円蕾嚧蜃指灏觯晕矣玫氖?>因?yàn)槲覀円蕾嚧蜃指逅焦桑慨a(chǎn)裝飾師這使我們能夠在組件聲明中使用裝飾器(例如組件摹察、Prop等,…)倡鲸。供嚎。">‘這使我們能夠在組件聲明中使用裝飾器(例如組件、Prop等,…)克滴。

在我們的例子中逼争,我們希望實(shí)現(xiàn)一個簡單的行為:鍵入某樣?xùn)|西并作為查詢進(jìn)行搜索。">在我們的例子中劝赔,我們希望實(shí)現(xiàn)一個簡單的行為:鍵入某樣?xùn)|西并作為查詢進(jìn)行搜索誓焦。</trans>

首先,我們需要創(chuàng)建一個可觀察的着帽,它將所有來自字段的輸入流杂伟。一種方法是依賴于輸入標(biāo)記中的keyup事件:">首先,我們需要創(chuàng)建一個可觀察的仍翰,它將所有來自字段的輸入流赫粥。一種方法是依賴于輸入標(biāo)記中的keyup事件

Component<Search>({
    subscriptions() {
        *return* ({
            news: *this*.$fromDOMEvent('input', 'keyup')
        });
    }
})
*export default class* Search *extends* Vue {
    news: any; // we will specifically type it later on
}</pre>

在使用類型記錄時,注冊對VueJS組件的訂閱的方法予借,就是上面聲明的方法傅是。">在使用類型記錄時,注冊對VueJS組件的訂閱的方法蕾羊,就是上面聲明的方法喧笔。</trans>
從“訂閱”函數(shù)返回的對象包含一個屬性“news”,該屬性是一個數(shù)據(jù)屬性龟再,它將與注冊的可觀測值相關(guān)聯(lián)(在本例中為.$fromDOMEVENT…)书闸。。">從“訂閱”函數(shù)返回的對象包含一個屬性“news”利凑,該屬性是一個數(shù)據(jù)屬性浆劲,它將與注冊的可觀測值相關(guān)聯(lián)
當(dāng)輸入字段中輸入某項(xiàng)內(nèi)容時,與“news”相關(guān)聯(lián)的可觀察到的事件將接收到DOM事件“С海現(xiàn)在牌借,讓我們稍微調(diào)整一下邏輯,轉(zhuǎn)而依賴一個字符串(例如割按,字段的值)膨报。">當(dāng)輸入字段中輸入某項(xiàng)內(nèi)容時,與“news”相關(guān)聯(lián)的可觀察到的事件將接收到DOM事件∈嗜伲現(xiàn)在现柠,讓我們稍微調(diào)整一下邏輯,轉(zhuǎn)而依賴一個字符串(例如弛矛,字段的值)够吩。

Component<Search>({
    subscriptions() {
        *return* ({
            news: *this*.$fromDOMEvent('input', 'keyup').pipe(
                pluck<Event, *string*>('target', 'value')
            )
        });
    }
})
*export default class* Search *extends* Vue {
    news: *string*;
}</pre>

為了從接收到的事件中檢索輸入的值,我們可以使用‘">為了從接收到的事件中檢索輸入的值丈氓,我們可以使用拔毛一個由RxJS公開的操作符周循,它允許我們從定義的對象中查看所需的屬性(即使是嵌套的路徑)强法。">一個由RxJS公開的操作符,它允許我們從定義的對象中查看所需的屬性(即使是嵌套的路徑)湾笛。</trans>

<figure style="display: block; margin: 0px 0px 1em; color: rgb(51, 51, 51); font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微軟雅黑, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254); text-decoration-style: initial; text-decoration-color: initial;">

即使有一個字符串拟烫,它對我們也沒有太大的幫助,因?yàn)槲覀冃枰粋€結(jié)果列表迄本。下一步可能是一個簡單的請求,在HackerNewsAPI上搜索給定的查詢(我們的輸入字段值)课竣。">即使有一個字符串嘉赎,它對我們也沒有太大的幫助,因?yàn)槲覀冃枰粋€結(jié)果列表于樟。下一步可能是一個簡單的請求公条,在HackerNewsAPI上搜索給定的查詢(我們的輸入字段值)。</trans>

import* axios *from* 'axios';
*import* { Component, Vue } *from* 'vue-property-decorator';
*import* { *from* } *from* 'rxjs';
*import* { pluck, switchMap } *from* 'rxjs/operators';

*interface* HackerNewsResult {
    objectID: *string*;
    title?: *string*;
    url?: *string*;
}

*interface* HackerNewsSearchResponse {
    hits: Array<HackerNewsResult>
}

*const* hackerNewsEndpoint: *string* = 'http://hn.algolia.com/api/v1/search?query=';

@Component<Search>({
    subscriptions() {
        *return* ({
            news: *this*.$fromDOMEvent('input', 'keyup').pipe(
                pluck<Event, *string*>('target', 'value'),
                switchMap(value => *from*(
                    axios.get<HackerNewsSearchResponse>(`${hackerNewsEndpoint}${value}`)
                    )
                )
            )
        });
    }
})
*export default class* Search *extends* Vue {
    news: Array<HackerNewsResult>;
}</pre>

它開始采取一些實(shí)際的行為迂曲,從行中可以看到發(fā)生了什么:我們從呈現(xiàn)的輸入中流出DOM事件靶橱,我們選擇它的值,并使用來執(zhí)行針對端點(diǎn)的請求路捧。根據(jù)文檔关霸,它開始采取一些實(shí)際的行為,從行中可以看到發(fā)生了什么:我們從呈現(xiàn)的輸入中流出DOM事件杰扫,我們選擇它的值队寇,并使用SwitMap來執(zhí)行針對端點(diǎn)的請求。根據(jù)文檔將每個源值投影到可觀察的可觀測值章姓,該值合并到可觀測的輸出中佳遣,僅從最近預(yù)測的可觀測值中發(fā)出值。">將每個源值投影到可觀察的可觀測值凡伊,該值合并到可觀測的輸出中零渐,僅從最近預(yù)測的可觀測值中發(fā)出值。</trans>*<trans oldtip=" To clarify, the only latest promise will be tracked down till the end (resolved — rejected). Nice! " newtip="為了澄清系忙,唯一的最新承諾將被追查到最后(解決-拒絕)诵盼。好的,漂亮的">為了澄清银还,唯一的最新承諾將被追查到最后(解決-拒絕)拦耐。好的,漂亮的

<figure style="display: block; margin: 0px 0px 1em; color: rgb(51, 51, 51); font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微軟雅黑, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254); text-decoration-style: initial; text-decoration-color: initial;">

現(xiàn)在见剩,最好只針對特定的時間窗口執(zhí)行請求杀糯,而不是每次用戶輸入時都執(zhí)行請求。為了完成這個案子苍苞,我們可以用">現(xiàn)在固翰,最好只針對特定的時間窗口執(zhí)行請求狼纬,而不是每次用戶輸入時都執(zhí)行請求。為了完成這個案子骂际,我們可以用借債時間,它從源發(fā)出一個值疗琉,只有在特定的時間跨度過去之后才能觀察到,而沒有另一個源發(fā)射歉铝。">它從源發(fā)出一個值盈简,只有在特定的時間跨度過去之后才能觀察到,而沒有另一個源發(fā)射太示。</trans>

<trans oldtip="If you have already worked with Lodash/Underscore, “debounce” might sound familiar." newtip="如果您已經(jīng)使用過Lodash/下劃線柠贤,那么“退出”可能聽起來很熟悉。">如果您已經(jīng)使用過Lodash/下劃線类缤,那么“退出”可能聽起來很熟悉臼勉。</trans>

import* { debounceTime, pluck, switchMap } *from* 'rxjs/operators';
@Component<Search>({
    subscriptions() {
        *return* ({
            news: *this*.$fromDOMEvent('input', 'keyup').pipe(
                **debounceTime(300),**
                pluck<Event, *string*>('target', 'value'),
                switchMap(value => *from*(
                    axios.get<HackerNewsSearchResponse>(`${hackerNewsEndpoint}${value}`)
                    )
                )
            )
        });
    }
})
*export default class* Search *extends* Vue {
    news: Array<HackerNewsResult>;
}</pre>

為了解決上面提到的問題,向管道中添加了為了解決上面提到的問題餐弱,向管道中添加了

(dueTime: *number*, scheduler: SchedulerLike = async): MonoTypeOperatorFunction<T> {
  *return* (source: Observable<T>) => source.lift(*new* DebounceTimeOperator(dueTime, scheduler));
}</pre>

作為參數(shù)傳遞給函數(shù)的數(shù)字表示時間窗口宴霸,以毫秒為單位。每次用戶輸入某項(xiàng)內(nèi)容時膏蚓,下一個值將在300 ms后發(fā)出(因此瓢谢,它將聚合下一個條目,以防萬一驮瞧,并在所需的時間之后觸發(fā)下一個值)">作為參數(shù)傳遞給函數(shù)的數(shù)字表示時間窗口恩闻,以毫秒為單位。每次用戶輸入某項(xiàng)內(nèi)容時剧董,下一個值將在300 ms后發(fā)出(因此幢尚,它將聚合下一個條目,以防萬一翅楼,并在所需的時間之后觸發(fā)下一個值)</trans>

<figure style="display: block; margin: 0px 0px 1em; color: rgb(51, 51, 51); font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微軟雅黑, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254); text-decoration-style: initial; text-decoration-color: initial;">

image

<figcaption style="display: block; margin: auto; text-align: center;">http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-debounceTime</figcaption>

</figure>

快好了∥臼#現(xiàn)在,我們需要接受響應(yīng)毅臊,使用有效的信息過濾結(jié)果并將其呈現(xiàn)給用戶理茎。">快好了。現(xiàn)在管嬉,我們需要接受響應(yīng)皂林,使用有效的信息過濾結(jié)果并將其呈現(xiàn)給用戶。

<template>
 <div>
 <label *for=*"search">Search for something:</label>
 <input *type=*"text" *id=*"search" *class=*"input-field">
 ** <ul *v-for=*"item in news">
 <li *:key=*"item.objectID">
 <a *:href=*"item.url">{{ item.title }}</a>
 </li>
 </ul>**
 </div>
</template>

<script *lang=*"ts">
 ...</pre>

*import* { debounceTime, map, pluck, switchMap } *from* 'rxjs/operators';

    @Component<Search>({
 subscriptions(*this*: Vue) {
  *return* ({
 news: *this*.$fromDOMEvent('input', 'keyup').pipe(
 debounceTime(300),
 pluck<Event, *string*>('target', 'value'),
 switchMap(value => *from*(
 axios.get<HackerNewsSearchResponse>(`${hackerNewsEndpoint}${value}`)
 )
 ),
  **pluck<AxiosResponse, Array<HackerNewsResult>>('data', 'hits'),
 map((results: Array<HackerNewsResult>) => results.filter((news: HackerNewsResult) => Boolean(news.title && news.url)))**
                )
            });
        }
    })
    *export default class* Search *extends* Vue {
        news: Array<HackerNewsResult> = [];
    }

首先蚯撩,我在管道中增加了兩個額外的步驟:">首先础倍,我在管道中增加了兩個額外的步驟

考慮到來自Axios承諾的成功響應(yīng),我們從JSON“data”中選擇“HITS”(這包含基于查詢的結(jié)果)胎挎;">考慮到來自Axios承諾的成功響應(yīng)沟启,我們從JSON“data”中選擇“HITS”(這包含基于查詢的結(jié)果)忆家;后來,我介紹了">后來德迹,我介紹了地圖遍歷流中的每個值(包含結(jié)果的數(shù)組)芽卿,只過濾包含有效標(biāo)題和URL的有效值;">遍歷流中的每個值(包含結(jié)果的數(shù)組)胳搞,只過濾包含有效標(biāo)題和URL的有效值卸例;</trans>

為了呈現(xiàn)數(shù)組,我在模板中創(chuàng)建了一個簡單的列表肌毅,它迭代新聞數(shù)組筷转,并呈現(xiàn)一個簡單的鏈接,顯示新聞標(biāo)題并在href中實(shí)現(xiàn)URL芽腾。">為了呈現(xiàn)數(shù)組,我在模板中創(chuàng)建了一個簡單的列表页衙,它迭代新聞數(shù)組摊滔,并呈現(xiàn)一個簡單的鏈接,顯示新聞標(biāo)題并在href中實(shí)現(xiàn)URL店乐。

就這樣IMHO艰躺,它看起來非常整潔和“容易”閱讀。我知道這可能不是簡單的眨八,但是一旦熟悉了RxJS和反應(yīng)性方法腺兴,維護(hù)/測試就變得更加容易了。現(xiàn)在停下來好好想想廉侧。傳統(tǒng)的聲明式方法很容易出錯页响,而可維護(hù)性/測試將處于邊緣。">就這樣IMHO段誊,它看起來非常整潔和“容易”閱讀闰蚕。我知道這可能不是簡單的,但是一旦熟悉了RxJS和反應(yīng)性方法连舍,維護(hù)/測試就變得更加容易了。現(xiàn)在停下來好好想想索赏。傳統(tǒng)的聲明式方法很容易出錯盼玄,而可維護(hù)性/測試將處于邊緣。</trans>

您還可以添加額外的步驟潜腻,例如">現(xiàn)在埃儿,感謝RxJS,您還可以添加額外的步驟融涣,"如果出現(xiàn)錯誤和許多其他特性蝌箍。此外青灼,如果您熱衷于測試流,我建議您使用">如果出現(xiàn)錯誤和許多其他特性妓盲。此外杂拨,如果您熱衷于測試流,我建議您使用大理石測試并對所觀察到的結(jié)果進(jìn)行測試悯衬,得到一定的結(jié)果弹沽。">并對所觀察到的結(jié)果進(jìn)行測試,得到一定的結(jié)果筋粗。

interface* HandleObservableOptions {
    time?: *number*;
    scheduler?: SchedulerLike;
}

*export const* handleObservable = *function* (observable: Observable<Event>, options: HandleObservableOptions = {}): Observable<Array<HackerNewsResult>> {
    *const* { time = 300, scheduler } = options;
     *return* observable.pipe(
       debounceTime(time, scheduler),
       ...    
    );
};</pre>

[https://github.com/ReactiveX/rxjs/blob/master/doc/marble-testing.md](https://github.com/ReactiveX/rxjs/blob/master/doc/marble-testing.md)</pre>

// This test will actually run *synchronously*
it('generate the stream correctly', () => {
  scheduler.run(helpers => {
    const { cold, expectObservable, expectSubscriptions } = helpers;
    const obs =  handleObservable(cold('-a--b--c---|'), { 
      time: 300, 
      scheduler
    });
    const subs =     '^----------!';
    const expected = '-a-----c---|';

    expectObservable(obs).toBe(expected);
    expectSubscriptions(obs.subscriptions).toBe(subs);
  });

上面的片段僅僅是測試看起來的一個例子(注意:根據(jù)您的環(huán)境策橘,真正的測試可能略有不同)。多虧了大理石策略娜亿,才有可能測試你能想到的所有可能的路徑丽已。也許這是下一篇()文章的一個有效主題,因?yàn)橛泻芏嗍虑橐懻摗?>上面的片段僅僅是測試看起來的一個例子(注意:根據(jù)您的環(huán)境买决,真正的測試可能略有不同)沛婴。多虧了大理石策略,才有可能測試你能想到的所有可能的路徑督赤。也許這是下一篇()文章的一個有效主題嘁灯,因?yàn)橛泻芏嗍虑橐懻摗?lt;/trans>

<trans oldtip="Anyway, the complete solution might look like this." newtip="無論如何,完整的解決方案可能是這樣的躲舌。">無論如何丑婿,完整的解決方案可能是這樣的。</trans>

<template>
 <div>
 <label *for=*"search">Search for something:</label>
 <input *type=*"text" *id=*"search" *class=*"input-field">
 <ul *v-for=*"item in news">
 <li *:key=*"item.objectID">
 <a *:href=*"item.url">{{ item.title }}</a>
 </li>
 </ul>
 </div>
</template>

<script *lang=*"ts">
  *import* axios, { AxiosResponse } *from* 'axios';
  *import* { Component, Vue } *from* 'vue-property-decorator';
  *import* { *from*, Observable, SchedulerLike } *from* 'rxjs';
  *import* { debounceTime, map, pluck, switchMap } *from* 'rxjs/operators';

  *interface* HackerNewsResult {
 objectID: *string*;
 title?: *string*;
 url?: *string*;
 }

  *interface* HackerNewsSearchResponse {
 hits: Array<HackerNewsResult>
 }

  *interface* HandleObservableOptions {
 time?: *number*;
 scheduler?: SchedulerLike;
 }

  *const* hackerNewsEndpoint: *string* = 'http://hn.algolia.com/api/v1/search?query=';

  *export const* handleObservable = *function* (observable: Observable<Event>, options: HandleObservableOptions = {}): Observable<Array<HackerNewsResult>> {
  *const* { time = 300, scheduler } = options;
  *return* observable.pipe(
 debounceTime(time, scheduler),
 pluck<Event, *string*>('target', 'value'),
 switchMap(value => *from*(
 axios.get<HackerNewsSearchResponse>(`${hackerNewsEndpoint}${value}`)
 )
 ),
 pluck<AxiosResponse, Array<HackerNewsResult>>('data', 'hits'),
 map((results: Array<HackerNewsResult>) => results.filter((news: HackerNewsResult) => Boolean(news.title && news.url)))
 );
 };

 @Component<Search>({
 subscriptions(*this*: Vue) {
  *return* ({
 news: handleObservable(*this*.$fromDOMEvent('input', 'keyup'))
 });
 }
 })
  *export default class* Search *extends* Vue {
 news: Array<HackerNewsResult> = [];
 }

<style *scoped*>
 .input-field {
 width: 50%;
 }

這可能是一個起點(diǎn)没卸,許多東西可能會得到增強(qiáng)羹奉,但我建議您在應(yīng)用程序中考慮這個策略,并在代碼中替換瘋狂的流约计。">這可能是一個起點(diǎn)尘奏,許多東西可能會得到增強(qiáng),但我建議您在應(yīng)用程序中考慮這個策略病蛉,并在代碼中替換瘋狂的流炫加。

干杯

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市铺然,隨后出現(xiàn)的幾起案子俗孝,更是在濱河造成了極大的恐慌,老刑警劉巖魄健,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赋铝,死亡現(xiàn)場離奇詭異,居然都是意外死亡沽瘦,警方通過查閱死者的電腦和手機(jī)革骨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門农尖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人良哲,你說我怎么就攤上這事盛卡。” “怎么了筑凫?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵滑沧,是天一觀的道長。 經(jīng)常有香客問我巍实,道長滓技,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任棚潦,我火速辦了婚禮令漂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丸边。我一直安慰自己叠必,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布原环。 她就那樣靜靜地躺著挠唆,像睡著了一般处窥。 火紅的嫁衣襯著肌膚如雪嘱吗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天滔驾,我揣著相機(jī)與錄音谒麦,去河邊找鬼。 笑死哆致,一個胖子當(dāng)著我的面吹牛绕德,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播摊阀,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼耻蛇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胞此?” 一聲冷哼從身側(cè)響起臣咖,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漱牵,沒想到半個月后夺蛇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡酣胀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年刁赦,在試婚紗的時候發(fā)現(xiàn)自己被綠了娶聘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡甚脉,死狀恐怖丸升,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宦焦,我是刑警寧澤发钝,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站波闹,受9級特大地震影響酝豪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜精堕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一孵淘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧歹篓,春花似錦瘫证、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至洞斯,卻和暖如春毡庆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背烙如。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工么抗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人亚铁。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓蝇刀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親徘溢。 傳聞我的和親對象是個殘疾皇子吞琐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)然爆,斷路器站粟,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,102評論 25 707
  • 古典音樂是一個獨(dú)立的流派,藝術(shù)手法講求洗練施蜜,追求理性地表達(dá)情感卒蘸,內(nèi)涵深刻,能發(fā)人深思,更能使人高尚缸沃,免于低俗恰起。并歷...
    八度黑白閱讀 3,529評論 2 51
  • 我們吃飯的時候翘单,知道吃麻辣要找川渝吨枉,吃香辣找湖南菜,吃清涼爽口的甜品找港式......因?yàn)橐环剿琉B(yǎng)一方食哄芜,這塊地...
    樂小飲閱讀 317評論 0 3
  • (五) 像每一個開學(xué)一樣貌亭,教室里嘰嘰喳喳聲一片,仿佛自己真的很久很久沒有見到彼此一樣认臊,恨不得將自己一整個假期的...
    沈白_閱讀 163評論 0 0