我的<input />不可能這麼可愛(APP打開有驚喜)

<input /> 標籤是我們日常開發中非常常見的替換元素了,但是最近在刷 whattwg 跟 MDN 的時候發現 跟 <input /> 有很多相關的屬性,選擇器都沒怎麼用過,所以就開篇文章來整理一下一些比較有趣或者實用的知識點。
本篇文章默認大家已經知道 <input /> 標籤的基本用法,不會做過多的基礎說明~

沒想到,這些選擇器居然跟 input ...

到寫文章爲止,根據最新的 drafts 指出,一共有3大類,16種跟 input 相關的選擇。其實都挺有用的,善用它們,會讓我們的用戶體驗更加美好。

下面我們來分享一下這3大類選擇器的作用:

第一類:控制系(Input Control States)

選擇器
作用

:enabled
選擇可使用狀態的 <input /> 元素

:disabled
選擇不可使用狀態的 <input /> 元素

:read-only
選擇不可編輯狀態的元素(不僅僅是 <input /> )

:read-write
選擇可編輯狀態的元素(不僅僅是 <input /> )

:placeholder-shown
選擇 placeholder text 顯示時的元素

:default
選擇在 <button>,<input type="checkbox" />, <input type="radio" />, 以及 <option> 上的默認狀態

第二類:輸出系(Input Value States)

選擇器
作用

:checked
選擇處於選中狀態的 <input type="radio" />

:indeterminate
選擇狀態不確定的表單元素與 <progress>

第三類:偵查系(Input Value-checking)

選擇器
作用

:blank
選擇處於空值時的 <input>,暫未被瀏覽器支持

:valid
選擇驗證通過的表單元素

:invalid
選擇驗證不通過的表單元素

:in-range
選擇處於指定範圍內的 <input />

:out-of-range
選擇不處於指定範圍內的 <input />

:required
選擇必填的表單元素

:optional
選擇選填的表單元素

:user-invalid
選擇用戶輸入但值非法時的 <input />,暫未被瀏覽器支持

可怕,除了選擇器,居然還跟這些屬性有關係
<input> 除了有很多相關的選擇器,結合不同的type還有不同的屬性可以供使用。他們的作用如下:

屬性
作用

maxlength
可輸入的最大長度

minlength
可輸入的最小長度

size
輸入框的長度

readonly
輸入框是否只讀

required
輸入框是否必填

multiple
輸入框是否可以多選

pattern
輸入框驗證規則

min
可輸入的最小值

max
可輸入的最大值

step
輸入框每次的增量

list
輸入框綁定的可選值數據

placeholder
輸入框預選文字

實戰
通過上面的三類說明,我們大致瞭解了 <input /> 標籤的相關信息,但是你們以爲我是來列list的嗎?
當然不是,還有實操啊~

純CSS實現表單提交功能
首先我們來看個效果圖

