国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

徒手擼UI之Cascader

junnplus / 2081人閱讀

摘要:但是如果一剎那我不想選江疏影了,我想選張雨綺因為胸大,首先我要從霍思燕換到高圓圓,然后轉到張雨綺,選中展示出來,這時候就要先刪除霍思燕,然后把高圓圓和張雨綺進來。

QingUI是一個UI組件庫
目前擁有的組件:DatePicker, TimePicker, Paginator, Tree, Cascader, Checkbox, Radio, Switch, InputNumber, Input
ES6語法編寫,無依賴
原生模塊化,Chrome63以上支持,請開啟靜態服務器預覽效果,靜態服務器傳送門
采用CSS變量配置樣式
辛苦造輪子,歡迎來github倉庫star:QingUI
寫在前面

去年年底項目中嘗試著寫過一個分頁的Angular組件,然后就有了寫QingUI的想法

過程還是非常有意思的

接下來我會用幾篇文章分別介紹每個組件的大概思路,請大家耐心等待

這一篇介紹Cascader級聯選擇器

點個star就是對我最好的支持

repo: QingUI
少廢話,先上圖

數據

既然是級聯選擇器,數據肯定是樹形結構,像這樣

const data = [
    {
        label: "霍思燕",
        sub: [
            {
                label: "江疏影",
            },
            {
                label: "倪妮",
            },
        ],
    },
    {
        label: "高圓圓",
        sub: [
            {
                label: "張雨綺",
            },
            {
                label: "宋佳",
            },
        ],
    },
];

你猜我最喜歡哪位女明星 :)

而且用戶點到哪一個label上,就呼出下一級列表

那么問題來了,我怎么知道我當前在哪一級,又在哪一個分支?

所以我需要給每一個分支做標記,點到哪一個label上,就取出標記,該標記能指引我找到對應的數據分支

我的方法是這樣的,新建一個字段queue,字段值是一個字符串形式的數字,位數表示當前是第幾級,數字表示當前是第幾個分支

比如說queue = 131;,表示當前在第一個分支下面的第三個分支下面的第一個分支

buildQueue(data, queue = "") {
    for (let i = 0; i < data.length; i++) {
        const item = data[i];
        const sub = item.sub;
        const newQueue = `${queue}${i}`;
        item[this.queue] = newQueue;
        if (sub) {
            this.buildQueue(sub, newQueue);
        }
    }
}

字段名其實我并沒有用queue,因為有可能已經被占用,我用的是時間戳組成的hash值,所以賦值的時候要寫成item[this.queue] = newQueue;

渲染的時候給DOM元素加一個data-v="${item[this.queue]}就行了

那么怎么讀呢?

這些數字其實就是數組的索引,加一個遞歸搞定

findSubByQueue(data, queue) {
    const n = Number.parseInt(queue.charAt(0));
    for (let i = 0; i < data.length; i++) {
        if (i === n) {
            if (queue.length > 1) {
                return this.findSubByQueue(data[i].sub, queue.slice(1));
            } else {
                return data[i].sub;
            }
        }
    }
}
事件

級聯肯定要支持點擊和懸浮兩種事件觸發機制

所以我用this.eventType來保存事件類型,其實兩種事件大部分代碼是可以復用的

for (let i = 0; i < $trunks.length; i++) {
    const $trunk = $trunks[i];
    const v = $trunk.dataset.v;
    const label = $trunk.querySelector(".label").innerHTML;
    const CL = $trunk.classList;
    $trunk.addEventListener(this.eventType, function(event) {
        event.stopPropagation();
        // 遍歷清除trunk的active
        self.removeTrunkActive($trunks);
        // 當前trunk變成active
        CL.add("active");
        // 構建路徑
        self.buildPath(v.length, label, false);
        // 找到子數據
        const sub = self.findSubByQueue(self.data, v);
        // 填充子board
        $subBoard.innerHTML = self.renderCascade(sub);
        // 添加事件
        self.$rowEvent($subBoard);
    });
}

