abbr 全稱是 abbreviations,意思是縮寫。應(yīng)用場景也很簡單,為一些文章中的縮寫增加注釋。
以前在文章中對于縮寫的解釋經(jīng)常會這么做:
DAU(Daily Active User),日活躍用戶數(shù) ......
那我們用 abbr 標(biāo)簽?zāi)兀?/span>
<abbr title="Daily Active User">
DAU
</abbr>
<span>,日活躍用戶數(shù) ......</span>
展示的效果如下:
這個標(biāo)簽就可以把全稱隱藏掉,弱化信息量,讓真正不知道該縮寫的用戶主動去獲取縮寫的具體意思,這個在 markdown 里經(jīng)常會出現(xiàn)。
<mark/> 在 markdown 中也是很常用的,用于將包裹的文本高亮展示。
<mark>高亮文本</mark>
效果如下:
如果全文統(tǒng)一高亮樣式,可以專門對 mark 標(biāo)簽進(jìn)行樣式重置,這樣就不用對你用的每個 div 加一個 highlight 的類名了,又不語義化,又徒增文檔大小。
<sup/>和<sub/>分別表示上標(biāo)和下標(biāo),在 markdown 中出現(xiàn)得也很頻繁,比如數(shù)學(xué)公式和引用。
<div>3<sup>[2]</sup></div>
<div>4<sub>2</sub></div>
效果如下:
上標(biāo)和下標(biāo)的樣式原理也比較簡單,主要就是利用了 vertical-align 的 top 和 sub 屬性值,然后將字號縮小,不過有現(xiàn)成的標(biāo)簽,干嘛不用呢?
figure 是用于包裹其它標(biāo)簽的內(nèi)容的,然后再利用另一個標(biāo)簽 figcaption ,可以對包裹的內(nèi)容進(jìn)行一個文本描述,例如:
<figure>
<img src="/media/cc0-images/elephant-660-480.jpg"
alt="大象">
<figcaption>這是一張大象的照片</figcaption>
</figure>
效果如下:
那要是圖片掛了呢?
再友好點處理,我們把 img 標(biāo)簽的 alt 屬性去掉。
漂亮,終于把我一直厭煩的圖裂 icon 給干掉了,樣式還巨好看。
當(dāng)然不止能包裹 img 標(biāo)簽,其它任何都是可以的。
嘿嘿,給大家在本文來個實戰(zhàn),下面這個可以點擊,樣式也是利用了 figure 這個標(biāo)簽。
我是figure標(biāo)簽產(chǎn)生的
說到 <progress/> 這個標(biāo)簽就很有意思了,去年有段時間我做的業(yè)務(wù)里涉及到了進(jìn)度條,當(dāng)時是前同事做的,然后有一些性能問題,我就在研究如何優(yōu)化,減少進(jìn)度條改變帶來的性能問題。
雖然最后問題是解決了,但是也有幸收到了張鑫旭大佬的評論,他告訴我 progress 這個標(biāo)簽就足夠了,既有語義化,又有進(jìn)度條的功能,性能還好,兼容性也很不錯。后來經(jīng)過一番嘗試,還真是,當(dāng)時是我孤陋寡聞了,也安利給大家。
<!-- 進(jìn)度條最大值為100,當(dāng)前進(jìn)度為60,即60% -->
<progress max="100" value="60"/>
瀏覽器自帶的樣式就已經(jīng)很好看了,效果如下:
業(yè)務(wù)中我們也就可以通過控制 value 屬性,來改變進(jìn)度條的進(jìn)度了。
area 這個標(biāo)簽也非常有意思,它的作用是為圖片提供點擊熱區(qū),可以自己規(guī)定一張圖的哪些區(qū)域可點擊,且點擊后跳轉(zhuǎn)的鏈接,也可以設(shè)置成點擊下載文件,我們來舉個例子:
<img src="example.png" width="100" height="100" alt="" usemap="#map">
<map name="map">
<area shape="rect" coords="0,0,100,50" alt="baidu" href="https://www.baidu.com">
<area shape="rect" coords="0,50,100,100" alt="sougou" href="https://www.sogou.com/">
</map>
area 一般要搭配 map 標(biāo)簽一起使用,每個 area 標(biāo)簽表示一個熱區(qū),例如上面代碼中,我們定義了兩個熱區(qū),熱區(qū)形狀都為rect(矩形),他們的熱區(qū)分別是:
我們都知道,默認(rèn)的坐標(biāo)軸是這樣的:
因此,我們劃分的兩個熱區(qū)就是:
最后再來看一下我們的實際效果:
i
details 字面意思是 "詳情",在 markdown 里也經(jīng)常用,用該標(biāo)簽包裹了的內(nèi)容默認(rèn)會被隱藏,只留下一個簡述的文字,我們點擊以后才會展示詳細(xì)的內(nèi)容。
<details>
<p>我是一段被隱藏的內(nèi)容</p>
</details>
效果如下:
這還沒有加任何一行的 js 代碼,我們點擊后,details 標(biāo)簽上會多一個 open 的屬性,被隱藏的內(nèi)容就展示出來了。
默認(rèn)情況下,簡要文字為 "詳情",想要修改這個文字,要搭配 summary 標(biāo)簽來使用。
<details>
<summary>點擊查看更多</summary>
<p>我是一段被隱藏的內(nèi)容</p>
</details>
就搞定了!
瀏覽器自帶彈窗方法 alert、confirm、prompt,樣式固定且每個瀏覽器不同,同時還會阻塞頁面運行,除了這個還提供了一個 dialog 標(biāo)簽,它的使用方式有點類似于現(xiàn)在各大組件庫的 Modal 組件了,瀏覽器還為該標(biāo)簽提供了原生的 dom 方法:showModal、close,可以直接控制彈窗的展示和隱藏。
<dialog id="dialog">
<input type="text">
<button id="close">ok</button>
</dialog>
<button id="openBtn">打開彈框</button>
<script>
const dialog = document.getElementById('dialog')
const openBtn = document.getElementById('openBtn')
const closeBtn = document.getElementById('close')
openBtn.addEventListener('click', () => {
// 打開彈框
dialog.showModal()
})
closeBtn.addEventListener('click', () => {
// 隱藏彈框
dialog.close()
})
</script>
效果如下:
細(xì)心的你有沒有發(fā)現(xiàn),這原生的彈框還自帶背景蒙層,點擊是關(guān)閉不掉的,但起碼它不會阻塞頁面。
然后我們在彈窗展示時,也可以通過 esc 鍵來關(guān)閉彈窗。
datalist 是用于給輸入框提供可選值的一個列表標(biāo)簽,類似咱們常用的 Select 組件。
我可以用其實現(xiàn)一個 "輸入聯(lián)想" 的功能。
<label> 輸入C開頭的英文單詞:</label>
<input list="c_words"/>
<datalist id="c_words">
<option value="China">
<option value="Click">
<option value="Close">
<option value="Const">
<option value="Count">
</datalist>
來試一試:
剛點擊時會把所有推薦的選項都列出來,然后根據(jù)后面輸入的內(nèi)容,會過濾掉不匹配的選項,比如我輸入 cl,會過濾掉不是 cl 開頭的單詞,最后只剩下 Click 和 Close 了。
最后我發(fā)現(xiàn),他這個下拉框有點好看啊?為啥這原生的 input 框默認(rèn)樣式那么丑,啥時候改改。
fieldset 標(biāo)簽是用于分組管理 form 表單內(nèi)的元素的,若 fieldset 設(shè)置了 disabled 屬性,則被其包裹的所有表單元素都會被禁用置灰,且不會隨著表單一起提交上去,是的就成了擺設(shè)。
什么意思呢?看個例子:
<form action="/example">
<fieldset disabled>
<legend>被禁用區(qū)域</legend>
<label>ID:</label>
<input type="text" name="id" value="1">
<label>郵箱:</label>
<input type="text" name="email" value="1234567@163.com">
</fieldset>
<label>名字:</label>
<input type="text" name="name">
<button type="submit">提交</button>
</form>
這里我們把 ID 和 郵箱 的表單包裹了起來,且設(shè)置了 disabled,只開放了一個 name 的輸入控件,此時界面如下:
可以看到除了 name 輸入框,其它的兩個輸入框都被禁用了,此時點提交會是什么樣子呢?
嗯,只提交了 name 字段。
這個標(biāo)簽是在瀏覽器不支持或禁用了 javascript 時才展示的,大多用于對 js 強依賴的應(yīng)用,比如現(xiàn)在大部分的 SPA 頁面,一旦不支持 javascript,頁面基本上什么內(nèi)容都沒了,此時可以靠這個標(biāo)簽做友好提示。
一般我們不需要特地去使用,大多都是在打包過程中自動插入到 html 靜態(tài)文件里去的,例如:
// init.js
const root = document.getElementById('root')
const button = document.createElement('button')
button.innerText = '點擊出彈窗'
root.appendChild(button)
<!-- index.html -->
<script defer src="./init.js"></script>
<noscript>
不好意思,你的瀏覽器不支持或禁用了 JavaScript,請更換瀏覽器或啟用 JavaScript
</noscript>
<div id="root"></div>
未禁用 javascript 時,頁面是這樣的:
禁用了 javascript 時,是這樣的:
過閱讀本文,希望你能意識到在項目中可以減少JavaScript的使用。
原文鏈接:https://www.htmhell.dev/adventcalendar/2023/2/
未經(jīng)允許,禁止轉(zhuǎn)載!
首先聲明我并不討厭JavaScript,相反,我很喜歡JavaScript,而且每天我都會編寫大量的JavaScript。但我也喜歡CSS,甚至喜歡 HTML。我之所以喜歡這三種技術(shù),是因為:最小權(quán)限原則。
這是Web開發(fā)的核心原則之一,意思是說你應(yīng)該在特定情境下選擇最“弱”的語言。
在Web上,這意味著選擇的優(yōu)先順序為:HTML > CSS > JavaScript。在這三種技術(shù)中,JavaScript是最靈活的語言,因為你可以描述瀏覽器應(yīng)該如何運行,但JavaScript代碼也可能出現(xiàn)故障、無法加載,而且需要額外的資源來下載、解析和運行。此外,使用JavaScript還會導(dǎo)致鍵盤用戶和使用輔助技術(shù)的用戶無法使用頁面。
與JavaScript不同,HTML和CSS是聲明式的。你告訴瀏覽器做什么,而不是怎么做。這意味著瀏覽器可以選擇如何執(zhí)行,并以最有效的方式執(zhí)行。
由于HTML和CSS的特性由瀏覽器處理,因此更高效、更原生、更符合用戶的偏好,而且更易訪問。雖然有時也并非這般美好(尤其是在可訪問性方面),但由瀏覽器替你完成繁重的工作,通常最終用戶都會有更好的體驗。
你可能會想:“我使用JavaScript正是因為我需要它?!痹掚m如此,但你要知道瀏覽器制造商和規(guī)范撰寫者已經(jīng)將許多功能轉(zhuǎn)移到了CSS和HTML上,而在幾年前這些功能還需要JavaScript。這正是本文所討論的內(nèi)容。
Web的棘手之處在于,在學(xué)會如何構(gòu)建某個功能之后,就永遠(yuǎn)都不需要再學(xué)一次了。我們默認(rèn)Web是向后兼容的(有極少數(shù)例外,但全世界第一個Web網(wǎng)頁至今仍然可以在所有現(xiàn)代瀏覽器中正常運行)。
這也意味著,你學(xué)習(xí)到的解決方案都成為了你的工具箱的一部分,你可以反復(fù)使用,而且每次都能正常工作。因此,下面我所給出的示例都很酷,但我希望通過閱讀本文,你能有所收獲:雖然你知道一些功能需要JavaScript,但這不意味著如今仍然需要。你可以試試看,牢記這一點你就能制作出更好的網(wǎng)站。
自定義開關(guān)
首先是一個label元素,里面包含一個復(fù)選框。這樣做的好處是,瀏覽器已經(jīng)為我們完成了很多工作。因為input位于label內(nèi)部,瀏覽器已經(jīng)將二者關(guān)聯(lián)起來了,我們只需點擊label的某處,就可以切換復(fù)選框,而無需onclick處理程序。瀏覽器免費為我們提供了這個功能。從功能上來說,我們已經(jīng)做完了。
當(dāng)然,設(shè)計師可不喜歡這個外觀。下面,我們來添加一些CSS代碼,創(chuàng)建一個擁有漂亮外觀的自定義開關(guān)。
此處的樣式細(xì)節(jié)并不重要,但我希望你注意一下第二行代碼:appearance: none。
表單元素,以及圖片被稱為“替換內(nèi)容”。這意味著,它們并不真正屬于HTML,而是由瀏覽器提供的。當(dāng)瀏覽器渲染HTML并發(fā)現(xiàn)替換內(nèi)容時,就會留下一個框,然后用實際內(nèi)容替換該框。這就是為什么,例如,圖片和表單元素不能使用偽元素的原因:當(dāng)瀏覽器替換整個元素時,它們會被替換掉。
appearance 是告訴瀏覽器停止這種做法的一種方式。它告訴瀏覽器:“謝謝,但我想自己樣式化我的表單控件?!边@樣,我們就可以使用::before 偽元素了?,F(xiàn)在input本身就是開關(guān)的背景,而 ::before 偽元素是其中的切換點。
點擊鼠標(biāo)仍然可以切換復(fù)選框,但由于替換了元素,所以我們需要自己完成外觀顯示的工作。這里我們需要用到是:checked偽類:
此時點擊復(fù)選框時,:checked偽類開始工作,外觀就會更新。
此處,我們使用原生HTML元素和一些CSS創(chuàng)建了一個擁有漂亮外觀的自定義開關(guān),但我們的工作還沒有完成。對于鼠標(biāo)用戶,我們很清楚他們正在與哪個表單控件交互,但對于使用鍵盤的人來說,就沒有那么容易了。
我相信你很熟悉下面這段CSS。為了擺脫那個丑陋的、點狀的方框輪廓。
看到這里,你可能會說這種寫法并不好。但我們應(yīng)該怎樣改進(jìn)呢?在這方面,瀏覽器也已更新,能為我們提供更好的體驗。如今,outline會沿著元素的border-radius顯示,而且我們還可以將它設(shè)置到元素外部或內(nèi)部:
如此一來,當(dāng)用戶使用鍵盤與元素交互時(你可以嘗試在點擊復(fù)選框后按空格鍵,或者通過Tab鍵定位到它),:focus-visible就會匹配(使用鼠標(biāo)時不會),然后你就能看到元素周圍出現(xiàn)了一個漂亮的、藍(lán)色的輪廓線。
最后,我希望你將outline: none替換為:
最后的結(jié)果相同:你看不見輪廓線,不是因為它被隱藏了,而是因為它是透明的。然而,打開高對比度模式(也稱為強制顏色)的用戶就可以看到這條輪廓線。因為在高對比度模式下,透明顏色會被用戶選擇的顏色替換,幫助他們看清楚正在與之交互的內(nèi)容,即使他們使用鼠標(biāo)。
我希望在下一個項目中,當(dāng)需要安裝自動完成的框架時,你可以先試試看數(shù)據(jù)列表(datalist)。數(shù)據(jù)列表是瀏覽器內(nèi)置的一個功能,可在用戶輸入時以列表的形式顯示選項。
為了使用這個功能,你需要在HTML中添加一個帶有ID和一組選項的數(shù)據(jù)列表元素。別擔(dān)心,這個元素是不可見的。然后,你需要使用input的list屬性將它們關(guān)聯(lián)起來。
當(dāng)用戶在input中輸入時,瀏覽器就會將數(shù)據(jù)列表顯示為下拉菜單,并根據(jù)用戶的輸入自動過濾選項。由于它是一個常規(guī)輸入,用戶仍然可以輸入自己的值。當(dāng)然,他們也可以選擇輸入框并使用箭頭鍵導(dǎo)航列表,或者點擊瀏覽器添加的下拉圖標(biāo)來查看所有選項。
我們見過很多具有漂亮外觀的顏色選擇器,它們由漂亮的畫布UI和幾百行的JavaScript代碼構(gòu)建而成。但你可知道你也可以使用原生的顏色選擇器?
這行HTML就可以為你提供一個擁有漂亮的UI的顏色選擇器,免去你編寫大量的JavaScript。此外,由于這個顏色選擇器是由瀏覽器處理的,我們還可以免費獲得更多功能。在Chromium瀏覽器中,這個原生顏色選擇器還可以讓你自由選擇顏色,不僅可以選擇自己的網(wǎng)站,還可以從屏幕的任何地方選擇顏色。非常強大!
需要注意的是,盡管瀏覽器顯示了一個漂亮的顏色選擇器,但并非所有的用戶都可以使用。但提供另一種選擇顏色的方式仍然是一個好主意。
折疊菜單是以更有條理、更整潔的方式顯示具有大量內(nèi)容的頁面的一種好方法,因為它可以將不必要的內(nèi)容隱藏起來,當(dāng)用戶需要時再顯示出來。而如今瀏覽器也提供了免費的折疊菜單,你可以通過details和summary元素實現(xiàn):
默認(rèn)情況下,details元素內(nèi)的所有內(nèi)容都是隱藏的,summary元素除外。當(dāng)用戶點擊summary元素時,瀏覽器會顯示其余內(nèi)容。
通常你會看到折疊菜單的其中一項已是打開狀態(tài),而其他項是關(guān)閉的。你可以使用open屬性來實現(xiàn)這一點:
如果你熟悉React,看到這段代碼就會想:“這樣很好,如今該元素有了open屬性,就不會再關(guān)閉了”,然而實際情況并非如此。open屬性只是初始狀態(tài),會隨著用戶的交互更新。
你也可以定義details元素的樣式。那個小三角形(設(shè)計師一看到就想要替換)是一個::marker偽元素,你可以設(shè)置它的樣式:
請記住,更改內(nèi)容可能會影響輔助技術(shù)如何讀取折疊菜單。此外,對于Safari,你需要使用偽元素::-webkit-details-marker。
偽元素marker無法像其他元素一樣指定常見的樣式(許多CSS屬性對它無效,例如將其定位到完全不同的位置),但你可以替換其內(nèi)容,例如使用表情符號,設(shè)置背景顏色或圖像,以及更改字體大小。
我們可以通過open屬性賦予打開狀態(tài)和關(guān)閉狀態(tài)不同的樣式。
最后,我們想要對summary元素做一些處理。它是可點擊的,但與鏈接不同,它沒有指針光標(biāo),而且看起來也不像一個按鈕。因此,我認(rèn)為我們應(yīng)該為它添加懸停和焦點狀態(tài),并幫助用戶意識到它是可點擊的:
此處,我不想討論“只有鏈接應(yīng)有指針光標(biāo)”的問題,我想表達(dá)的主要觀點是你需要做一些處理。
有時你需要向用戶傳達(dá)一些信息,或詢問他們,或讓他們確認(rèn)一些事情。在JavaScript中,我們可以使用alert()、prompt()和confirm()。但它們有一個很大的缺點:它們鎖定了主線程,這意味著頁面不能做任何其他事情。此外,這些都是瀏覽器原生的功能,因此你不能根據(jù)自己的設(shè)計設(shè)置它們的樣式。
另一方面,構(gòu)建自己的對話框純屬自找麻煩:你需要保持焦點在對話框內(nèi),以確??稍L問性,聲明它的模態(tài)性,確保用戶不會意外退出,而且還需要與z-index為2147483647的聊天小部件斗爭(懂得都懂)。
因此,瀏覽器提供了一個原生的對話框元素:
這個元素默認(rèn)情況下是不顯示的,因此我們需要一些小技巧,而且還會用到JavaScript:
上面的代碼可以在不使用JavaScript的情況下打開對話框,但這種寫法還沒有規(guī)范化。因此,目前我們需要使用JavaScript來打開對話框。但只有這個地方用到了JavaScript,其余代碼都是原生HTML和CSS。
dialog元素有一個showModal()函數(shù),我們可以利用它打開對話框。這個對話框是在top-layer上打開的,這是瀏覽器中的一個新概念。
這里的top layer是一個新層,不同于HTML,你可以將元素“提升”到該層。這意味著,位于top layer上的元素始終在所有其他元素之上,無論元素的z-index和上下文嵌套如何。
然而,你可能會注意到瀏覽器并沒有提供任何UI。這個對話框基本上就是一個div(不是按鈕),必須由你來提供關(guān)閉按鈕。這就是上面代碼中表單的作用。你可能已經(jīng)注意到它有一個"dialog"方法。在提交該表單時,瀏覽器會將其視為關(guān)閉對話框的信號。
另外,你還可以創(chuàng)建確認(rèn)對話框,只需提供兩個按鈕即可:
為了響應(yīng)用戶點擊按鈕,你需要通過監(jiān)聽對話框上的close事件,并讀取returnValue屬性:
如果對話框中還有其他表單數(shù)據(jù),你還可以讀取formData。
至于樣式,由于該對話框本質(zhì)上是一個div,你可以根據(jù)自己的需求設(shè)置樣式。瀏覽器只負(fù)責(zé)自動將其放置在屏幕中央,其他一切由你決定。
另外,對話框還帶有一個新的偽元素,名叫 ::backdrop。這是一個位于對話框和頁面其余部分之間的層,你可以設(shè)置它的樣式,例如,調(diào)暗頁面的其余部分或以其他方式將用戶的注意力引導(dǎo)到對話框上。舉個例子,你可以覆蓋一個白色層并模糊頁面:
就像對話框元素本身一樣,backdrop 的定位由瀏覽器處理,因此你無需擔(dān)心滾動、固定元素和瀏覽器調(diào)整大小。這一切都由瀏覽器處理。
希望通過閱讀本文,你能意識到下一個項目可以減少JavaScript的使用。
這類的例子還有很多,下面僅列舉一些:
使用scroll-behavior: smooth實現(xiàn)原生的平滑滾動(僅當(dāng)prefers-reduced-motion: no-preference匹配時)。
使用scroll-snap創(chuàng)建原生的輪播。
使用position: sticky創(chuàng)建"視圖內(nèi)"的元素。
以及容器查詢的概念等。
另外,展望未來,我們還會看到更多有趣的東西:
滾動驅(qū)動的動畫。
使用grid-template-rows: masonry實現(xiàn)瀑布流布局。
使用新的selectlist元素實現(xiàn)完全可樣式化的選擇框(你可以樣式化選擇框的每個部分,而無需破壞其原生功能)。
:has()選擇器將消除一大類JS選擇。
最后,重申本文的主要觀點:
雖然你知道一些功能需要JavaScript,但這不意味著如今仍然需要。你可以試試看,牢記這一點你就能制作出更好的網(wǎng)站。
日常開發(fā)時,彈窗是一個經(jīng)常使用的功能,而且重復(fù)性極高,你可能會遇到下面這些問題:
1、一個頁面內(nèi)多個彈窗, 要維護(hù)多套彈窗狀態(tài),看的眼花繚亂
2、彈窗內(nèi)容比較簡單,聲明變量 + 模板語法的方式寫起來比較麻煩
關(guān)于這些問題, 我首先想到的是應(yīng)該弄一個即用即走的Dialog,不用去單獨維護(hù)它的狀態(tài),使用Dialog({ xxx })這種形式去調(diào)用它,例如下面這種配置的方式:
Dialog({
title: 'xxx',
render: () => xxx
})
其中render可以是一個html字符串,也可以是jsx(需要配置對jsx的支持),這樣可以對內(nèi)容區(qū)域?qū)崿F(xiàn)自定義。
各大主流的ui庫基本都實現(xiàn)了這種調(diào)用方式:
之前沒有注意到Element-plus的MessageBox可以使用jsx,大部分場景下,用它來代替Dialog還是很方便的。
示例代碼:
<script lang="jsx" setup>
import { reactive, ref } from 'vue';
import { ElMessageBox, ElForm, ElFormItem, ElInput } from 'element-plus'
const formRef = ref(null)
const form = reactive({ height: '', width: '' })
const rules = reactive({
height: {
required: true,
trigger: 'blur'
},
width: {
required: true,
trigger: 'blur'
}
})
function openMessageBox() {
ElMessageBox({
title: 'Message',
showCancelButton: true,
// message如果不是函數(shù)形式 綁定ref會失敗
message: () =>
<ElForm
ref={formRef}
model={form}
rules={rules}
>
<ElFormItem label="height" prop="height">
<ElInput v-model={form.height}></ElInput>
</ElFormItem>
<ElFormItem label="width" prop="width">
<ElInput v-model={form.width}></ElInput>
</ElFormItem>
</ElForm>
,
beforeClose: (action, instance, done) => {
console.log(action, instance)
formRef.value && formRef.value.validate(status => {
console.log('校驗狀態(tài): ', status)
if (status || action==='cancel') done()
})
}
})
}
</script>
<template>
<div class="container">
<button @click="openMessageBox">
打開messagebox
</button>
</div>
</template>
效果如下:
如果你不想使用jsx,而是想使用模板,vue的hooks工具庫vueuse中提供了 createTemplatePromise 這個函數(shù)用來創(chuàng)建對話框、模態(tài)框、Toast 等,并且完全使用的是template的方式,因此自定義程度更高,并且沒有任何額外成本(不需要jsx)。
下面是一個createTemplatePromise結(jié)合el-dialog的例子(當(dāng)然也可以結(jié)合其它的dialog或者自定義dialog):
<script lang="jsx" setup>
import { createTemplatePromise } from '@vueuse/core'
import { ElDialog, ElButton } from 'element-plus'
const TemplatePromise = createTemplatePromise()
async function open(idx) {
console.log(idx, 'Before')
const result = await TemplatePromise.start('Title', `Hello ${idx}`)
console.log(idx, 'After', result)
}
function asyncFn() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('ok')
}, 1000)
})
}
</script>
<template>
<div class="container">
<button @click="open(1); open(2)">
打開兩個彈框
</button>
</div>
<TemplatePromise v-slot="{ resolve, args, isResolving }">
<el-dialog :modelValue="true" :title="args[0]">
<div>Dialog {{ args[1] }}</div>
<p>可以打開控制臺查看logs</p>
<div class="flex gap-2 justify-end">
<el-button @click="resolve('cancel')">
取消
</el-button>
<el-button type="primary" :disabled="isResolving" @click="resolve(asyncFn())">
{{ isResolving ? 'loading...' : '確認(rèn)' }}
</el-button>
</div>
</el-dialog>
</TemplatePromise>
</template>
效果如圖:
這樣有小伙伴可能會說, 這看起來和原來用dialog也沒有很大區(qū)別啊, 也要寫模版 + 函數(shù)方法. 那么讓dialog變成這樣有什么好處呢?
1、最大的好處是彈窗變得可編程了, 通過函數(shù)調(diào)用的方式來控制UI. 不用再單獨聲明變量控制顯隱, 也不用單獨再去控制按鈕的禁用、loading等狀態(tài). 例如以上的例子中, 我們可以輕松的處理button的loading狀態(tài)(不用再額外聲明變量), 用Promise讓Dialog的UI和狀態(tài)實現(xiàn)了內(nèi)聚.
2、相比第一種方式, 對UI的可自定義程度更高.
作者:隔壁老王z
鏈接:https://juejin.cn/post/7293173815181738022
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。