最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于原生CSS+JS實(shí)現(xiàn)一個(gè)標(biāo)簽輸入框

 更新時(shí)間:2022年04月07日 15:38:50   作者:XboxYan  
在各種框架大行其道的氛圍下,有些原生的屬性和方法可能都不太關(guān)注了,這也不失為是一種損失。本文就將利用原生CSS+JS實(shí)現(xiàn)一個(gè)簡(jiǎn)單的標(biāo)簽輸入框,感興趣的可以了解一下

最近在項(xiàng)目中需要做一個(gè)標(biāo)簽輸入框,還挺實(shí)用的,演示效果如下:

主要交互要求是這樣的:

  • 點(diǎn)擊輸入框可以輸入內(nèi)容。
  • 按回車(chē)可以生成標(biāo)簽。
  • 按退格鍵可以刪除標(biāo)簽。
  • 點(diǎn)擊標(biāo)簽上的關(guān)閉按鈕可以刪除標(biāo)簽。

習(xí)慣了各種 react 框架或者UI庫(kù),大家有多久沒(méi)接觸沒(méi)有原生開(kāi)發(fā)了呢?有時(shí)候頁(yè)面比較簡(jiǎn)單,沒(méi)必要引入一個(gè)完整的框架,原生實(shí)現(xiàn)就完全滿足了,一起看看吧!

一、自適應(yīng)輸入框布局

不管什么組件,布局都是最重要的。這個(gè)布局分為標(biāo)簽和輸入框兩個(gè)部分,假設(shè) HTML 如下:

<div class="tags-content">
  <tag>CSS<a class="tag-close"></a></tag> 
  <input class="tags-input" placeholder="添加標(biāo)簽">
</div>

簡(jiǎn)單修飾一下:

.tags-content{
   display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 6px;
    width: 400px;
    box-sizing: border-box;
    padding: 8px 12px;
    border: 1px solid #D9D9D9;
    border-radius: 4px;
    font-size: 16px;
    line-height: 24px;
    color: #333;
    outline-color: #4F46E5;
    overflow: auto;
    cursor: text;
}
tag{
    display: flex;
    align-items: center;
    padding: 4px 0 4px 8px;
    font-size: 16px;
    line-height: 24px;
    background: #F5F5F5;
    color: rgba(0, 0, 0, 0.85);
    cursor: default;
}
tag-close{
    width: 18px;
    height: 18px;
    cursor: pointer;
    background: url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.578 5l2.93-3.493a.089.089 0 0 0-.068-.146h-.891a.182.182 0 0 0-.137.064l-2.417 2.88-2.416-2.88a.178.178 0 0 0-.137-.064h-.89a.089.089 0 0 0-.069.146L4.413 5l-2.93 3.493a.089.089 0 0 0 .068.146h.89a.182.182 0 0 0 .138-.064l2.416-2.88 2.417 2.88c.033.04.083.064.137.064h.89a.089.089 0 0 0 .069-.146l-2.93-3.493z' fill='%23000' fill-opacity='.45'/%3E%3C/svg%3E") center no-repeat;
}
.tags-input{
    flex: auto;
    border: 0;
    outline: 0;
    padding: 4px 0;
    line-height: 24px;
    font-size: 16px;
}
.tags-content:focus-within,
.tags-content:active{
    outline: auto #4F46E5;
}

注意幾點(diǎn)實(shí)現(xiàn)技巧:

  • 標(biāo)簽的間隔可以用 gap 實(shí)現(xiàn)。
  • 為了讓輸入框的區(qū)域鋪滿剩余空間,這里用到了flex: auto。
  • 為了讓父級(jí)處于聚焦?fàn)顟B(tài),這里用到了:focus-within。

效果如下:

但是這里的輸入框用 input 還是有些問(wèn)題的,如下所示:

由于 input 輸入內(nèi)容無(wú)法跟隨寬度自適應(yīng),所以有時(shí)候會(huì)出現(xiàn)文字被截?cái)嗟那闆r:

理想情況下,當(dāng)輸入內(nèi)容較多時(shí),應(yīng)該整體換行。如何實(shí)現(xiàn)呢?可以用普通的 div 來(lái)實(shí)現(xiàn)。

<div class="tags-content">
  <tag>CSS<a class="tag-close"></a></tag> 
  <div class="tags-input" placeholder="添加標(biāo)簽"></div>
</div>

可以通過(guò)添加contenteditable或者以下 CSS 來(lái)實(shí)現(xiàn):

.tags-input{
  -webkit-user-modify: read-write-plaintext-only;
}

這個(gè)屬性表示只允許輸入純文本,有興趣的可以參考張?chǎng)涡竦倪@篇文章:小tip: 如何讓contenteditable元素只能輸入純文本[1]。

這樣可以自適應(yīng)內(nèi)容寬度了。

二、輸入框占位提示

