可輸入/選擇的下拉框 -- 異步編程

版權聲明:本文爲博主原創文章,如要轉載或者其餘合做請郵件告知我將會在24小時內回覆,郵箱:lengroubao@163.com

在實際開發開發中咱們會用到各類瀏覽器、HTML、JS等提供的原生的組件/接口,可是這樣並不必定知足咱們的要求,因此咱們須要本身寫一些咱們須要的組件。 日常咱們會常常用`select` 標籤作下拉選項,不過這個只能選擇不能手動輸入,固然網上也有很強大的select2插件,若是隻要輸入和選擇兩個功能的話那麼強大的功能並非咱們須要的。這篇文章咱們就來寫一個簡單實用的selectjavascript

需求css

需求很簡單咱們要作的是兩個功能 輸入和下拉選擇,爲了交互體驗更好,咱們須要作動畫和事件。保證交互的流暢。並且咱們還須要作一些簡單的驗證來檢測非法輸入。html

交互vue

首先,咱們要先明白要寫那些事件,經過以前的gif 咱們能夠看到 一共有三個事件,獲取焦點,焦點事情,點擊事件。 除了事件,還須要作一些過分,若是對兼容性沒有嚴格要求的話(IE低版本)過分用CSS就行了。若是對兼容性有嚴格要求那麼就用JS來寫。這裏的是用CSS3的 `transition` 來作一個0.3秒的過渡java

驗證jquery

除了交互還要驗證是否輸入了非法字符,這裏最合適的是用正則表達式來作,咱們這個例子是驗證正整數 `/^[1-9]\d*$/` 若是是要驗證郵箱`/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/` 驗證只能輸入數字和英文的 `/^[0-9a-zA_Z]+$/` 若是不會正則表達式能夠網上百度,基本上你須要的表達式都能查到。web

具體實現正則表達式

知道要作什麼了 大家就直接上代碼吧,這裏JS是重點,全部我先貼html結構和JS,CSS最後放。HTML結構編程

<div class="canInpSelection">
	<input type="text" class="canInp" name="">
	<ul class="select" data-height="">
		<li data-value='1'>1</li>
		<li data-value='2'>2</li>
		<li data-value='3'>3</li>
		<li data-value='4'>4</li>
	</ul>
</div>

  這裏的li列表能夠寫死能夠動態渲染。 data-value是用來存數據的,好比數據的ID或者其餘的什麼。 data-height是用來存ul的高度的,主要是過分動畫須要瀏覽器

JS 注意 這裏依賴JQ的選擇器和data()方法 能夠直接用百度的CDN

<script type="text/javascript" src="https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/js/lib/jquery-1.10.2_d88366fd.js"></script>

 

獲取焦點事件(focus)

這個事件的邏輯是 獲取焦點->若是用戶還沒輸入那麼把輸入框清空方便用戶輸入 ->根據列表數計算UL高度存入data-height屬性裏->而後設置高度,CSS會自動出現過分效果

$('body').on('focus ','.canInpSelection',function () {
        var ul =$(this).find('.select')
		if($(this).find('input').val() == 0){
            $(this).find('input').val('')
		}
        if(ul.data('height') == ''){
            var h= ul.find('li').length *25
            ul.data('height',h)
        }
        var ch = ul.css('height')
        var dh = ul.data('height')
        if(ch == '0px'){
            ul.css('height',dh)
        }
    })

  

失去焦點事件(blur)

這裏的邏輯很簡單 若是用戶沒有輸入就設置默認值0,不然就判斷,而後`異步`執行關閉下拉事件。

$('body').on('blur ','.canInpSelection',function () {
        var ul =$(this).find('.select')
        var val = $(this).find('input').val()
        if(val== ''){
            $(this).find('input').val('0')
        }else{
        	var ex = /^[1-9]\d*$/;
			if(!ex.test(val)){
				$(this).find('input').val('0')
				// tips.error('請輸入正整數')
				alert('請輸入正整數')
			}
        }
        setTimeout(function () {
            ul.css('height',0)
        },100)
    })

  

點擊事件(click)

點擊事件就是賦值加關閉

$('body').on('click ','.select li',function () {
		var value = $(this).data('value')
		$(this).parent().prev().val(value)
		$(this).parent().css('height','0')
	})

  

解BUG-異步編程

在事情焦點事件裏最後的關閉必定要用異步來作(setTimeout),不然會出BUG,由於JS是單線程的,必須先執行完blur才能執行click,可是執行blur的時候會關閉UL,致使click沒法觸發(由於咱們這裏有300毫秒的過分因此會有一部分能觸發click一部分不能)。爲了保證交互 那段關閉UL的代碼也必須存在,全部只能用異步來作。 等個100毫秒,在關閉,在這100毫秒裏足夠JS處理完click的事件了。 有興趣的同窗能夠試試不用異步會發生什麼,或者將100毫秒縮短到1毫秒? 若是對異步感興趣的同窗能夠百度「js 異步編程」。之後我也會寫一篇關於異步的博文。

 

組件化

對於組件化我以爲要根據實際工做環境來講: 若是用框架的能夠用框架的方式來,好比NG的directive或者vue的directive之類的。 若是不用框架用了underscore之類的工具庫,也能夠用_.template來寫通用的。 若是都不用,也能夠用面向對象的方式抽出來。 這個組件化,根據實際開發環境來,仁者見仁智者見智。 若是 要寫成組件的話,正則表達式最好做爲參數傳進去。我這裏只提供思路,並不難。

CSS

其實CSS沒啥 能夠根據本身公司的風格隨便改。這裏最主要的就是下面這段CSS

-webkit-transition: height ease-out .3s;
         transition: height ease-out .3s;

  transition height 就是根據height的編程作過分 用時300毫秒。 值得注意的是 transition 所根據的屬性必須是具體值,好比auto就不能夠。並且這個元素也必須存在,否則也不會有效果。 下面是完整CSS

div,ul,li,input{
		box-sizing: border-box;
	}
	ul{
		list-style-type: none;
	}
	.canInpSelection{
		position: relative;
		width: 200px;
	}
	.canInp{
	    width: 100%;
	    height: 34px;
	    padding: 6px 12px;
	    font-size: 14px;
	    line-height: 1.42857143;
	    color: #555;
	    background-color: #fff;
	    background-image: none;
		border-color: #ddd;
	    border: 1px solid #ccc;
	    border-radius: 4px;
	    -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
	    box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
	    -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
	    -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
	    transition: border-color ease-in-out;
	    box-shadow: none;
    	-webkit-box-shadow: none;
	    -webkit-tap-highlight-color: rgba(0,0,0,0);
	}
	.select{
		position: absolute;
         top: 33px;
         left: 0px;
         right: 0px;
         background-color: #fff;
         background-image: none;
         z-index: 10;
         text-align: left;
         height:0;
		 overflow: hidden;
         -webkit-transition: height ease-out .3s;
         transition: height ease-out .3s;
         border-radius: 0 0 5px 5px;
         padding: 0;
         margin: 0;
     }
     .select li{
         height: 25px;
         line-height: 25px;
		 cursor: pointer;
         border: 1px solid #ccc;
		 border-top: 0;
		 border-bottom: 0;
         width: 100%;
         padding-left: 10px;
     }
     .select li:last-child{
		 border-bottom:1px solid #ccc;
	 }
     .select li:first-child{
         border-top:1px solid #ccc;
     }

  

總結

縱觀整個組件,思路理清楚了其實並不難,我以爲最有意思的就是用`setTimeout` 來作異步處理了。

相關文章
相關標籤/搜索