您好,登錄后才能下訂單哦!
案例設(shè)定:
創(chuàng)建2個樹控件,左右排列。
使用拖動的方式,將樹節(jié)點(diǎn)從左側(cè)樹控件拖拽的右側(cè)樹控件。
拖拽過程中右側(cè)樹控件要進(jìn)行驗(yàn)證,確認(rèn)是否可以方式拖拽中的節(jié)點(diǎn)。
放置的處理,識別要放置的節(jié)點(diǎn),獲取其信息并動態(tài)創(chuàng)建新的節(jié)點(diǎn)(基于基礎(chǔ)類型進(jìn)行實(shí)例化的過程)。
右側(cè)樹控件內(nèi)(實(shí)例化之后的節(jié)點(diǎn)),同類型節(jié)點(diǎn)間支持拖動排序。
Dojo版本 1.10.3
圖例1:創(chuàng)建2個樹控件,左右排列。
圖例2、3:
使用拖動的方式,將樹節(jié)點(diǎn)從左側(cè)樹控件拖拽的右側(cè)樹控件。
拖拽過程中右側(cè)樹控件要進(jìn)行驗(yàn)證,確認(rèn)是否可以方式拖拽中的節(jié)點(diǎn)。
圖例4
放置的處理,識別要放置的節(jié)點(diǎn),獲取其信息并動態(tài)創(chuàng)建新的節(jié)點(diǎn)(基于基礎(chǔ)類型進(jìn)行實(shí)例化的過程)。
圖例5:拖拽之后的效果
圖例6、7
右側(cè)樹控件內(nèi)(實(shí)例化之后的節(jié)點(diǎn)),同類型節(jié)點(diǎn)間支持拖動排序。
案例代碼:
<!DOCTYPE html> <html > <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link rel="stylesheet" type="text/css" href="../dojo_1.10.3/dijit/themes/claro/claro.css"/> <script type="text/javascript" src="../dojo_1.10.3/dojo/dojo.js" ></script> <script> function makeTree(treedata, rootid, treenodeid, dndSkip , registry, ItemFileWriteStore, TreeStoreModel, dndSource, Tree) { var store2 = new ItemFileWriteStore({data: treedata}); var treeModel = new TreeStoreModel({ store: store2 , query: {"id": rootid} , childrenAttrs: ["children"] }); var tree = new Tree({ model: treeModel, openOnClick: true, showRoot: true, autoExpand: true, persist: false, style: "width:400px;height:500px;" }, treenodeid); tree.startup(); var foo = new dndSource(tree, {betweenThreshold: 5, singular: true}); foo.checkItemAcceptance = function (target, source, position) { if (dndSkip) return false; var flag = false;//判斷是否可以拖拽 var tar_type = registry.byNode(target.parentNode).item.type[0]; var src_type = source.tree.selectedItem.type[0]; flag = (tar_type === src_type + '_sp' && position === "over") || (tar_type === src_type && position !== "over"); return flag; }; // dijit/tree/dndSource.js 源碼中明確提及要求開發(fā)者覆蓋此方法。 foo.itemCreator = function (nodes) { var rst = new Array(); for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; var id = '' + Math.floor(Math.random() * 1000); var item = registry.byNode(node).item; var rst2 = {id: id, name: item.name + "(" + id + ")", type : item.type}; rst.push(rst2); } return rst; }; } require(["dijit/registry", "dojo/data/ItemFileWriteStore", "dijit/tree/TreeStoreModel", "dijit/tree/dndSource", "dijit/Tree", "dojo/domReady!"], function (registry, ItemFileWriteStore, TreeStoreModel, dndSource, Tree) { if (true) { var rootid = 'root2'; var treedata = {"identifier": "id", label: "name", "items": [ {id: rootid, name: '零件庫', type: 'static', children: [ {id: 'fdj_comp', name: '發(fā)動機(jī)', type: 'static', children: [ {id: 'fdj1', name: 'A01-發(fā)動機(jī)', parent: 'fdj_comp', type: 'fdj_comp'} , {id: 'fdj2', name: 'A02-發(fā)動機(jī)', parent: 'fdj_comp', type: 'fdj_comp'} , {id: 'fdj3', name: 'A03-發(fā)動機(jī)', parent: 'fdj_comp', type: 'fdj_comp'} ]}, {id: 'jss_comp', name: '駕駛室', type: 'static', children: [ {id: 'cm_comp', name: '車門', type: 'static', children: [ {id: 'cm1', name: '左側(cè)車門', parent: 'cm_comp', type: 'cm_comp'}, {id: 'cm2', name: '右側(cè)車門', parent: 'cm_comp', type: 'cm_comp'} ]}, {id: 'ys_com', name: '內(nèi)飾顏色', type: 'static', children: [ {id: 'heis', name: '黑色', parent: 'ys_com', type: 'ys_com'}, {id: 'mis', name: '米色', parent: 'ys_com', type: 'ys_com'}, {id: 'hongs', name: '紅色', parent: 'ys_com', type: 'ys_com'} ]} ]} ]} ]}; makeTree(treedata, rootid, 'funtree1', true, registry, ItemFileWriteStore, TreeStoreModel, dndSource, Tree); } if (true) { var rootid = 'root3'; var treedata = {"identifier": "id", label: "name", "items": [ {id: rootid, name: '配置選擇', type: 'static', children: [ {id: 'zfdj', name: '發(fā)動機(jī)', type: 'fdj_comp_sp', children: []}, {id: 'zcm', name: '車門', type: 'cm_comp_sp', children: []}, {id: 'zys', name: '內(nèi)飾顏色', type: 'ys_com_sp', children: []} ]} ]}; makeTree(treedata, rootid, 'funtree2', false, registry, ItemFileWriteStore, TreeStoreModel, dndSource, Tree); } }); </script> </head> <body class="claro"> <table border="1"> <tr> <td><div id="funtree1"/></td> <td><div id="funtree2"/></td> </tr> </table> </body> </html>
重點(diǎn)分析:
1. 使用的dojo組件:
"dijit/registry" //用于獲取組件 , "dojo/_base/array" //用于整理數(shù)據(jù) , "dojo/data/ItemFileWriteStore" //用于包裝數(shù)據(jù) , "dijit/tree/TreeStoreModel" //用于轉(zhuǎn)換數(shù)據(jù)(Tre要求) , "dijit/tree/dndSource" //用于處理拖拽 , "dijit/Tree" //樹控件
2. 構(gòu)建符合樹控件模型接受的數(shù)據(jù)結(jié)構(gòu):
var rootid = 'root3'; var treedata = {"identifier": "id", label: "name", "items": [ {id: rootid, name: '配置選擇', type: 'static', children: [ {id: 'zfdj', name: '發(fā)動機(jī)', type: 'fdj_comp_sp', children: []}, {id: 'zcm', name: '車門', type: 'cm_comp_sp', children: []}, {id: 'zys', name: '內(nèi)飾顏色', type: 'ys_com_sp', children: []} ]} ]};
3. 拖動對象的處理:
3.1 注冊:
var foo = new dndSource( tree, //指向目標(biāo)樹控件 {betweenThreshold: 5, //支持拖動至目標(biāo)節(jié)點(diǎn)的“前位置”和“后位置” singular: true}); //制定拖動的是1個目標(biāo)節(jié)點(diǎn)(不含其子節(jié)點(diǎn))
3.2 判定拖動的有效性:
foo.checkItemAcceptance = function (target, source, position) { //覆蓋函數(shù)checkItemAcceptance ,返回true允許放置,返回false不允許放置 if (dndSkip) return false; //案例使用,左側(cè)樹始終不允許放置 var flag = false;//判斷是否可以拖拽 var tar_type = registry.byNode(target.parentNode).item.type[0]; //案例使用,右側(cè)樹允許同類型節(jié)點(diǎn)放置 var src_type = source.tree.selectedItem.type[0]; flag = (tar_type === src_type + '_sp' && position === "over") || (tar_type === src_type && position !== "over"); return flag; };
3.3 創(chuàng)建目標(biāo)樹節(jié)點(diǎn):
// dijit/tree/dndSource.js 源碼中明確提及要求開發(fā)者覆蓋此方法。 foo.itemCreator = function (nodes) { var rst = new Array(); for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; var id = '' + Math.floor(Math.random() * 1000); var item = registry.byNode(node).item; var rst2 = {id: id, name: item.name + "(" + id + ")", type : item.type}; rst.push(rst2); } return rst; };
這部分很重要卻很難了解到,在dijit/tree/dndSource.js的源碼中明確提及需要開發(fā)者進(jìn)行覆蓋。而官方文檔的介紹內(nèi)容中并沒有提及。
備注:
關(guān)于Dojo官方給出的樹控件的介紹案例(https://dojotoolkit.org/reference-guide/1.10/dijit/Tree.html#dijit-tree),其使用的是"dojo/store/Memory",其數(shù)據(jù)結(jié)構(gòu)
var myStore = new Memory({ data: [ { id: 'world', name:'The earth', type:'planet', population: '6 billion'}, { id: 'AF', name:'Africa', type:'continent', population:'900 million', area: '30,221,532 sq km', timezone: '-1 UTC to +4 UTC', parent: 'world'}, …… { id: 'SA', name:'South America', type:'continent', parent: 'world' } ], getChildren: function(object){ return this.query({parent: object.id}); } });
換言之其使用的是一維數(shù)組的數(shù)據(jù)構(gòu),加之?dāng)?shù)據(jù)對象中的parent屬性指向父節(jié)點(diǎn),完成樹模型的構(gòu)建。但是這個方法在功能上有缺陷:
一次性構(gòu)建樹控件,可以。
樹控件中節(jié)點(diǎn)的拖動,可以。
樹控件中節(jié)點(diǎn)的排序,不可以,因?yàn)槠浠A(chǔ)模型是一維數(shù)組,無法實(shí)現(xiàn)或者難以實(shí)現(xiàn)針對某一樹節(jié)點(diǎn)的子節(jié)點(diǎn)序列進(jìn)行排序的處理。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。