由于輸入框已經(jīng)從 input 換成了普通的 div 標(biāo)簽,并沒(méi)有 placeholder 特性。不過(guò),我們?nèi)匀豢梢酝ㄟ^(guò)其他 CSS 特性來(lái)實(shí)現(xiàn)占位效果,當(dāng)輸入框沒(méi)有內(nèi)容時(shí),就可以匹配到 :empty選擇器,然后通過(guò)偽元素::before動(dòng)態(tài)生成 placeholder 內(nèi)容,具體實(shí)現(xiàn)如下:

.tags-input:empty::before{
    content: attr(placeholder);
    color: #828282;
}

效果如下:

這樣就幾乎和 input 的占位效果一致了。

另外還有一種情況,如果需要僅在沒(méi)有任何標(biāo)簽的情況下才顯示占位,如何實(shí)現(xiàn)呢?可以想想,在沒(méi)有任何標(biāo)簽的情況下,HTML 就變成了這樣:

<div class="tags-content">
  <div class="tags-input" placeholder="添加標(biāo)簽"></div>
</div>

這種情況,就僅剩輸入框唯一元素了,唯一元素可以通過(guò):only-child來(lái)匹配,所以實(shí)現(xiàn)如下:

.tags-input:only-child:empty::before{
    content: attr(placeholder);
    color: #828282;
}

這樣添加一個(gè)偽類(lèi)就解決了。

兩種需求都符合認(rèn)知,看設(shè)計(jì)如何決定了。

三、標(biāo)簽的輸入與刪除

要實(shí)現(xiàn)標(biāo)簽的輸入與刪除就需要 JS 出馬了,只需要監(jiān)聽(tīng)鍵盤(pán)的“回車(chē)”和“退格”兩個(gè)鍵值。需要注意的是,默認(rèn)情況下,普通 contenteditable元素在回車(chē)時(shí),會(huì)出現(xiàn)換行,如下:

因此,在監(jiān)聽(tīng)鍵盤(pán)事件時(shí)需要阻止默認(rèn)事件,然后動(dòng)態(tài)創(chuàng)建標(biāo)簽元素,通過(guò) before添加到輸入框前面,具體實(shí)現(xiàn)如下:

// TagInput是輸入框
TagInput.addEventListener('keydown', function(ev) {
  if (ev.key === 'Enter') {
    ev.preventDefault()
    if (this.innerText) { // 輸入框內(nèi)容通過(guò) innerText 獲取
      const tag = document.createElement('TAG');
      tag.innerHTML = this.innerText + '<a class="kalos-tag-close"></a>';
      this.before(tag);
      this.innerText = '';
    }
  }
})

這樣就能正常創(chuàng)建標(biāo)簽了。

然后是標(biāo)簽的刪除。

這里有兩種途徑,首先看鍵盤(pán)的刪除,具體邏輯是當(dāng)輸入框內(nèi)容為空時(shí)刪除標(biāo)簽,很簡(jiǎn)單,刪除的標(biāo)簽就是輸入框的前面一個(gè)元素,通過(guò)previousElementSibling獲取,具體實(shí)現(xiàn)如下:

TagInput.addEventListener('keydown', function(ev) {
  if (ev.key === 'Backspace' && !this.innerText) {
    this.previousElementSibling?.remove(); // 需要判斷前一個(gè)元素是否存在
  }
})

然后是點(diǎn)擊刪除圖標(biāo)的刪除。由于標(biāo)簽是動(dòng)態(tài)生成的,所以這里需要用事件委托的方式來(lái)添加刪除事件。

// TagContent是父級(jí)容器
TagContent.addEventListener('click', function(ev) {
  if (ev.target.className === 'tag-close') {
    ev.target.parentNode.remove();
  }
  TagInput.focus(); //點(diǎn)擊任意地方輸入框都需要聚焦
})

這樣就實(shí)現(xiàn)了文章開(kāi)頭的所示效果:

四、選擇框架還是原生

總結(jié)一下!

整體實(shí)現(xiàn)并不算復(fù)雜,不少交互邏輯 CSS 也可以輕松實(shí)現(xiàn),JS 也就 10 來(lái)行代碼,這里總結(jié)一下實(shí)現(xiàn)要點(diǎn):

  • 普通 div 元素輸入純文本可以使用 -webkit-user-modify: read-write-plaintext-only
  • 普通 div 元素輸入可以自適應(yīng)內(nèi)容寬度
  • 普通 div 元素輸入框的 placeholder 占位可以通過(guò) :empty 結(jié)合偽元素實(shí)現(xiàn)
  • 回車(chē)事件需要阻止默認(rèn)事件,不然會(huì)換行
  • 在一個(gè)元素的前面新增元素可以用 before 方法
  • 刪除一個(gè)元素的前面一個(gè)元素,可以用 previousElementSibling.remove 方法
  • 給動(dòng)態(tài)生成的元素綁定事件可以用事件委托的方式

