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