zoukankan      html  css  js  c++  java
  • jonmiles/bootstrap-treeview踩坑记录(吐槽下checkNode和expandNode方法使用)

    现在在2020年了,jonmiles/bootstrap-treeview 项目已经归档了,并且最后一次更新在2015年。但是,项目中使用到了这个库,所以,没得选择,只能粪不顾身跳入坑里。

    这篇文章主要吐槽bootstrap-treeview的两个方法:checkNodeexpandNode 的使用。

    checkNode 方法

    顾名思义,这个方法用来勾选 node 节点。根据文档说明:

    checkNode 方法的第一个参数可以是 node 对象或者 nodeId 数字。这里要特别注意 nodeId 数字,并不是想当然的初始化 treeview 所传入的 data 属性中对象的 id 字段。原先我也先入为主的以为是 data 对象中的 id 字段,但是发现不是,于是阅读了源代码。

    	/*
    		Identifies a node from either a node id or object
    	*/
    	Tree.prototype.identifyNode = function (identifier) {
    		return ((typeof identifier) === 'number') ?
    						this.nodes[identifier] :
    						identifier;
    	};
    

    identifyNode 方法,用来通过 identifier 标识来返回 node 对象。如果 identifier 是数字,就返回 this.nodes[identifier],否则原样返回。

    由于要找的是 identifier 是数字时所代表的含义,找到 setInitialStates 方法,它用来初始化所有节点及节点的状态:

    	Tree.prototype.setInitialStates = function (node, level) {
    
    		if (!node.nodes) return;
    		level += 1;
    
    		var parent = node;
    		var _this = this;
    		$.each(node.nodes, function checkStates(index, node) {
    
    			// nodeId : unique, incremental identifier
    			node.nodeId = _this.nodes.length;
    
    	// 中间代码省略...
    
    			// index nodes in a flattened structure for use later
    			_this.nodes.push(node);
    
    			// recurse child nodes and transverse the tree
    			if (node.nodes) {
    				_this.setInitialStates(node, level);
    			}
    		});
    	};
    

    从这两行关键代码可以看出来 nodeId 是从 0 开始的自增的整数,而并非 data 对象中的 id 字段:

    			// nodeId : unique, incremental identifier
    			node.nodeId = _this.nodes.length;
    
    	// 中间代码省略...
    
    			// index nodes in a flattened structure for use later
    			_this.nodes.push(node)
    

    啰嗦一大堆,结论就是 nodeId 是 treeview 自动生成的从 0 开始的自增整数。那解决想通过 data 对象中的 id 字段来实现 checkNode 该怎么做呢?

    分为两步,要在 bootstrap-treeview 新增一行代码,并且使用这一行新增的代码:

    #1

    bootstra-treeview.js 的源码里的 var Tree = function () { ... } 最后 return 返回的对象中新增一行代码:

    			findNodes: $.proxy(this.findNodes, this)
    

    #2

    完成 1 步骤后,我们就可以在源码外调用 findNodes 方法。这个方法很强大,可以通过正则表达式查找 nodes 节点中的指定属性的内容,并返回所有匹配的节点,findNodes 的源码:

    使用 findNodes 方法,就能够根据 id 属性查找所需的节点,然后传入 checkNodes 方法里:

    var node = $('#target').treeview('findNodes', ['^' + n + '$', 'g', 'id']);
    if (!node || !node.length) {
        return;
    }
    $('#target').treeview('checkNode', node);
    

    $('#target').treeview('findNodes', ['^' + n + '$', 'g', 'id']) 是含义是查找 nodes 节点中 id 属性值等于变量 n 的所有节点。

    expandNode 方法

    expandNode 方法用来展开指定的 node 节点,根据文档说明:

    expandNode 方法的第一个参数和 checkNode 方法的一样,可以接受 node 对象或者 nodeId 数字。第二个参数可选传入 levels 指定要展开节点的层级。默认就是 1 了,只展开一层;如果 levels: 2,那么会展开两层。

    实际情况中,使用了 checkNode 方法勾选节点后,想要自动展开这些节点,按照 expandNode 方法的实现是完成不了这个需求的。比方说,勾选了第三层级的 C 节点,要实现自动展开这个节点,需要先展开 C 节点的父节点(位于第二层级的某节点),再展开 C 节点的父节点的父节点(位于第一层级的某节点)。

    把这个需求用代码实现,方法取名为 expandRealNode(这才是我心目中的展开节点方法:-D):

    #1

    Tree.prototype.expandNode = function (identifiers, options) { ... } 的后面加上如下代码:

    	Tree.prototype.expandRealNode = function (identifiers, options) {
    		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
    			var real = node;
    			while (true) {
    				real = this.getParent(real);
    				console.log(real);
    				if (!real || !real.hasOwnProperty('nodeId')) {
    					break;
    				}
    				this.setExpandedState(real, true, options);
    			}
    		}, this));
    
    		this.render();
    	};
    

    #2

    bootstra-treeview.js 的源码里的 var Tree = function () { ... } 最后 return 返回的对象中新增一行代码:

    expandRealNode: $.proxy(this.expandRealNode, this)
    

    expandRealNode 的使用方法示例:

    var node = $('#target').treeview('findNodes', ['^' + n + '$', 'g', 'id']);
    if (!node || !node.length) {
        return;
    }
    $('#target').treeview('checkNode', node);
    
    $('#target').treeview('expandRealNode', node);
    

    总结

    主要分析了 bootstrap-treeview 源码里的 checkNodeexpandNode 方法的具体的含义,并按需改造成适合自己使用的场景。

    <全文完>

  • 相关阅读:
    二分法查找算法
    [Java]事件驱动程序设计
    spring 事件驱动模型简介
    事件驱动模型实例详解(Java篇)
    协程
    事件驱动模型的简单Java实现
    负载均衡技术(一)———负载均衡技术介绍
    知物由学 | 未来50年网络安全行业发展愿景
    知物由学 | 如何从勒索软件的攻击中全身而退
    “网易大数据讲堂第一期:数说”直播活动资料:课程回放收看及PPT下载
  • 原文地址:https://www.cnblogs.com/imzhi/p/bootstrap-view-step-hold.html
Copyright © 2011-2022 走看看