注釋也寫的很清楚,首先是一個高亮的處理,然后要把當前路徑保存下來,通過queue找到子數據,然后渲染出來,最后給子節點添加事件

要知道,分支可以分為兩種,一種是下面還有分支,我把它稱作trunk,另一種是末梢,下面沒有分支了,我把它稱作leaf

點擊很容易,只給trunk添加事件就可以了

但是懸浮,leaf也要有事件,就是把之前的高亮和子數據清空

if (this.trigger === "hover") {
    for (let i = 0; i < $leafs.length; i++) {
        $leafs[i].addEventListener("mouseenter", function() {
            self.removeTrunkActive($trunks);
            $subBoard.innerHTML = "";
        });
    }
    // 離開curtain
    this.$curtain.addEventListener("mouseleave", function() {
        self.removeTrunkActive(self.$trunks);
        self.$subBoard.innerHTML = "";
    });
}

那么怎么選中呢?

到leaf才是一個完整的路徑,所以leaf特殊處理,無論是什么事件,點擊leaf選中,把路徑渲染出來

路徑

保存路徑是一個動態的過程

因為我可能查看了某一個分支,然后又查看另一個分支,最終選中了別的分支

所以保存路徑要根據路徑的長度和當前級別來確定是添加還是刪除

比如我現在在江疏影這里,還沒有選中,那么當前是第二級,路徑里只保存了霍思燕,如果我選中,那么簡單,直接把江疏影push到數組里,展示出來。但是如果一剎那我不想選江疏影了,我想選張雨綺(因為胸大),首先我要從霍思燕換到高圓圓,然后轉到張雨綺,選中展示出來,這時候就要先刪除霍思燕,然后把高圓圓和張雨綺push進來。

buildPath(level, label, render) {
    if (this.path.length < level) {
        // 往下選擇,直接push
        this.path.push(label);
    } else {
        // 退回選擇,根據退回長度刪除path元素,再push
        this.path = [...this.path.slice(0, level - 1), label];
    }
    if (render) {
        this.renderPath();
    }
}
搜索

突發奇想,我又想加一個搜索功能

比如說我現在搜集了好幾千個女明星,打亂格式化成樹形數據,那我選擇起來可就困難了,難道每一個分支都查看一遍嗎?如果有搜索,我只要搜張雨綺,所有包含張雨綺的級聯都展示出來,是不是方便很多!

看起來很復雜的樣子

其實,換一個思路,初始化的時候就把所有的路徑都遍歷出來,緩存在一個數組里,搜索的時候只要檢索這些字符串有沒有張雨綺,是不是回到我們熟悉的字符串操作上來了?

遍歷所有路徑

iterateAllPath() {
    const self = this;
    let temp = [];
    const data = pathPush([...this.data]);
    function pathPush(data, arr = []) {
        for (const item of data) {
            item.path = [];
            // 將路徑存入item中的數組
            item.path.push(...arr, item.label);
        }
        return data;
    }
    function recursive(data) {
        for (const item of data) {
            const sub = item.sub;
            if (sub) {
                // 將下一層放入temp
                temp.push(...pathPush(sub, item.path));
            } else {
                // 沒有下一層則路徑結束
                self.pathPool.push(item.path.join(self.seperator));
            }
        }
        if (temp.length) {
            // 重新初始化
            data = temp;
            temp = [];
            recursive(data);
        }
    }
    recursive(data);
}
for (const item of this.pathPool) {
    const match = item.match(reg);
    if (!match) {
        continue;
    }
    result.push(item);
}

別急,還有需求,我想把關鍵詞高亮

比如說我搜張雨綺,所有結果中張雨綺都要高亮

我搜張雨,所有結果中張雨都要高亮

這個也不復雜,用關鍵詞把路徑截成三段,如果關鍵詞在首尾那就截成兩段

這里有一個小問題,如果分隔符與關鍵詞之間有空格,展示結果總是不符合預期

