一尤筐、自定義原因
1.項目定制化需求您朽,下拉框的樣式包括滾動條都需要同現(xiàn)有客戶端(QT qml開發(fā))版本保持一致黑界;
2.據(jù)有web前端經(jīng)驗開發(fā)人員告知劳澄,select滾動條樣式不可以改變稍走。后來google了之后發(fā)現(xiàn)是可以的袁翁,采用jquery-nicescroll.js插件,但我并沒有嘗試婿脸,原因有以下兩點粱胜;
3.嵌入Qt的界面,下拉框滾動條只能鼠標滾動狐树,單擊滾動條不能滾動焙压;
4.嵌入Qt的界面,在mainwindow出現(xiàn)滾動條的時候抑钟,打開下拉框的選擇面板的時候涯曲,下拉框選擇面板會錯位;
二味赃、解決方案
簡而言之:采用input ul li標簽實現(xiàn)自定義
如下圖:
示例圖
2.1)遇到的問題
No. | 問題 | 解決方案 | 示例 |
---|---|---|---|
1 | 監(jiān)聽事件對于動態(tài)加載的元素沒有起效掀抹,即使使用jquery的on監(jiān)聽也無效 | 監(jiān)聽靜態(tài)元素,通過on或者off的第二個選擇器參數(shù)心俗,指定到具體監(jiān)聽的元素 | $('body').off('blur' , '.select-box .input-box input.ipt-select') |
2 | 同一元素多次添加監(jiān)聽事件傲武,執(zhí)行的時候,事件中的方法會執(zhí)行多次 | 監(jiān)聽事件前城榛,先解綁該事件 | $('body').off('blur' , '.select-box .input-box input.ipt-select').on('blur', '.select-box .input-box input.ipt-select', function () { $(this).parent().siblings('ul').addClass('hide'); }) |
3 | 下拉箭頭click沒有響應(yīng)下拉框展示隱藏事件 | 因為下拉箭頭同input響應(yīng)click的事件相同揪利,因此將箭頭的css鼠標事件透傳 | .select-box .input-box span{pointer-events: none;} |
2.2)具體代碼
2.2.1)css代碼
/* css變量定義 */
:root{
--g-Width-input: 229px; /*輸入框、搜索框?qū)挾?/
--g-height-input: 22px; /*輸入框狠持、搜索框高度*/
--g-color-bg-input_nor: #2d2e30; /*控件公用顏色--輸入框疟位、搜索框、背景--nor狀態(tài)--背景色*/
--g-color-bg-input_hov: #232426;
--g-color-border_dow: 1px solid #1690f5; /*控件公用顏色--邊框--dow狀態(tài)--顏色*/
--g-radius-input: 2px; /*輸入框喘垂、搜索框圓角半徑*/
--g-color-border_nor: 1px solid #424447; /*控件公用顏色--邊框--nor狀態(tài)--顏色*/
--g-color-border_dow: 1px solid #1690f5;
--g-color-bg_hov:#1690f5;/*控件公用顏色--控件背景--hor狀態(tài)--底色*/
--g-color-b-text:#b5b5b5;
--g-color-w-border_modal:#fff;
}
input[type="number"],
input[type="text"],
input[type="password"],
textarea.form-control {
font-size: 12px;
background-color: var(--g-color-bg-input_nor);
color: var(--g-color-b-text);
width: var(--g-Width-input);
height: var(--g-height-input);
line-height: 28px;
padding: 0px 6px;
border: var(--g-color-border_nor);
/* border-radius: 0px; */
border-radius: var(--g-radius-input);
}
input[type="number"]:hover,
input[type="text"]:hover,
input[type="text"]:hover +.search-icon,
textarea.form-control:hover{
background-color: var(--g-color-bg-input_hov);
}
input[type="number"]:focus,
input[type="text"]:focus{
background-color: var(--g-color-bg-input_hov);
border: var(--g-color-border_dow);
}
input:focus {
outline: none;
}
input[type="number"][disabled],
input[type="text"][disabled],
.form-control[disabled],
input[type="text"].disabled {
background-color: transparent;
color: var(--g-color-b-text);
border: var( --g-color-border_nor);
cursor: default;
}
input:-webkit-autofill {
-webkit-box-shadow: 0 0 0px 1000px var(--g-color-bg-input_nor) inset !important;
-webkit-text-fill-color: var(--g-color-b-text);
}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none !important;
margin: 0;
}
/* select框自定義樣式 */
.select-box {
position: relative;
width: var(--g-Width-input);
display: inline-block;
}
.select-box .input-box{
position: relative;
width: 100%;
}
.select-box .input-box .icon-box{
position: relative;
right: 18px;
}
.select-box .input-box input.ipt-select{
width: 100%;
}
.select-box .input-box input.ipt-select:focus{
background-color: var(--g-color-bg-input_hov);
border: var(--g-color-border_dow);
}
.select-box .input-box span{
pointer-events: none;
}
.select-box .input-box .icon-box{
position: absolute;
right: 5px;
top: 1px;
}
.select-box .input-box .icon-box i{
font-size: 14px;
font-weight: 1000;
transform: scale(0.65);
-webkit-transform: scale(0.75);
display: inline-block;
}
.select-box ul.select{
position: absolute;
background-color: var(--g-color-bg-input_hov);
border: var(--g-color-border_dow);
height: auto;
width: 100%;
max-height: 274px;
min-width: 152px;
top: 22px;
left: 0px;
z-index: 99;
}
.select-box ul.select > li{
font-size: 12px;
height: 22px;
line-height: 22px;
padding: 0px 6px 1px;
text-align: left;
}
.select-box ul.select > li.selected,
.select-box ul.select > li[selected]{
background-color: var(--g-color-bg_hov);
color: var(--g-color-w-border_modal);
}
.select-box ul.select > li:hover{
background-color: var(--g-color-bg_hov);
color: var(--g-color-w-border_modal);
}
.vertical-auto.select::-webkit-scrollbar { /*select滾動條對應(yīng)的寬度 */
width: 5px;
}
2.2.2)html代碼
<!--使能的下拉框-->
<div class="select-box">
<ul class="select hide vertical-auto">
<li value="0">蘋果</li>
<li value="1">香蕉</li>
<li value="2">橘子</li>
<li value="3">梨</li>
</ul>
</div>
<!--不使能的下拉框-->
<div class="select-box" disabled>
<ul class="select hide vertical-auto">
<li value="0">蘋果</li>
<li value="1">香蕉</li>
<li value="2">橘子</li>
<li value="3">梨</li>
</ul>
</div>
2.2.2)js代碼
/**
* @description: 下拉框賦默認值,document ready的時候甜刻,需要調(diào)用該方法初始化
* @param {*} dom $(document.documentElement)
*/
function initOptionSelect($dom){
// 添加input框
let selects = $dom.find('.select-box');
for(let i = 0; i < selects.length; i++) {
let $select = $(selects[i]);
if($select.children('.input-box').length === 0) {
// 添加不使能的input
if($select.attr('disabled')) {
$select.prepend(
`<div class="input-box">
<input type="text" class="ipt-select" readonly="readonly" disabled>
<span class="icon-box"><i class="icon iconfont icon-arrow-down"></i></span>
</div>`
);
} else {
// 添加使能的input
$select.prepend(
`<div class="input-box">
<input type="text" class="ipt-select" readonly="readonly">
<span class="icon-box"><i class="icon iconfont icon-arrow-down"></i></span>
</div>`
);
}
} else {
// select已經(jīng)有input了,不需要再添加
}
}
boundEventFun();
// 默認選中第一條記錄
let uls = $dom.find('.select-box ul.select');
for(let i = 0; i < uls.length; i++) {
selectLiChange($(uls[i]).find('li:first'));
}
}
/**
* @description: 綁定自定義下拉框事件
* 1)想要監(jiān)聽動態(tài)生成元素的事件正勒,可以綁定靜態(tài)元素得院,再在on或者off中添加需要監(jiān)聽元素的選擇器即可
* 2)如果初始化多次走到boundEventFun事件,會導(dǎo)致該元素監(jiān)聽多次章贞,
* 即監(jiān)聽事件中的方法會走多次祥绞,防止這種事情發(fā)生,應(yīng)該在綁定監(jiān)聽事件前,先解綁一下蜕径。
*/
function boundEventFun(){
// input框失焦两踏,需要隱藏下拉框
$('body').off('blur' , '.select-box .input-box input.ipt-select')
.on('blur', '.select-box .input-box input.ipt-select', function () {
$(this).parent().siblings('ul').addClass('hide');
})
// 下拉框中的input框點擊的時候,需要控制下拉菜單的顯隱
$('body').off('click', '.select-box .input-box input.ipt-select')
.on('click', '.select-box .input-box input.ipt-select', function () {
if ($(this).parent().siblings('ul').hasClass('hide')) {
$(this).parent().siblings('ul').removeClass('hide');
} else {
$(this).parent().siblings('ul').addClass('hide');
}
});
// 觸發(fā)change事件
$('body').off('change', '.select-box .input-box input.ipt-select')
.on('change', '.select-box .input-box input.ipt-select', function () {
$(this).parent().parent().trigger('change');
});
// 監(jiān)聽鼠標滑動在下拉菜單的事件兜喻,清除選中樣式以及屬性
$('body').off('mousemove', '.select-box ul.select')
.on('mousemove', '.select-box ul.select', function () {
$(this).children().removeClass('selected');
$(this).children().removeAttr('selected');
});
// 監(jiān)聽鼠標選中某個li的事件
$('body').off('mousedown', '.select-box ul.select > li')
.on('mousedown', '.select-box ul.select > li', function () {
selectLiChange($(this), true);
})
}
/**
* @description: 下拉框賦指定值
* @param {*} dom 下拉框DOM元素 jquery對象
* @param {*} value 默認值
*/
function setSelDefValue($dom, value) {
if (value !== null && value !== '' && value !== undefined) {
// 選中下拉框指定的一項
selectLiChange($dom.find(`li[value=${value}]`), true);
} else {
// 默認選中下拉框第一項
selectLiChange($dom.find("li:first"));
}
}
/**
* @description: li select狀態(tài)發(fā)生變化梦染,需要改變input值
* @param {*} $this li
* needTriggerChange: 是否需要觸發(fā)change信號
*/
function selectLiChange($this, needTriggerChange = false) {
// 下拉框賦值
let $select = $this.parent().parent('.select-box');
$select.attr('value', $this.attr('value'));
$select.val($this.attr('value'));
// 設(shè)置下拉框的selectedIndex
let lis = $select.find('li');
let selectedIndex = 0;
for(let i = 0; i < lis.length; i++) {
let li = lis[i];
if($(li).attr('value') === $this.attr('value')) {
selectedIndex = i;
break;
}
}
$select.prop('selectedIndex', selectedIndex);
// option添加select類
$this.siblings().removeClass('selected');
$this.siblings().removeAttr('selected');
$this.addClass('selected');
$this.attr('selected', 'selected');
// input框賦值
let $input = $this.parent('.select').siblings('.input-box').find('input');
if($input.val() + '' !== $this.attr('value') + '') {
if(needTriggerChange) {
$select.trigger('change');
}
}
$input.val($this.text());
// 隱藏下拉框
$this.parent('.select').addClass("hide");
}
三、教訓(xùn)總結(jié)
1.因為此次項目中【一虹统、自定義原因】中的問題弓坞,都是在完全開發(fā)完成之后才發(fā)現(xiàn),無論如何想到共通化的修改车荔,帶來的改動量以及風(fēng)險都是很大的。
2.因此戚扳,如果界面定制化極強的開發(fā)忧便,下拉框慎重考慮,采用自定義的不要采用html自帶標簽select帽借。就目前而言是這樣珠增,將來某天標簽發(fā)生變化了另說。