整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          11 個可能你沒見過,但非常特別的 HTML 標(biāo)簽

          、abbr

          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

          <mark/> 在 markdown 中也是很常用的,用于將包裹的文本高亮展示。

          <mark>高亮文本</mark>
          

          效果如下:

          如果全文統(tǒng)一高亮樣式,可以專門對 mark 標(biāo)簽進(jìn)行樣式重置,這樣就不用對你用的每個 div 加一個 highlight 的類名了,又不語義化,又徒增文檔大小。

          三、sup、sub

          <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-aligntopsub 屬性值,然后將字號縮小,不過有現(xiàn)成的標(biāo)簽,干嘛不用呢?

          四、figure

          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

          說到 <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

          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ū)分別是:

          • 坐標(biāo) (0,0) 到坐標(biāo) (100,50) 的一個矩形
          • 坐標(biāo) (0,50) 到坐標(biāo) (100,100) 的一個矩形

          我們都知道,默認(rèn)的坐標(biāo)軸是這樣的:

          因此,我們劃分的兩個熱區(qū)就是:

          最后再來看一下我們的實際效果:

          i

          七、details

          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>
          

          就搞定了!

          八、dialog

          瀏覽器自帶彈窗方法 alert、confirmprompt,樣式固定且每個瀏覽器不同,同時還會阻塞頁面運行,除了這個還提供了一個 dialog 標(biāo)簽,它的使用方式有點類似于現(xiàn)在各大組件庫的 Modal 組件了,瀏覽器還為該標(biāo)簽提供了原生的 dom 方法:showModalclose,可以直接控制彈窗的展示和隱藏。

          <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

          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 開頭的單詞,最后只剩下 ClickClose 了。

          最后我發(fā)現(xiàn),他這個下拉框有點好看啊?為啥這原生的 input 框默認(rèn)樣式那么丑,啥時候改改。

          十、fieldset

          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 字段。

          十一、noscript

          這個標(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)載!


          作者 | Kilian Valkhof 譯者 | 彎月
          責(zé)編 | 夏萌
          出品 | CSDN(ID:CSDNnews)

          首先聲明我并不討厭JavaScript,相反,我很喜歡JavaScript,而且每天我都會編寫大量的JavaScript。但我也喜歡CSS,甚至喜歡 HTML。我之所以喜歡這三種技術(shù),是因為:最小權(quán)限原則。

          最小權(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

          你可能會想:“我使用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)

          我們的第一個例子是大家都非常熟悉的自定義開關(guān)。與普通的復(fù)選框不同,我們來設(shè)計要一個外觀十分漂亮的開關(guān)。如果使用JavaScript,我們需要編寫div、onclick處理程序和內(nèi)部狀態(tài)。但此處,我們將使用常規(guī)復(fù)選框和:checked偽類。以下是我們將要使用的HTML:

          首先是一個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)。

          數(shù)據(jù)列表,原生的自動建議

          我希望在下一個項目中,當(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á)的主要觀點是你需要做一些處理。

          模態(tài)對話框

          有時你需要向用戶傳達(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)整大小。這一切都由瀏覽器處理。

          總結(jié)

          希望通過閱讀本文,你能意識到下一個項目可以減少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)自定義。

          通過配置項調(diào)用

          各大主流的ui庫基本都實現(xiàn)了這種調(diào)用方式:

          • Ant Design Vue的 Modal
          • Element-plus的 MessageBox

          之前沒有注意到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>
          


          效果如下:

          vueuse的createTemplatePromise

          如果你不想使用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>
          


          效果如圖:

          Promise化Dialog的優(yōu)點

          這樣有小伙伴可能會說, 這看起來和原來用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


          主站蜘蛛池模板: 福利一区福利二区| 色一乱一伦一区一直爽| 亚洲一区二区三区免费| 麻豆天美国产一区在线播放| 成人在线视频一区| 国产在线观看一区二区三区精品| 亚洲综合一区二区精品导航| 美女视频在线一区二区三区| 日本不卡一区二区视频a| 日本亚洲成高清一区二区三区| 亚洲国产一区明星换脸| 中文字幕无码一区二区免费| 久久99精品波多结衣一区| 亚洲国产欧美日韩精品一区二区三区 | 美女视频一区三区网站在线观看 | 日韩免费无码一区二区三区| 亚洲综合无码一区二区三区| 国产精品美女一区二区| 精品视频一区二区三区四区五区| 91视频一区二区| 国产一区二区草草影院| 日韩精品人妻一区二区三区四区 | 国产日韩一区二区三区在线播放| 人妻互换精品一区二区| 亚洲AV无码一区二区三区在线观看| 波多野结衣中文字幕一区| 国产伦精品一区二区三区无广告| 国产一国产一区秋霞在线观看 | 在线免费视频一区| 黑人大战亚洲人精品一区| 亚洲高清一区二区三区| 国产无码一区二区在线| 亚洲国产精品综合一区在线 | av无码人妻一区二区三区牛牛| 精品无码人妻一区二区三区品| 国产日韩高清一区二区三区 | 国产亚洲欧洲Aⅴ综合一区| 久久久久人妻一区精品色| 国产精品女同一区二区久久| 精品女同一区二区三区在线| 蜜臀AV无码一区二区三区|