聯級選擇器(仿element-ui),不過我用的是jq寫的!
阿新 • • 發佈:2019-01-10
在做元件之前,一般我都是把HTML結構先寫出來的,最終我們需要變成這樣的結構
<div class="cascader-menus"> <ul class="menus"> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> </ul> <ul class="menus"> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> </ul> <ul class="menus"> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> <li>文字</li> </ul> </div>
然後是樣式:
/*這裡採用浮動是為了讓寬度自適應*/ .cascader-menus{ float: left; font-size: 0; border: 1px #ccc solid; } /*佈局用的inline-block,並且溢位會有滾動條*/ .cascader-menus .menus{ display: inline-block; min-width: 160px; height: 204px; overflow-y: auto; border-right: 1px #ccc solid; } .cascader-menus .menus:last-child{ border-right: none; } .cascader-menus .menus li{ font-size: 14px; padding: 0 10px; line-height: 30px; height: 30px; } .cascader-menus .menus li:hover { cursor: pointer; background-color: #eee; } /*點選的時候需要加的樣式*/ .cascader-menus .menus li.active { background-color: #eee; }
資料結構(直接從element-ui複製的):
var lists = [ { value: 'zhinan', label: '指南', children: [ { value: 'shejiyuanze', label: '設計原則', children: [{ value: 'yizhi', label: '一致' }, { value: 'fankui', label: '反饋' }, { value: 'xiaolv', label: '效率' }, { value: 'kekong', label: '可控' }] }, { value: 'daohang', label: '導航', children: [ { value: 'cexiangdaohang', label: '側向導航' }, { value: 'dingbudaohang', label: '頂部導航' } ] } ] }, { value: 'zujian', label: '元件', children: [{ value: 'basic', label: 'Basic', children: [{ value: 'layout', label: 'Layout 佈局' }, { value: 'color', label: 'Color 色彩' }, { value: 'typography', label: 'Typography 字型' }, { value: 'icon', label: 'Icon 圖示' }, { value: 'button', label: 'Button 按鈕' }] }, { value: 'form', label: 'Form', children: [{ value: 'radio', label: 'Radio 單選框' }, { value: 'checkbox', label: 'Checkbox 多選框' }, { value: 'input', label: 'Input 輸入框' }, { value: 'input-number', label: 'InputNumber 計數器' }, { value: 'select', label: 'Select 選擇器' }, { value: 'cascader', label: 'Cascader 級聯選擇器' }, { value: 'switch', label: 'Switch 開關' }, { value: 'slider', label: 'Slider 滑塊' }, { value: 'time-picker', label: 'TimePicker 時間選擇器' }, { value: 'date-picker', label: 'DatePicker 日期選擇器' }, { value: 'datetime-picker', label: 'DateTimePicker 日期時間選擇器' }, { value: 'upload', label: 'Upload 上傳' }, { value: 'rate', label: 'Rate 評分' }, { value: 'form', label: 'Form 表單' }] }, { value: 'data', label: 'Data', children: [{ value: 'table', label: 'Table 表格' }, { value: 'tag', label: 'Tag 標籤' }, { value: 'progress', label: 'Progress 進度條' }, { value: 'tree', label: 'Tree 樹形控制元件' }, { value: 'pagination', label: 'Pagination 分頁' }, { value: 'badge', label: 'Badge 標記' }] }, { value: 'notice', label: 'Notice', children: [{ value: 'alert', label: 'Alert 警告' }, { value: 'loading', label: 'Loading 載入' }, { value: 'message', label: 'Message 訊息提示' }, { value: 'message-box', label: 'MessageBox 彈框' }, { value: 'notification', label: 'Notification 通知' }] }, { value: 'navigation', label: 'Navigation', children: [{ value: 'menu', label: 'NavMenu 導航選單' }, { value: 'tabs', label: 'Tabs 標籤頁' }, { value: 'breadcrumb', label: 'Breadcrumb 麵包屑' }, { value: 'dropdown', label: 'Dropdown 下拉選單' }, { value: 'steps', label: 'Steps 步驟條' }] }, { value: 'others', label: 'Others', children: [{ value: 'dialog', label: 'Dialog 對話方塊' }, { value: 'tooltip', label: 'Tooltip 文字提示' }, { value: 'popover', label: 'Popover 彈出框' }, { value: 'card', label: 'Card 卡片' }, { value: 'carousel', label: 'Carousel 走馬燈' }, { value: 'collapse', label: 'Collapse 摺疊面板' }] }] }, { value: 'ziyuan', label: '資源', children: [{ value: 'axure', label: 'Axure Components' }, { value: 'sketch', label: 'Sketch Templates' }, { value: 'jiaohu', label: '元件互動文件' }] }, {"value": 1, label: 'xxx'}, ]
然後是JS:
//建構函式
function Cascader(id,data,fn){
//把建立好的“聯級選擇器”插入到哪個元素內
this.$box = $("#"+id);
//data: 是要填充的資料
this.init(data);
//對外提供的介面函式
this.clickHandle = fn || function(){};
//最外層的容器,後期需要把createEl()方法建立的內容都插入到這裡面的
this.$wrap = null;
}
Cascader.prototype = {
constructor: Cascader,
init: function(data){
var This = this;
this.$wrap = $("<div class='cascader-menus'></div>")
//建立裡面的元素
this.createEl(data,function($ul){
This.$wrap.append($ul);
This.$box.append(This.$wrap)
});
console.log(data)
},
createEl: function(data,fn) {
var This = this;
//建立完成以後回撥函式
var fn = fn || function(){};
var $ul = $("<ul class='menus'></ul>");
//建立li,並把li插入到ul中
for (var i=0;i<data.length;i++) {
var $li = $("<li>"+ data[i].label +"</li>");
//給每一個Li加點選事件,點選以後顯示子選單,這裡最好採用閉包的形式,不然i傳遞不進去,當然也可以用es6的let(不過這裡沒有bable,瀏覽器會不支援let的,在vue-cli中的話就沒問題了)
(function(i){
$li.click(function(){
$(this).addClass('active').siblings().removeClass('active');
//先需要清除掉後面所有的選單
$ul.nextAll().remove();
if (data[i].children && data[i].children.length) {
//建立子選單
This.createEl(data[i].children,function(ul){
//把建立好的子選單插入到上一個選單的後面
$ul.after(ul);
});
}
//對外提供的點選介面函式,並把資料給傳遞出去
This.clickHandle(data[i]);
})
})(i)
$ul.append($li);
}
//建立完成以後回撥函式
fn($ul)
}
}
使用:
//呼叫
var c1 = new Cascader("box",lists,function(mes){
console.log(mes)
});
這個box就是個<div id="box"></div>