用 Angular 弄了一個背單詞的網站——eliseos.org
弄了一個背單詞的網站——eliseos.org,或者叫 jingtu.io。(這倆名字其實是一個意思。當然這個網站不主要是為了背單詞而開發的,不過目前只有背單詞的還能用。)
它是 Angular 開發的,同時用了一些時新的技術,比如前端的 redux-observable, graphql, apollo client,後端的 inversify, sequelize-typescript,另外我還自己搞了一些用於自動生成 graphql schema 的 decorator——
@Tablenexport class Language extends NoPrimaryOrdinaryModel<Language> {nn @Default(DataType.UUIDV1)n @Columnn @GraphQLFieldToTypen id: string;nn @PrimaryKeyn @Columnn @GraphQLFieldToTypen name: string;nn @GraphQLFieldJsonLike(() => Kv)n @Column(DataType.JSONB)n namesInLang: KvInterface;nn @HasMany(() => LanguageOfLanguage, languageName)n languageOfLanguages: LanguageOfLanguage[];n}n
是不是有點像 Java 了?這麼寫就會生成一個叫 Language 的表,有這麼些 column 和 association,這部分是 sequelize-typescript 的功能,還會生成一個叫 Language 的 graphql schema,這部分是我自己寫的。難也不難,主要是提供一種思路。
另外寫的過程中我也理解了為什麼 sequelize-typescript 的 decorator 參數里,類型是 lazy 的(即以上代碼里的 () => LanguageOfLanguage。這是因為如果不 lazy,出現類的循環引用的時候,有一方會變成 undefined。我碰到了這個問題,所以我自己也用了 thunk 形式作為參數。
然後對於 query 也有這麼些個 decorator,比如——
@GraphQLQueryField(userGraphqlType, {n token: {n type: new GraphQLNonNull(GraphQLString)n }n}, Checks if a token is valid. Returns the validated user.)nasync checkToken(parentValue: any, {token}: {n token: stringn}, context: ContextInterface) {n return await context.services.userService.checkToken(token);n}n
其實也沒什麼學問,主要是我看著原來 graphql-js 的 object literal 結構太不穩當了,嵌套一深,隨便哪裡類型寫錯了,TypeScript 就拋一大堆錯(其實挺穩當的,只要你把 object literal 拆分開來,每一級都標註類型,報錯就不會大規模傳播)。
用上了 decorator,順帶用了 inversify——一個依賴注入管理器,以及 TypeScript 的一套東西,誰說 Node.js 不可以工程化開發呢?
至於前端,也是從 TypeScript 中獲益良多。Angular 原生就是依賴 TS 的,也是原生就依賴 decorator 的,也是原生就依賴注入的。這麼看 JS 生態系統前後端的技術選型已經趨同了,我相信這是好的趨勢。
還有什麼要說的話,就是我把以前答過的Axurez:如何評價 TypeScript 最新加入的 Discriminated union type?這個定義 tagged union 的簡便語法,真的給用到了實戰里——不僅僅是定義 redux actions,而且我寫了一個可以深度 get 和 set 的 Map,因為要用遞歸指涉自身,還必須用到 tagged union。這個類型如下:
export type RecMap<K, V> = Map<K, { type: V, value: V } | { type: M, map: RecMap<K, V> }>;n
整個弄下來的感想就是,Angular 是真的好用,Angular 生態是真的不錯,universal 完全按官方走一遍就活了,現在線上運行的版本就是 universal 的,右鍵查看源碼可以看到是渲染好的頁面發過來的。angular cli 一路可以 generate 到底,基於 NgModule 的路由懶載入也是開箱即用,不需要任何配置,非常美妙。
還有一點就是,還是純 css 庫比較穩妥,帶 JS 的反而不行,我用了 material design components 和 material design lite(因為前者沒實現 chip……),還是把 js 拆了用的。一方面是它帶的 JS 不一定合你的意,另一方面是它哪怕是用了你用的框架,它的 API 設計也不一定合你意(這也是我不用 Angular Material 的原因)。另外用了 Angular 這樣的框架,它封裝的那點功能你自己封裝也要不了多久。
如果說還有一點感想,那就是我好像有點達成以前的目標了。以前總是感覺 sequelize 要寫一套定義,要寫一套介面,graphql 還要寫一套定義,來來回回同樣的東西要寫好多遍。現在藉助 decorator 真的實現了只寫一遍。現在還有 sequelize-auto-migrations 這樣的東西,可以自動根據模型的更改生成 migration,簡直不要太省勞動力。
說了這麼多關於開發的功能,那麼這個網站怎麼用呢?(推薦桌面使用,雖然移動端也完全可用)
關於背單詞功能,如下圖,點擊右側的「巴別」(巴別,用 wikipedia 的人應該見過,典出巴別塔,我用來指代和語言相關的模塊)中的「學習」,就來到了學習界面(同時在線統計是用 socket.io 實現的,不過用戶數量目前並不對,頁面是對的。這裡有個彩蛋,沒網的時候 logo 就會黑掉):
你可以在右側的「語料」里粘貼進英文文章,然後點擊「使用這篇文章」:
它會把文章跟伺服器同步,解析出你認識的、不認識的、沒決定過的辭彙,分別標上白色、紅色和綠色:
正如提示所說的
在左邊粘貼文章,並點擊按鈕,來提取文章中的單詞。
綠色表示狀態未知的單詞,划過標記為認識,單擊標記為不認識,再單擊標記為認識,以此類推。你可以在概覽中回顧不認識的單詞。
照著做就行了。我還弄了一個功能就是添加和查看單詞釋義。把滑鼠懸停在不認識的(即紅的)單詞上,會出現懸浮框:
點擊加號就會出現文本框,可以添加釋義,以及選擇釋義的語言(這個網站處於我個人的惡趣味,是支持了四種語言的,用右上角的語言選單可以極速切換語言)。添加完之後,或者本來就已經有人添加過,就會是這個樣子:
本來應當是可以代理一個其他網站的 API,或者乾脆伺服器上搞一個詞庫的,實際上應該是可行的,但我還是想先試試 UGC 一段時間(估計效果不好)。添加釋義的另一個好處就是可以在個人主頁上顯示……比如我的主頁:
個人主頁怎麼進?登陸之後右上角的用戶名可以直接點擊:
或者滑鼠懸停,在下拉菜單里選「個人檔」也行。
如果你誤操作了,一方面你可以再次點擊單詞,在白色和紅色之間切換,另一方面也可以在右下角看到所有紅色、白色辭彙的列表,點擊就可以復歸「未確認」狀態,即綠色。
確認單詞為未知之後,不僅單詞會被同步到伺服器,單詞所在的句子也會被同步到伺服器,在右側的「巴別—概覽」中可以回看:
未知單詞在句子中的未知也會標紅。(這裡本來是給單詞加上 html 標籤,然後渲染 html 的,但是會有注入的危險,所以最後強行把句子 split 成一個結構體,用 ngFor + ngIf 渲染了)
以上大概就是目前能用的內容。設置的個人檔也可以更新
還可以生成邀請鏈接,推廣註冊。
如果遇到什麼 bug,請一定聯繫我。
至於為什麼要做這個網站?這個網站除了背單詞之外,還是幹什麼的?就如關於頁面所說:
Eliseos 就是「極樂凈土」的西班牙語形式。我用西班牙語是因為其他語種類似的域名都註冊了(elysium, elysian, elysion 之類的)。其實我原來有個 elysion.tech,但是 .tech
太冷門了,很多地方識別不出來。這網站還有個域名,叫「凈土」—— jingtu.io。
根據維基百科:
至福樂土(Elysium)或是樂土平原(Elysian Fields)(古希臘語:?λ?σιον πεδ?ον,ēlysion pedíon,音譯:伊利西恩、伊利西昂。中文翻譯上亦可名為歸靜樂土或是歸凈樂土,意為回歸安靜或回歸純凈的樂土。)是一個來世觀的理念,隨著時間的推移並由一些希臘的宗教教派的儀式與哲學流派所延續發展。
我最早是在《聖鬥士星矢》里接觸到這概念的。在這裡,我想用它指代這個網站,是因為我想做一個能進行深刻思想交流(包括語言、知識)的地方。
推薦閱讀:
※如果有一個導購工具網站,取名為59同城,你們覺得這名字怎麼樣?
※寫在「 看知乎 」下線的第二天 還有誰能帶我們優雅的看知乎?
※soopat、佰騰網等專利檢索網站的專利數據信息是從哪裡獲得的?
※辦一個網站教爸媽玩手機,怎麼樣?
※哪個訂機票的網站可信度高?綜合服務較好呢?
TAG:Angular? | TypeScript | 网站 |