上面的效果就是一個純CSS實現的表單提交功能,這是怎麼實現的呢?下面我們直接看源碼,然後一步一步地來分拆(不想看的可以直接CV下面的源碼自己做測試~)
<style>
:root {
--error-color: red;
}
.form > input {
margin-bottom: 10px;
}
.form > .f-tips {
color: var(--error-color);
display: none;
}
input[type="text"]:invalid ~ input[type="submit"],
input[type="password"]:invalid ~ input[type="submit"] {
display: none;
}
input[required]:focus:invalid + span {
display: inline;
}
input[required]:empty + span {
display: none;
}
input[required]:invalid:not(:placeholder-shown) + span {
display: inline;
}
</style>
<form class="form" id="form" method="get" action="/api/form">
賬號:
<input data-title="賬號" placeholder="請輸入正確的賬號" pattern="\w{6,10}" name="account" type="text" required />
<span class="f-tips">請輸入正確的賬號</span>
<br />
密碼:
<input data-title="密碼" placeholder="請輸入正確的密碼" pattern="\w{6,10}" name="password" type="password" required />
<span class="f-tips">請輸入正確的密碼</span>
<br />
<input name="button" type="submit" value="提交" />
</form>
複製代碼第一步:寫好基礎結構
首先我們來把基礎結構給寫好,代碼如下:
<style>
:root {
--error-color: red;
}
.form > input {
margin-bottom: 10px;
}
.form > .f-tips {
color: var(--error-color);
display: none;
}
</style>
<form class="form" id="form" method="get" action="/api/form">
賬號:
<input data-title="賬號" placeholder="請輸入正確的賬號" pattern="\w{6,10}" name="account" type="text" required />
<span class="f-tips">請輸入正確的賬號</span>
<br />
密碼:
<input data-title="密碼" placeholder="請輸入正確的密碼" pattern="\w{6,10}" name="password" type="password" required />
<span class="f-tips">請輸入正確的密碼</span>
<br />
<input name="button" type="submit" value="提交" />
</form>
複製代碼掃一眼,嗯,挺簡單的,都是常用的東西。咦,不對,這個 pattern 是什麼東西?
在這裏我們重點分享下 pattern 這個屬性,這是一個用來驗證 input[value] 是否合法的屬性,裏面的內容就是匹配value的,語法便是正則的語法,例子如下:
<label>
<!--
當前pattern的內容就是驗證input[name="part"]的value的,其規則如同裏面的正則一樣,匹配input[name="part"]的value是否是一個數字+3個大寫字母
-->
<input pattern="[0-9][A-Z]{3}" name="part" />
</label>
複製代碼當然,不同的 input[type] 也會默認帶有相應的 pattern ,例如 input[type="email"] 就是默認匹配了以下規則:br/>/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
複製代碼第二步:重點功能
input[type="text"]:invalid ~ input[type="submit"],
input[type="password"]:invalid ~ input[type="submit"] {
display: none;
}
input[required]:focus:invalid + span {
display: inline;
}
input[required]:empty + span {
display: none;
}
input[required]:invalid:not(:placeholder-shown) + span {
display: inline;
}
複製代碼上面便是核心交互的實現。
首先第一個class就是保證了在兩個輸入框不通過的時候隱藏,就是當輸入框值爲空或者不符合驗證規則,則隱藏提交按鈕。
第二個,第三個class則是控制當用戶在輸入框輸入內容時,如果不符合驗證規則,則顯示錯誤信息,否則則隱藏。
第四個class則是用過 placeholder 是否存在來控制錯誤信息的顯隱,如果 placeholder 不顯示,則證明用戶正在輸入,錯誤信息則根據用戶輸入的值來判斷是否顯隱,否則則隱藏。
狀態切換
上面我們有提到一個選擇器 :indeterminate ,這個是用於選擇狀態不確定的表單元素與 <progress> ,玩過掃雷的人都知道,右擊除了可以選擇紅旗,還可以選擇問號,就是選中,但不確定;又跟 promise 的 pending 狀態類型,介於 resolve 與 reject 之間。
多了 :indeterminate 會給我們帶來很多很有趣的體驗。
首先我們來看看它的使用案例。
基礎使用法
先看效果

代碼如下:
<style>
body {
background: #333;
color: #fff;
padding: 20px;
text-align: center;
}
input {
margin-right: .25em;
width: 30px;
height: 30px;
}
label {
position: relative;
top: 1px;
font-size: 30px;
}
</style>
<form>
<input type="checkbox" id="checkbox">
<label for="option">點擊左邊</label>
</form>
<script>
'use strict';
checkbox.addEventListener('click', ev => {
if (ev.target.readOnly) {
ev.target.checked = ev.target.readOnly = false;
} else if (!ev.target.checked) {
ev.target.readOnly = ev.target.indeterminate = true;
};
});
</script>
複製代碼這裏面其實沒有什麼複雜的實現,只是做了箇中間態的判斷,就非常輕鬆的實現了radio的三種狀態切換。
秀到頭皮發麻法
先看效果

(此天秀效果來自於 Ben Szabo 的 codepen,有興趣的可以仔細研究下,我何時纔能有大佬這麼優秀,嚶嚶嚶~)
輸入框綁定的可選值
先看效果

其實代碼很簡單:
<input type="text" list="names" multiple />
<datalist id="names">
<option value="kris">
<option value="陳大魚頭">
<option value="深圳金城武">
</datalist>

<input type="email" list="emails" multiple />
<datalist id="emails">
<option value="[email protected]" label="kris">
<option value="[email protected]" label="kris">
</datalist>

<input type="date" list="dates" />
<datalist id="dates">
<option value="2019-09-03">
</datalist>
複製代碼這裏原理就是通過 <input list="dates" /> 來綁定需要下拉顯示的數據列表 <datalist id="dates"> 。
那麼當我們要實現輸入聯想的時候,也可以通過修改 <datalist id="dates"> 的子元素來實現,而不是再寫一大堆的操作函數來實現。
總結
其實 <input /> 標籤還有很多有趣的功能是可以挖掘的,不同的類型,結合不同的選擇器與屬性,是可以有更多讓人爲之驚歎的體驗的。如果你有興趣的話,不妨多開開腦洞,親自動手實現一些有趣的功能,或者有什麼有趣的想法也可以在下方給魚頭留言或者加魚頭微信 “krisChans95” 來暢談。
彩蛋
經由掘友跟微友們提醒,才發現一個比較有趣的彩蛋,感覺我這篇文章應該改名爲《震驚,一篇文章居然引發出掘金跟微信的。。。》

如果你、喜歡探討技術,或者對本文有任何的意見或建議,你可以掃描下方二維碼,關注微信公衆號“魚頭的Web海洋”,隨時與魚頭互動。歡迎!衷心希望可以遇見你。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章