讓Mavo在構建交互式Web應用程序中發光
本教程將深入探討Mavo:一種便捷易用的方法,只需編寫HTML和CSS,無需一行JavaScript代碼或服務器後端,即可創建複雜、響應式、持久化的Web應用程序。
Mavo由麻省理工學院CSAIL的Haystack小組開發,由Lea Verou領導。
我們將共同構建一個外語學習用的抽認卡應用程序。這是一個功能齊全的CRUD應用程序,允許您:
- 創建、刪除、更新抽認卡,並通過拖放重新排列。
- 導入和導出抽認卡。
- 評估您對抽認卡上單詞的掌握程度。
以下是我們完成的應用程序的外觀:
在本教程中,我將引導您完成構建應用程序的整個過程。
在某些步驟的結尾,我將提供一些建議,讓您嘗試使用Mavo——學習更多知識——並對我們正在構建的應用程序進行一些增強。
準備好了嗎?讓我們開始吧! ?
靜態模板
為了說明Mavo如何增強標準HTML,我們將首先創建一個純靜態HTML頁面,然後使用Mavo將這個靜態HTML轉換為一個功能齊全的Web應用程序。
假設我們在以下HTML代碼中:
<h1 id="抽認卡">抽認卡</h1> <main><p>單詞或短語</p> <p>翻譯</p> </main>
在該代碼中,<main></main>
元素表示單個抽認卡。
讓我們添加一些樣式,使我們的HTML看起來更像一個實際的抽認卡應用程序。您可以查看源代碼並在此處使用它。
開始使用Mavo
現在,我們只有靜態模板。是時候添加功能了,這樣它才能真正像抽認卡應用程序一樣工作。 Mavo閃亮登場!
為了使用Mavo,我們首先需要在頁面的部分包含其JavaScript和CSS文件:
... <link href="https://get.mavo.io/mavo.css" rel="stylesheet"> ...
您可能需要支持舊版瀏覽器,或者希望能夠閱讀代碼?您可以通過回答幾個問題來自定義您正在使用的Mavo版本和構建版本。
定義Mavo應用程序
要在HTML結構上啟用Mavo功能,我們必須在包含Mavo應用程序的元素上使用mv-app
屬性(甚至可以是或
元素,都可以! )。其值為應用程序的ID,在頁面中應唯一。如果我們不帶值使用<code>mv-app
,並且同一元素上沒有id
或name
屬性,則會自動生成諸如mavo1
、 mavo2
等名稱。
但是,強烈建議您命名Mavo應用程序,因為該名稱在許多地方都會使用。
考慮到<main></main>
元素代表我們的Mavo應用程序,讓我們向其添加mv-app
屬性,並為我們的應用程序指定ID“flashcards”:
<main mv-app="flashcards"> ... </main>
屬性屬性
是時候告訴Mavo哪些應用程序元素是重要的,即我們希望哪些元素可編輯並保存。
現在我們有兩個這樣的元素,它們是<p>元素。讓我們向這些元素添加<code>property
屬性,以告訴Mavo它們包含數據。具有property
屬性的元素稱為屬性。
我們可以將property
屬性放在任何HTML5元素上,Mavo知道如何使其可編輯。例如,對於<input>
,您可以編輯其內容,但<time></time>
允許您通過適當的日期/時間選擇器編輯其日期/時間。
您還可以通過插件擴展這組規則,並以新的方式(例如,富文本)使元素可編輯。
請記住, property
屬性的值應類似於id
或class
屬性那樣描述元素:
... <p property="source">單詞或短語</p> <p property="translation">翻譯</p> ...
如果您已經有充分描述元素的class
、 id
或itemprop
屬性,則可以使用不帶值的property
,例如property="source"
。
您注意到我們的應用程序中有什麼變化嗎?頁面頂部出現了一個帶有編輯按鈕的Mavo工具欄。編輯按鈕允許用戶在閱讀和編輯模式之間切換。現在我們的應用程序處於閱讀模式。這意味著我們無法編輯頁面上的數據。
Mavo工具欄是完全可定制的,幾乎所有由Mavo生成的UI都是如此:您可以更改其位置、刪除其默認樣式、添加自定義按鈕元素或使用您自己的HTML元素,等等。
我們稍後在本教程中將看到一個這樣的自定義示例。
訪問Mavo網站的此部分以了解更多信息。
現在讓我們通過單擊編輯按鈕切換到編輯模式。發生了什麼變化?編輯按鈕的文本變為正在編輯,以指示我們處於編輯模式。如果您將鼠標懸停在段落上,Mavo會通過將它們突出顯示為黃色來告知您可以單擊以編輯它們。開始吧!單擊文本並編輯它。哇!我們可以直接在頁面上更改內容!
假設除了單詞及其翻譯之外,抽認卡還應包含一個單詞在句子中用法的示例。通過向抽認卡添加相應的元素來增強應用程序。
mv-multiple
屬性
目前,我們的應用程序中只有一個抽認卡。這沒什麼用!對於一個有效的抽認卡應用程序,我們需要能夠添加、刪除和重新排列抽認卡。我們該如何做到這一點?我們可以通過向代碼中添加更多<main></main>
元素來創建更多抽認卡,但是最終用戶如何創建和刪除抽認卡呢?
幸運的是,Mavo提供了一些使這變得輕而易舉的東西: mv-multiple
屬性,它告訴Mavo某些元素可以被複製。它將其使用的元素轉換為可編輯的項目集合,並生成(可定制的)UI用於添加、刪除和重新排列項目。
如果在沒有property
屬性的元素上使用mv-multiple
,Mavo會自動向其添加property="collection"
(或collection2
、 collection3
等,以便名稱唯一)。但是,建議您也使用property
屬性,為您的集合命名,並確保在HTML更改時保留其數據。
讓我們在我們的應用程序中使用mv-multiple
屬性,將我們孤單的抽認卡轉換為抽認卡集合:
... <main mv-app="flashcards" mv-multiple> <p property="source">單詞或短語</p> <p property="translation">翻譯</p> </main>
也可以將屬性名稱指定為mv-multiple
的值,例如mv-multiple="flashcards"
。
mv-multiple
屬性位於將被複製的元素上,而不是集合的容器上。人們常常犯的一個錯誤是使用<main mv-multiple></main>
而不是<main></main>
,並且在檢查元素或樣式使其明顯之前,通常會長時間不被發現。現在切換應用程序到編輯模式。請注意,在抽認卡下方,現在有一個添加抽認卡按鈕。讓我們試一試:使用該按鈕創建一些抽認卡。現在我們可以直接在應用程序中動態添加新元素,即使HTML中沒有相應的元素。但這還不是全部!
請注意,<main></main>
上的property
屬性實際上並沒有使整個<main></main>
元素可編輯,而是充當分組元素。當您在包含其他屬性的元素上使用property
屬性時,就會發生這種情況。嘗試將鼠標懸停在抽認卡上,並註意出現在其右上角的三個按鈕,用於通過拖放句柄添加、刪除和重新排列元素。通過將鼠標懸停在任何項目欄按鈕上,我們可以理解它們對應哪個抽認卡:Mavo會突出顯示它。是不是很神奇?
您可以自定義Mavo生成的任何UI元素,例如,您可以通過使用mv-drag-handle
類創建您自己的拖動句柄。
Mavo添加到集合中每個項目的按鈕也可以通過鍵盤訪問。甚至重新排序:您可以將焦點放在拖動句柄上,並使用箭頭鍵移動項目。
mv-storage
屬性
現在我們已經有了基本的UI,讓我們嘗試以下操作:
- 切換到編輯模式(如果您尚未這樣做)。
- 編輯第一個抽認卡的源單詞和翻譯。再添加幾個抽認卡。
- 將應用程序切換回閱讀模式。
- 最後……刷新頁面。
什麼? !我們的數據去哪兒了? Mavo不是應該保存它嗎?發生了什麼?
實際上,我們從未告訴Mavo是否或在哪裡存儲我們的數據!
為此,我們需要使用mv-storage
屬性。我們有什麼選擇?好吧,Mavo為我們打開了巨大的可能性,而Mavo插件則打開了更多可能性!
在我們的應用程序中,我們將數據存儲在瀏覽器的localStorage中,這是最簡單的選項之一,因此它非常適合我們的第一個Mavo應用程序。我們只需要在具有mv-app
屬性的元素(也稱為Mavo根)上添加值為local
的mv-storage
屬性。
<main mv-app="flashcards" mv-storage="local"> ... </main>
看看Mavo工具欄。注意到什麼了嗎?出現另一個按鈕——保存按鈕。
嘗試再次編輯應用程序數據。請注意,保存按鈕現在已突出顯示。將鼠標懸停在保存按鈕上,Mavo將突出顯示具有未保存數據的屬性。是不是很酷?
單擊保存按鈕並刷新頁面(無需在刷新頁面之前切換到閱讀模式)。您的數據還在嗎?太好了!我們離我們的目標又近了一步——一個功能齊全的抽認卡應用程序。
mv-autosave
屬性
現在我們每次需要保存數據時都必須單擊保存按鈕嗎?這可能更安全,可以防止破壞寶貴的數據,但這通常會很不方便。我們可以自動保存數據嗎?當然!為了在每次更改數據時自動保存數據,我們可以在Mavo根元素上使用mv-autosave
屬性。其值為節流保存的秒數。讓我們向應用程序的根元素添加mv-autosave="3"
:
<main mv-app="flashcard" mv-autosave="3" mv-storage="local"> ... </main>
如果mv-autosave="3"
,Mavo最多每三秒鐘只能保存一次。這對於保留更改歷史記錄的後端(例如, GitHub 、 Dropbox )尤其有用,以防止洪氾,這會使該歷史記錄毫無用處。
要禁用節流並立即保存,我們可以使用mv-autosave="0"
或僅使用mv-autosave
,這也會從UI中刪除保存按鈕(因為在這種情況下它沒有用處)。
再次更改數據並查看保存按鈕。看到了嗎?一開始,它被突出顯示,但在3秒鐘後——它沒有被突出顯示。我們所有的數據現在都自動保存了!
因此,現在我們的應用程序的主要部分看起來像這樣:
<main mv-app="flashcards" mv-autosave="3" mv-storage="local"><p property="source">單詞或短語</p> <p property="translation">翻譯</p> </main>
我們幾乎完成了應用程序的alpha版本。現在輪到您使應用程序變得更好。別擔心,您擁有所需的所有知識。
增強應用程序,以便抽認卡可以由最終用戶組織到與各種主題相關的不同組中,例如,用戶可以將所有與服裝相關的抽認卡收集到一個組中,將所有與廚房用具相關的抽認卡收集到另一個組中,等等。
?提示!
有很多方法可以實現這個目標,這取決於您決定遵循什麼。但是,我希望您在繼續之前考慮一些問題:
- 您將使用什麼HTML元素作為分組元素?如果用戶可以看到抽認卡組的名稱(主題名稱)並可以將組折疊到標題,那將很方便。
- 您將向該元素添加哪些Mavo屬性(如果有的話)?該元素將是屬性還是集合?
- 最終用戶能否添加新主題、刪除和重新排列它們、更改主題標題以及在不同主題之間移動抽認卡?
如果您決定不按組組織抽認卡,而是只用對應於各種主題的標籤標記它們,那也沒問題。使用標籤的解決方案也是合適的。為了練習,也嘗試完成這種方法。
mv-bar
屬性
由於我們的應用程序在本地存儲數據,因此默認情況下,應用程序的用戶將無法與其他用戶共享他們的卡片。如果我們允許他們導出他們的抽認卡和導入其他人的抽認卡,那不是很好嗎?謝天謝地,這些功能已經在Mavo中實現,我們可以很容易地將它們添加到我們的應用程序中!
mv-bar
屬性控制將顯示哪些按鈕(如果有的話)在工具欄中。它通常在Mavo根(具有mv-app
屬性的元素)上指定。按鈕由它們的id(非常邏輯)表示:edit、import、export等。
由於我們只想向默認集合添加幾個按鈕,因此我們可以使用所謂的相對語法,它允許我們向默認集合添加和刪除按鈕,而無需顯式列出所有內容。我們只需要以with
關鍵字開頭mv-bar
屬性的值即可。
通過這樣做,我們將得到以下內容:
<main mv-app="flashcards" mv-autosave="3" mv-bar="with import export" mv-storage="local"> ... </main>
嘗試這些功能:添加一些抽認卡,嘗試將它們導出到文件中。然後刪除現有抽認卡並從先前導出的文件中導入抽認卡。
表達式和MavoScript
現在讓我們向我們的應用程序添加一些統計信息,例如抽認卡的數量!聽起來很有趣嗎?我希望如此。 ?
為此,我們需要學習一些關於Mavo的新知識。
我們可以動態地引用我們在任何地方定義的任何屬性的值在我們的Mavo應用程序中(包括在HTML屬性中),方法是將它的名稱放在方括號中,像這樣: [propertyName]
。這是一個簡單的表達式的示例,它允許我們動態計算事物,並在它們發生變化時做出反應。
Mavo的表達式語法稱為MavoScript 。它類似於電子表格公式,允許我們執行計算和其他操作(使用數字、文本、列表等),但旨在更易於閱讀並適應嵌套關係。您可以在文檔中了解有關Mavo表達式和MavoScript的更多信息。
現在讓我們嘗試一下,在抽認卡屬性內部添加[source]
表達式,例如,在兩個屬性之間:源和翻譯。
... <p property="source">單詞或短語</p> [source] <p property="translation">翻譯</p> ...
我們的應用程序發生了什麼變化?抽認卡源屬性的值現在在頁面上顯示了兩次。
切換到編輯模式並嘗試更改源屬性的值。您看到了嗎?在您更改屬性值時,頁面內容會更新!這就是我之前說Mavo允許我們開發響應式Web應用程序的原因。
這確實很酷,但不幸的是,在我們的例子中,它並沒有什麼用處:我們無法使用此表達式來計算抽認卡的數量——我們總是只有一個值。
如果我們將[source]
表達式放在抽認卡屬性外部會怎樣?我們將得到如下內容:
... [source] ... ...
這與之前的案例有何不同?要查看差異,如果您尚未這樣做,請添加一些抽認卡。現在,我們不是一個值,而是一個逗號分隔的值列表:所有抽認卡的源屬性。這正是我們一直在尋找的:列表中項目的數量對應於應用程序中抽認卡的數量。
說得通嗎?是的,但是如果我們計算抽認卡的數量,而不是其源屬性的值的數量,豈不是更合乎邏輯?畢竟,即使在我們填寫其源或翻譯之前,添加的抽認卡也存在。我建議您執行以下操作:讓我們用[flashcard]
替換[source]
表達式:
... [flashcard] ... ...
注意到區別了嗎?我們仍然有一個列表,但其值不是簡單值,而是對象,即包含與每個抽認卡相關的所有數據的複雜值。好消息是這些對象的數目等於抽認卡的數目,因為每個抽認卡都有一個,即使它完全為空。所以,現在我們每個抽認卡都有一個對象,但是我們如何計算它們並顯示總數呢?
現在讓我們熟悉MavoScript函數,並找到可以讓我們計算抽認卡數量的函數。記住,我們有一個抽認卡列表,所以我們需要找到一個可以讓我們計算列表中項目數量的函數。它來了—— count()
函數就是這樣做的!
但是我們如何在表達式中使用函數呢?我們需要注意哪些規則?是的,有幾個:
- 表達式用方括號表示。
- 不要嵌套括號。
讓我們嘗試使用count()
函數來計算抽認卡的數量:
... [count(flashcard)] ... ...
這正是我們所追求的——現在我們的應用程序中有一些統計數據了!是不是很酷?
我希望您已經熱身並準備好繼續嘗試Mavo了。
改進應用程序,以便不僅顯示應用程序中抽認卡的總數的統計信息,而且還顯示每個主題中抽認卡的數量的統計信息(如果有的話)。
?提示!
想要根據某些條件過濾列表嗎? where
運算符將有所幫助。
自我評估功能
我們已經有一個應用程序,可以讓我們創建、編輯和存儲多個抽認卡。但是我們如何跟踪我們已經學習了哪些抽認卡,以及哪些抽認卡需要更多練習呢?任何值得尊敬的抽認卡應用程序都需要自我評估功能。讓我們研究一下我們如何添加它!
假設在我們的應用程序中,我們有兩個用於自我評估的按鈕:差和好。我們希望每次最終用戶單擊按鈕時會發生什麼?好吧,這個想法很簡單:
- 單擊“差”按鈕將表示用戶尚未學習該單詞,我們希望我們的應用程序將相應的抽認卡移動到列表的開頭,以便他們可以在啟動應用程序後儘快看到它。
- 單擊“好”按鈕將表示用戶已經學習了該單詞,相應的抽認卡需要移動到列表的末尾,讓他們使用他們尚未學習的其他抽認卡。
“您確定我們可以在沒有JavaScript的情況下做到這一點嗎?”你可能會問。是的! Mavo非常強大,能夠為我們提供所需的所有工具!
現在我們知道了我們將要實現的內容,讓我們首先設置UI,然後繼續下一步。我們的標記看起來像這樣:
... ... <h2 id="評估自己">評估自己</h2> <button>差</button> <button>好</button> ...
mv-action
屬性
Mavo操作允許我們創建我們自己的控件,這些控件以自定義方式修改數據,當用戶與它們交互時。聽起來很有希望,對吧?
要定義自定義操作,我們需要在Mavo應用程序內的相應元素上使用mv-action
屬性。每次單擊該元素時都會執行該操作。這正是我們一直在尋找的。
對於<form>元素,當表單<em>提交</em>時會執行自定義操作。 <code>mv-action
屬性的值是一個表達式。我們可以使用MavoScript為我們提供的任何表達式函數和語法,以及一些其他函數來促進數據操作,例如add()
、 set()
、 move()
或delete()
。重要的是要注意,與以反應方式計算的普通表達式不同,這些表達式僅在每次觸發操作時才計算。
Mavo期望mv-action
屬性的值是一個表達式,因此無需將其括在括號中: mv-action="expression"
。此外,如果我們包含它們,它們將被視為表達式的部分。
因此,我們需要移動集合內的抽認卡,而Mavo有一個合適的函數可以讓我們做到這一點—— move()
函數。它的第一個參數指的是我們正在移動的項目,第二個參數是它在集合中的位置。請記住,集合的元素從0開始編號。
想要了解有關move
函數(及其變體)以及自定義操作的更多信息,請參閱文檔。
讓我們實現我們前面討論的大綱的第一點:在自我評估時,最終用戶單擊“差”按鈕,相應的抽認卡將移動到集合的開頭,即成為第一個。所以在代碼中,我們有:
... ... <button mv-action="move(this, 0)">差</button> ... ...
請注意,在mv-action
屬性中,我們在屬性內部引用抽認卡屬性,因為我們希望處理當前抽認卡。
如果我們嘗試實現大綱的第二點,我們將面臨一個問題。您能否建議這究竟是什麼問題?
讓我們記住,如果最終用戶單擊“好”按鈕,相應的抽認卡將移動到集合的末尾,即成為最後一個。為了使抽認卡成為集合中的最後一個,我們需要知道集合中項目的數量。
謝天謝地,我們之前已經解決了這項任務並實現了相應的功能。但是我們能否使用該解決方案來解決我們當前的問題呢?不幸的是,我們不能:正如我們已經知道的,我們只能在抽認卡屬性外部引用抽認卡的集合(並評估其大小)。但在我們的例子中,我們需要在其中進行:我們需要為其編寫表達式的“好”按鈕在抽認卡屬性內部。
那我們該怎麼辦呢?我很高興你問。 Mavo有解決方案。
使用元元素保存中間值
因此,一方面,我們知道[count(flashcards)]
表達式會在外部評估抽認卡屬性時為我們提供抽認卡的數量。另一方面,我們需要在其中使用該值抽認卡屬性。
為了解決這個難題,我們需要在我們的代碼中評估抽認卡的數量,並以某種方式保存結果,以便能夠在應用程序的其他地方使用它,準確地說是在抽認卡屬性內部。對於這種情況,在Mavo中,有所謂的計算屬性。
為了保存中間結果以便我們可以引用它,我們需要代碼中的HTML元素。建議為此使用<meta>
元素,如下所示:<meta content="[expression]" property="propertyName">
。使用此元素的優點是它在編輯模式外部是隱藏的,在語義上和視覺上都是如此。
請記住,默認情況下不會保存計算屬性。
現在讓我們在我們的應用程序中添加flashcardCount
計算屬性。記住,我們必須將其放在抽認卡屬性外部,但是然後我們可以從任何地方引用它:
... <meta content="[count(flashcard)]" property="flashcardCount"> ... ...
只剩下一個步驟來完成自我評估功能的實現:如果最終用戶單擊“好”按鈕,相應的抽認卡將移動到集合的末尾,即成為最後一個。讓我們在應用程序的代碼中添加相關的操作:
... <meta content="[count(flashcard)]" property="flashcardCount"> ... <button mv-action="move(this, flashcardCount)">好</button> ...
我們完成了!恭喜! ?
還有另一種解決該任務的方法:借助$all
特殊屬性。如果$all
屬性位於集合內部,則它代表集合本身。因此,在這種情況下無需使用任何計算屬性。嘗試自己實現該解決方案。
只剩下最後一件事我們需要修復。還記得我們向應用程序添加了一些統計數據的部分嗎?還記得我們構建的用於評估應用程序中抽認卡數量的表達式嗎: [count(flashcard)]
?相反,我們現在可以使用(也應該使用)我們定義的計算屬性。在應用程序中進行相應的更改。
結論
那麼到目前為止我們學習了什麼呢?讓我們回顧一下。為了將任何靜態HTML頁面轉換為Mavo應用程序,我們需要:
- 在頁面的
部分包含Mavo JavaScript和CSS文件。
- 向Mavo根元素添加
mv-app
屬性。 - 通過向它們添加
property
屬性來告訴Mavo我們的應用程序的哪些元素是重要的。 - 將
mv-multiple
屬性放在將被複製並轉換為集合的元素上。 - 通過向Mavo根添加
mv-storage
屬性來告訴Mavo在哪裡存儲我們的數據。 - 決定Mavo是否應該自動保存我們的數據。如果是,則向Mavo根添加
mv-autosave
屬性。我們還知道: - Mavo工具欄是完全可定制的。
mv-bar
屬性控制將顯示哪些按鈕。 - 表達式允許我們在其他元素中顯示屬性的當前值並執行計算。表達式的值(和類型)取決於表達式在代碼中所處的位置。 Mavo的表達式語法稱為MavoScript。
- 自定義操作允許創建以自定義方式修改數據的控件。要在Mavo應用程序內的相應元素上定義自定義操作,請設置
mv-action
屬性。 - 值為表達式的屬性稱為計算屬性。為了保存中間結果以便能夠在應用程序的其他地方引用它,建議使用
<meta>
元素。
後記
所以我們構建了我們的應用程序。它已經完美了嗎?當然不是,沒有什麼東西是完美的!有很多東西可以改進,還有很多功能可以添加(在Mavo的幫助下,我們甚至可以使我們的應用程序多語言化!)。繼續,進一步增強它,不要猶豫嘗試新的東西!
到目前為止,我們對Mavo的了解只是冰山一角,還有很多東西。我鼓勵您仔細閱讀文檔,檢查示例(在Mavo網站上,或在CodePen上:由Lea Verou製作和一些由我自己製作),並創建新內容!祝你好運! ?
致謝
我要感謝兩位偉大的人。首先,我要衷心感謝Lea Verou,她不僅激勵我撰寫本教程(並幫助我實現它),而且還一直激勵我,她使Web開發世界變得更美好。我從未見過如此有天賦的人,我很高興有機會和她一起做一些事情!
我還感謝James Moore。他在Udemy上的“JavaScript初學者函數式編程”課程中使用的示例促使我製作我自己的抽認卡學習應用程序版本。他是一位很棒的老師!
以上是讓Mavo在構建交互式Web應用程序中發光的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在本週的平台新聞綜述中,Chrome引入了一個用於加載的新屬性,Web開發人員的可訪問性規範以及BBC Move

有很多分析平台可幫助您跟踪網站上的訪問者和使用數據。也許最著名的是Google Analytics(廣泛使用)
