建指南:深入解析 `cy.collection()` 的用法與實(shí)現(xiàn)原理)
數(shù)據(jù)可視化【免費(fèi)下載鏈接】cytoscape.jsGraph theory (network) library for visualisation and analysis項(xiàng)目地址https://gitcode.com/gh_mirrors/cy/cytoscape.js點(diǎn)擊查看免費(fèi)下載cy.collection()是 cytoscape.js 中用于構(gòu)建元素集合collection的核心方法。本文以官方文檔 documentation/md/core/collection.md 為骨架結(jié)合倉(cāng)庫(kù)源碼 src/core/search.mjs、src/collection/index.mjs 及測(cè)試用例 test/collection-building-and-filtering.mjs系統(tǒng)講解該 API 的四種調(diào)用形式、removed與unique選項(xiàng)的語(yǔ)義、集合運(yùn)算如union/merge的底層機(jī)制并給出可直接運(yùn)行于實(shí)際項(xiàng)目中的代碼示例。cy.collection()是什么在 cytoscape.js 中集合collection是節(jié)點(diǎn)node和邊edge的容器支持鏈?zhǔn)秸{(diào)用、批量操作與集合運(yùn)算。cy.collection()是 core 實(shí)例提供的集合工廠專門用于按需構(gòu)建、累積和維護(hù)集合對(duì)象。官方文檔對(duì)其定位只有一句話This function is useful for building up collections此函數(shù)對(duì)逐步構(gòu)建集合非常有用。但它背后的實(shí)際行為遠(yuǎn)比一句話豐富。從 src/core/search.mjs 的實(shí)現(xiàn)看cy.collection( eles, opts )會(huì)根據(jù)第一個(gè)參數(shù)的類型走四條不同的分支調(diào)用形式參數(shù)類型返回結(jié)果cy.collection()無(wú)參數(shù)返回一個(gè)空的集合new Collection( this )cy.collection( selector )字符串等價(jià)于cy.$( selector )返回圖中匹配選擇器的元素cy.collection( eles )元素 / 集合調(diào)用eles.collection()返回對(duì)應(yīng)集合cy.collection( jsonArray, opts )數(shù)組用 JSON 定義新建元素按opts決定是否加入圖其中無(wú)參數(shù)與JSON 數(shù)組兩種形式正是官方文檔兩個(gè)示例所演示的場(chǎng)景也是最常用的構(gòu)建方式。示例一持續(xù)累積被點(diǎn)擊的節(jié)點(diǎn)官方文檔給出的第一個(gè)示例展示如何用一個(gè)集合累積記錄所有被用戶點(diǎn)擊過(guò)的節(jié)點(diǎn)var collection cy.collection(); cy.nodes().on(click, function(e){ var clickedNode e.target; collection collection.union(clickedNode); });這里的關(guān)鍵鏈路是cy.collection()先創(chuàng)建空集合作為累積的起點(diǎn)監(jiān)聽(tīng)所有節(jié)點(diǎn)的click事件e.target是被點(diǎn)擊的節(jié)點(diǎn)元素通過(guò)collection.union(clickedNode)把新點(diǎn)擊的節(jié)點(diǎn)并入集合并將結(jié)果重新賦給collection。union與merge的底層差異union屬于非破壞性集合運(yùn)算返回一個(gè)包含調(diào)用集合與參數(shù)集合全部元素的新集合而源碼中與它共享邏輯的merge則是就地修改調(diào)用集合。在 src/collection/filter.mjs 中merge的實(shí)現(xiàn)要點(diǎn)是使用集合內(nèi)部的map以元素 id 為鍵做去重判斷l(xiāng)et add !map.has( id )僅當(dāng) id 尚未存在時(shí)才把元素追加到this[ this.length ]并更新 map因此重復(fù)merge同一個(gè)元素不會(huì)產(chǎn)生重復(fù)項(xiàng)。同文件末尾的別名聲明src/collection/filter.mjs則展示了union的多個(gè)等價(jià)寫法fn[ u ] fn[ | ] fn[ ] fn.union fn.or fn.add;也就是說(shuō)collection.union(clickedNode)也可以寫成collection.add(clickedNode)、collection.or(clickedNode)甚至collection。開(kāi)發(fā)者可以根據(jù)可讀性選擇任一別名。值得注意這個(gè)示例中的累積模式對(duì)remove事件并不感知。如果某個(gè)節(jié)點(diǎn)已被點(diǎn)擊后從圖中移除union前的舊集合仍持有該元素的引用。若需要嚴(yán)格同步圖狀態(tài)可以配合collection cy.nodes()或使用collection.intersect(cy.elements())過(guò)濾。示例二創(chuàng)建尚未加入圖的元素集合官方文檔的第二個(gè)示例展示了如何用 JSON 數(shù)組直接構(gòu)建一個(gè)已處于removed狀態(tài)的集合var removedCollection cy.collection([{ data: { id: a } }, { data: { id: b } }], { removed: true }); removedCollection.forEach(element { console.log(element.removed()); // true });執(zhí)行結(jié)果是集合中每個(gè)元素的element.removed()都返回true表示這些元素并未出現(xiàn)在圖渲染視圖中只是作為可操作的對(duì)象存在。參數(shù)語(yǔ)義opts.removed與opts.uniquecy.collection( eles, opts )的第二個(gè)參數(shù)支持兩個(gè)選項(xiàng)在 src/core/search.mjs 中被透?jìng)鹘oCollection構(gòu)造函數(shù)opts.removed為true時(shí)新創(chuàng)建的集合元素不會(huì)調(diào)用restore()加入圖保持已移除狀態(tài)不傳或?yàn)閒alse時(shí)元素創(chuàng)建后會(huì)被自動(dòng)恢復(fù)加入圖。opts.unique為true時(shí)構(gòu)造過(guò)程按元素 id 去重重復(fù) id 的元素只保留第一個(gè)。在 src/collection/index.mjs 的構(gòu)造函數(shù)中這兩項(xiàng)的行為可以逐一對(duì)應(yīng)JSON 轉(zhuǎn)元素當(dāng)傳入數(shù)組的首項(xiàng)是普通對(duì)象is.plainObject( elements[0] )且不是已有元素時(shí)會(huì)進(jìn)入createdElements true分支src/collection/index.mjs若 JSON 中未提供data.id會(huì)自動(dòng)用util.uuid()生成唯一 iddata.id util.uuid()若 id 與圖中已有元素或本次列表內(nèi)元素沖突該條 JSON 會(huì)被跳過(guò)continue避免 id 重復(fù)每條 JSON 被包裝成new Element( cy, json, false )注意第三個(gè)參數(shù)false表示暫不恢復(fù)。是否入圖構(gòu)造函數(shù)末尾執(zhí)行if( createdElements !removed ){ this.restore(); }src/collection/index.mjs。這正是removed: true與默認(rèn)行為的唯一分水嶺——只有removed為假時(shí)才會(huì)調(diào)用restore()把元素真正加入圖。去重邏輯在填充內(nèi)部數(shù)組的循環(huán)中if( !unique || !map.has(id) )決定是否收錄該元素unique為true時(shí)同時(shí)維護(hù)_private.map的 id 索引src/collection/index.mjs。實(shí)際應(yīng)用場(chǎng)景removed: true形態(tài)的典型用途包括預(yù)構(gòu)建元素先用 JSON 定義一批元素經(jīng)過(guò)數(shù)據(jù)校驗(yàn)、拓?fù)渑判蚧蜻^(guò)濾后再統(tǒng)一restore()加入圖批量添加把元素集合暫存配合collection.remove()與collection.restore()實(shí)現(xiàn)臨時(shí)隱藏/再次顯示數(shù)據(jù)轉(zhuǎn)移官方文檔 documentation/md/core/add.md 提到若將某核心實(shí)例的元素集合指定到另一個(gè)核心實(shí)例會(huì)創(chuàng)建這些元素的副本從而實(shí)現(xiàn)實(shí)例間的元素遷移。關(guān)于示例代碼的勘誤說(shuō)明官方文檔原示例末尾的forEach回調(diào)中缺少閉合圓括號(hào)寫作};。正確寫法應(yīng)為removedCollection.forEach(element { console.log(element.removed()); // true });forEach來(lái)自集合原型繼承的數(shù)組迭代能力具體實(shí)現(xiàn)在 src/collection/iteration.mjs其行為與原生Array.prototype.forEach一致回調(diào)簽名是( ele, i, eles )。集合對(duì)象的基礎(chǔ)能力通過(guò)cy.collection()得到的對(duì)象是一個(gè)擴(kuò)展了Array.prototype的集合類型。源碼 src/collection/index.mjs 中明確寫道let elesfn Element.prototype Collection.prototype Object.create(Array.prototype);這意味著集合與單個(gè)元素共享同一套原型方法注釋為an element has the same functions as a collection從而支持統(tǒng)一的鏈?zhǔn)秸{(diào)用。圍繞本文主題常用的基礎(chǔ)能力包括長(zhǎng)度與判空src/collection/iteration.mjsvar col cy.collection(); col.length; // 0 col.empty(); // true —— length 0 col.nonempty(); // false取元素src/collection/iteration.mjscol.eq(0); // 第 0 個(gè)元素越界時(shí)返回空集合而非 undefined col.first(); // 首個(gè)元素 col.last(); // 末個(gè)元素判斷元素歸屬src/collection/comparators.mjscollection.contains(node); // 是否包含指定節(jié)點(diǎn)等價(jià)于 has collection.same(other); // 與另一集合的元素是否完全相同 collection.anySame(other); // 是否有交集其中same的實(shí)現(xiàn)包含三重優(yōu)化先比較集合引用再比較長(zhǎng)度最后對(duì)單元素集合比較元素引用全部通過(guò)后再逐個(gè)按 id 查 mapsrc/collection/comparators.mjs。集合運(yùn)算全景union 家族的兄弟方法union并非孤立存在。在 src/collection/filter.mjs 的別名區(qū)可以看到完整的集合運(yùn)算家族它們共同構(gòu)成了構(gòu)建集合的代數(shù)工具fn[ u ] fn[ | ] fn[ ] fn.union fn.or fn.add; // 并集 fn[ \\ ] fn[ ! ] fn[ - ] fn.difference fn.relativeComplement fn.subtract fn.not; // 差集 fn[ n ] fn[ ] fn[ . ] fn.and fn.intersection fn.intersect; // 交集 fn[ ^ ] fn[ () ] fn[ (-) ] fn.symmetricDifference fn.symdiff fn.xor; // 對(duì)稱差集官方文檔 documentation/md/core/batch.md 也將集合構(gòu)建列為批處理場(chǎng)景的典型用法Building collections:eles.union(),eles.difference(),eles.intersection(), etc.。在實(shí)際項(xiàng)目中可以組合這些運(yùn)算完成復(fù)雜篩選例如保存所有被點(diǎn)擊的節(jié)點(diǎn)但排除其中已標(biāo)記為隱藏的節(jié)點(diǎn)var clicked cy.collection(); cy.nodes().on(click, function(e){ var clickedNode e.target; // 并集累積 差集剔除指定 id clicked clicked.union(clickedNode).difference(cy.$(#node-to-exclude)); });測(cè)試用例對(duì)行為的驗(yàn)證倉(cāng)庫(kù)測(cè)試文件 test/collection-building-and-filtering.mjs 對(duì)空集合與merge行為給出了明確的斷言可作為理解cy.collection()行為的佐證空集合test/collection-building-and-filtering.mjscy.collection()初始length 0、eles[0]不存在hasElementWithId(n1)返回false就地合并eles.merge( n1 )后length變?yōu)?1重復(fù)合并已存在的元素不會(huì)增加長(zhǎng)度因?yàn)榘?id 去重空交集test/collection-building-and-filtering.mjscy.$(#n1, #n2).intersect( cy.collection() ).empty()為true驗(yàn)證了空集合參與運(yùn)算時(shí)符合集合代數(shù)預(yù)期。這些斷言與 src/collection/index.mjs 中hasElementWithId、merge的實(shí)現(xiàn)一一對(duì)應(yīng)說(shuō)明本文所述行為均有可重復(fù)驗(yàn)證的測(cè)試保障??偨Y(jié)與注意事項(xiàng)cy.collection()是構(gòu)建、累積集合的入口無(wú)參調(diào)用得到空集合傳選擇器、元素/集合、JSON 數(shù)組時(shí)行為各不相同見(jiàn) src/core/search.mjs。傳入 JSON 數(shù)組時(shí)opts.removed: true可創(chuàng)建不加入圖、處于 removed 狀態(tài)的元素集合省略該選項(xiàng)則元素創(chuàng)建后自動(dòng)restore()入圖src/collection/index.mjs。opts.unique: true按 id 去重id 缺省時(shí)自動(dòng)生成與圖中已有 id 沖突的條目會(huì)被忽略。累積節(jié)點(diǎn)等動(dòng)態(tài)集合場(chǎng)景優(yōu)先組合union/intersection/difference等別名豐富的集合運(yùn)算對(duì)性能敏感、希望避免創(chuàng)建中間對(duì)象時(shí)可使用就地修改的merge/unmerge。集合與元素共享原型方法src/collection/index.mjsforEach、map、filter等迭代能力開(kāi)箱即用且forEach的回調(diào)參數(shù)順序?yàn)? ele, i, eles )。將cy.collection()與集合運(yùn)算配合使用可以構(gòu)建出從點(diǎn)擊選點(diǎn)到臨時(shí)元素管理再到實(shí)例間元素遷移的完整數(shù)據(jù)流是掌握 cytoscape.js 元素管理的基石 API。贊分享數(shù)據(jù)可視化【免費(fèi)下載鏈接】cytoscape.jsGraph theory (network) library for visualisation and analysis項(xiàng)目地址https://gitcode.com/gh_mirrors/cy/cytoscape.js點(diǎn)擊查看免費(fèi)下載相關(guān)推薦cytoscape.js 集合動(dòng)畫(huà)停止指南深入解析 eles.stop() 的參數(shù)、執(zhí)行原理與實(shí)戰(zhàn)用法cytoscape.js 集合動(dòng)畫(huà)停止指南深入解析 eles.stop 的參數(shù)、執(zhí)行原理與實(shí)戰(zhàn)用法 導(dǎo)讀 在 cytoscape.js 中動(dòng)畫(huà)是交互與可視化數(shù)據(jù)可視化cytoscape.js 集合運(yùn)算詳解eles.symmetricDifference對(duì)稱差的用法與實(shí)現(xiàn)原理cytoscape.js 集合運(yùn)算詳解eles.symmetricDifference對(duì)稱差的用法與實(shí)現(xiàn)原理 導(dǎo)讀 本文圍繞 cytoscape.js 元數(shù)據(jù)可視化Cytoscape.js 集合全量匹配 allAre() 方法深度指南語(yǔ)法、實(shí)現(xiàn)原理與實(shí)戰(zhàn)驗(yàn)證Cytoscape.js 集合全量匹配 allAre 方法深度指南語(yǔ)法、實(shí)現(xiàn)原理與實(shí)戰(zhàn)驗(yàn)證 導(dǎo)讀 eles.allAre 是 Cytoscape.js 集合數(shù)據(jù)可視化創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考