后來才發現,如果標簽內第一個字符是空格,空格會被忽略

所以還需要小小的處理一下

const reg = new RegExp(value, "i");
for (const item of this.pathPool) {
    const match = item.match(reg);
    if (!match) {
        continue;
    }
    result.push(item);
    const index = match.index;
    let [left, center, right] = [item.slice(0, index), match[0], item.slice(index + value.length)];
    // 如果標簽內第一個字符是空格,空格會被忽略
    if (right && right.startsWith(" ")) {
        right = ` ${right.trimLeft()}`;
    }
    tpl += `
        
${left ? `${left}` : ""} ${center} ${right ? `${right}` : ""}
`; } if (!tpl) { tpl = "
No Result
"; }
寫在后面

Cascader比較核心的邏輯就在這里了

相較前幾篇文檔,隔的時間有點長,不過Cascader不會讓你失望的

如果覺得QingUI還不錯,點個star激勵一下老夫

repo: QingUI

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95316.html

相關文章

  • 徒手UIDatePicker

    摘要:是一個組件庫目前擁有的組件語法編寫,無依賴原生模塊化,以上支持,請開啟靜態服務器預覽效果,靜態服務器傳送門采用變量配置樣式辛苦造輪子,歡迎來倉庫四月份找工作,求內推,坐標深圳寫在前面去年年底項目中嘗試著寫過一個分頁的組件,然后就有了寫的想法 QingUI是一個UI組件庫目前擁有的組件:DatePicker, TimePicker, Paginator, Tree, Cascader, ...

    zilu 評論0 收藏0
  • 徒手UIPaginator

    摘要:是一個組件庫目前擁有的組件語法編寫,無依賴原生模塊化,以上支持,請開啟靜態服務器預覽效果,靜態服務器傳送門采用變量配置樣式辛苦造輪子,歡迎來倉庫四月份找工作,求內推,坐標深圳寫在前面去年年底項目中嘗試著寫過一個分頁的組件,然后就有了寫的想法 QingUI是一個UI組件庫目前擁有的組件:DatePicker, TimePicker, Paginator, Tree, Cascader, ...

    liuhh 評論0 收藏0
  • 徒手UITimePicker

    摘要:是一個組件庫目前擁有的組件語法編寫,無依賴原生模塊化,以上支持,請開啟靜態服務器預覽效果,靜態服務器傳送門采用變量配置樣式辛苦造輪子,歡迎來倉庫四月份找工作,求內推,坐標深圳寫在前面去年年底項目中嘗試著寫過一個分頁的組件,然后就有了寫的想法 QingUI是一個UI組件庫目前擁有的組件:DatePicker, TimePicker, Paginator, Tree, Cascader, ...

    Codeing_ls 評論0 收藏0
  • 徒手UITree

    摘要:是一個組件庫目前擁有的組件語法編寫,無依賴原生模塊化,以上支持,請開啟靜態服務器預覽效果,靜態服務器傳送門采用變量配置樣式辛苦造輪子,歡迎來倉庫四月份找工作,求內推,坐標深圳寫在前面去年年底項目中嘗試著寫過一個分頁的組件,然后就有了寫的想法 QingUI是一個UI組件庫目前擁有的組件:DatePicker, TimePicker, Paginator, Tree, Cascader, ...

    2i18ns 評論0 收藏0
  • 徒手框架--高并發環境下的請求合并

    摘要:我們就可以將這些請求合并,達到一定數量我們統一提交。總結一個比較生動的例子給大家講解了一些多線程的具體運用。學習多線程應該多思考多動手,才會有比較好的效果。地址徒手擼框架系列文章地址徒手擼框架實現徒手擼框架實現 原文地址:https://www.xilidou.com/2018/01/22/merge-request/ 在高并發系統中,我們經常遇到這樣的需求:系統產生大量的請求,但是這...

    劉東 評論0 收藏0

發表評論

0條評論

junnplus

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<