小程式triggerevent 傳參_微信小程式——無限遞迴的層次列表
阿新 • • 發佈:2020-12-24
技術標籤:小程式triggerevent 傳參
——上禮拜踩的坑
1、關於為什麼不直接操作DOM物件?
因為微信小程式裡沒有document物件。
2、為什麼坑了這多時間?
因為之前看了個過期的帖子,完美避開了解決方案。
下面進入正文,需求是在微信小程式裡構造一棵檔案樹。
3、解決思路
定義一個自定義元件,並在這個元件裡遞迴自己。
4、自定義元件.json檔案
{ "component": true, "usingComponents": { "alexTree":"path/to/component" } }
由於元件要引用自己,所以這裡定義了元件自己。
“alexTree”是元件裡引用自己時用的標籤名,理論上是可以自定義的,只要在wxml檔案j裡對應起來就好。
5、元件的property定義
properties: { treeBody:{ type: Array, value:[], observer: function (newVal, oldVal, changedPath) { } }, treeConfig:{ type:Object, value:{ haveOpGroup:false, haveIconGroup:false, opGroup:{ label:"", icon:"", onTap:function(node){ console.log("opGroup tapped."); } }, tapOnNode:function(node){ console.log("tapOnNode"); } }, observer: function(newVal, oldVal, changedPath) { } }, },
主要定義了兩個屬性,一個是資料tree-body,一個是配置tree-config。
資料結構本身當然也是遞迴的。tree-body是一個數組(根目錄),其中的元素作為檔案,一個檔案可以是一個普通檔案,也可以是一個目錄檔案,用元素的isDir屬性來區分,如下:
{
filename:<String>
isDir:<Boolean>
data:<Array>/<Object>
}
filename是檔名,當isDir為true時,data為子檔案陣列,當isDir為false時,data為與檔案相關的自定義資料,例如檔案在伺服器的url等。
6、 wxml大致結構。
<view wx:for="{{treeBody}}">
<!-- 這裡為當前節點的構造邏輯 -->
<view class='treeNode' catchtap="tapOnNode" data-node='{{item}}'> <<<<<<vviieew>>>>>>>>>
<!-- balabala -->
<!-- balabala -->
<!-- balabala -->
<!-- 然後判斷此節點是否展開,下面的邏輯裡,如果這個節點為展開狀態的目錄,就遞迴此元件 -->
<!-- 注意alexTree為上面json檔案裡定義的 -->
<view class='childNodes'>
<alexTree wx:if="{{item.isDir && item.expand}}" tree-body="{{item.data}}" tree-config="{{treeConfig}}" data-filename="{{item.filename}}" bindnodechanged="_handleChildNodeChanged"/>
</view>
</view>
7、點選節點更改目錄展開狀態
tapOnNode:function(e){
// 點選節點時,摺疊或展開結點(目錄)
var tmpNode = e.currentTarget.dataset.node;
var filename = tmpNode.filename;
var nodes = this.data.treeBody;
var node = this._findNodeByName(nodes,filename);
if(!node){
return;
}
if(node.isDir){
if(node.expand){
delete node.expand;
}else{
node["expand"] = 1;
}
}
this._refreshTree(nodes);
// 呼叫treeConfig.tapOnNode
if(this.data.treeConfig.tapOnNode){
this.data.treeConfig.tapOnNode();
}
},
8、另一個問題
傳遞給子節點的資料為深複製之後的陣列,所以改變子節點的資料,不會影響到父節點的資料。當父節點目錄摺疊時,重新展開後,子節點的狀態無法儲存。
解決方案:當子節點資料改變時,丟擲一個自定義事件,父節點捕捉這個事件,同時更改自己的資料。
// 重新整理樹
_refreshTree:function(nodes){
this.setData({
treeBody : nodes,
});
// 然後向父結點丟擲一個nodeChanged事件
var filename = this.dataset.filename;
var myEventDetail = {
filename: filename,
nodes: nodes,
} // detail物件,提供給事件監聽函式
var myEventOption = {} // 觸發事件的選項
this.triggerEvent('nodechanged', myEventDetail, myEventOption)
},
_handleChildNodeChanged:function(e){
// 處理子結點丟擲的nodeChanged事件
var filename = e.detail.filename;
var nodes = this.data.treeBody;
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].filename == filename) {
nodes[i].data = e.detail.nodes;
}
}
this.setData({
treeBody: nodes,
});
},