在各種框架大行其道的氛圍下,有些原生的屬性和方法可能都不太關(guān)注了,這也不失為是一種損失。當(dāng)然,我本身也是各種框架都會(huì)用,特別是大型、復(fù)雜的交互頁(yè)面,一般比較小的交互,比如文章這個(gè)例子,在 ant design 中有相關(guān)的組件,也使用過(guò),因?yàn)檎w UI 全是這種風(fēng)格,設(shè)計(jì)也是按照這個(gè)設(shè)計(jì)的。后來(lái)需要單獨(dú)開(kāi)發(fā)一個(gè) chrome 插件,也用到了這樣一個(gè)交互,但是僅僅用了這樣一個(gè)組件,引入整個(gè)框架就過(guò)于累贅了,所以還是選擇直接原生實(shí)現(xiàn),簡(jiǎn)單方便。

以上就是基于原生CSS+JS實(shí)現(xiàn)一個(gè)標(biāo)簽輸入框的詳細(xì)內(nèi)容,更多關(guān)于JS標(biāo)簽輸入框的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JS實(shí)現(xiàn)下拉菜單賦值到文本框的方法

    JS實(shí)現(xiàn)下拉菜單賦值到文本框的方法

    這篇文章主要介紹了JS下拉菜單賦值到文本框的方法,涉及javascript頁(yè)面元素的選擇與賦值的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-08-08
  • 如何使用JavaScript獲取word的內(nèi)容

    如何使用JavaScript獲取word的內(nèi)容

    這篇文章主要為大家詳細(xì)介紹了如何使用JavaScript獲取word的內(nèi)容,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • 使用JavaScript操作Visual Viewport的方法示例

    使用JavaScript操作Visual Viewport的方法示例

    在現(xiàn)代前端開(kāi)發(fā)中,視口(viewport)是一個(gè)非常重要的概念,它決定了用戶在瀏覽網(wǎng)頁(yè)時(shí)所看到的內(nèi)容,JavaScript 提供了一個(gè)強(qiáng)大的接口 —— Visual Viewport API,讓開(kāi)發(fā)者可以更靈活地控制和獲取視口的信息,本文將詳細(xì)介紹如何使用 Visual Viewport API
    2024-09-09
  • TopList標(biāo)簽和JavaScript結(jié)合兩例

    TopList標(biāo)簽和JavaScript結(jié)合兩例

    TopList標(biāo)簽和JavaScript結(jié)合兩例...
    2007-08-08
  • 微信小程序圖片左右擺動(dòng)效果詳解

    微信小程序圖片左右擺動(dòng)效果詳解

    這篇文章主要介紹了微信小程序圖片左右擺動(dòng)效果詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • JavaScript自定義鼠標(biāo)右鍵菜單欄

    JavaScript自定義鼠標(biāo)右鍵菜單欄

    這篇文章主要為大家詳細(xì)介紹了JavaScript自定義鼠標(biāo)右鍵菜單欄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • js+css實(shí)現(xiàn)計(jì)算器功能

    js+css實(shí)現(xiàn)計(jì)算器功能

    這篇文章主要為大家詳細(xì)介紹了js+css實(shí)現(xiàn)計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • JavaScript設(shè)計(jì)模式--橋梁模式引入操作實(shí)例分析

    JavaScript設(shè)計(jì)模式--橋梁模式引入操作實(shí)例分析

    這篇文章主要介紹了JavaScript設(shè)計(jì)模式--橋梁模式,結(jié)合實(shí)例形式分析了JavaScript設(shè)計(jì)模式中橋梁模式應(yīng)用操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2020-05-05
  • js控制的回到頁(yè)面頂端goTop的代碼實(shí)現(xiàn)

    js控制的回到頁(yè)面頂端goTop的代碼實(shí)現(xiàn)

    在瀏覽網(wǎng)頁(yè)的時(shí)候應(yīng)該會(huì)經(jīng)常見(jiàn)到右下角有個(gè)【回到頂端】的懸浮東東,本文也要使用js實(shí)現(xiàn)一下,感興趣的朋友可以參考下哈,希望可以幫助到你
    2013-03-03
  • 微信小程序?qū)崿F(xiàn)單選選項(xiàng)卡切換效果

    微信小程序?qū)崿F(xiàn)單選選項(xiàng)卡切換效果

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)單選選項(xiàng)卡切換效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02

最新評(píng)論

霞浦县| 竹山县| 万荣县| 乌鲁木齐市| 内丘县| 曲靖市| 资溪县| 曲松县| 垫江县| 泊头市| 青浦区| 平定县| 榆社县| 阿荣旗| 焉耆| 星子县| 祁门县| 伊川县| 县级市| 泰安市| 乾安县| 宣化县| 富平县| 鹤峰县| 民和| 武穴市| 同德县| 景谷| 密云县| 邢台市| 大庆市| 肃南| 会昌县| 甘孜县| 临朐县| 瑞金市| 佛山市| 重庆市| 浦北县| 扬中市| 惠来县|