从 TreeView 中删除节点
Remove a node from a TreeView
我正在使用 knockoutJS 创建树视图,但在从树中删除某些节点时遇到了一些问题。我不知道为什么,但我的函数不检查所有树来查找节点,只检查第一个分支。这是我从树中删除节点的函数。
var ViewModel = function(){
self = this;
self.data = ko.mapping.fromJS(data.items);
self.removerItem = function(item){
debugger;
self.Remover(self.data,item);
}
self.Remover = function(data,item){
debugger;
for(i = 0; i < data().length; i++){
if(item.CategoryId == data()[i].CategoryId){
debugger;
data.remove(item);
return;
}
else{
debugger;
if(data()[i].items() != null && data()[i].items() != undefined && data()[i].items().length > 0)
arguments.callee(data()[i].items,item);
}
}
}
}
var data = {
items: [{
"CategoryId": 65,
"name": "MORPHED",
"items": [{
"name": "5 Day",
"items": [{
"CategoryId": 20,
"name": "30 day countdown"
}, {
"CategoryId": 19,
"name": "Staffing your program"
}, {
"CategoryId": 22,
"name": "Emergency/Medical Information"
}, {
"CategoryId": 18,
"name": "Promoting your program"
}, {
"CategoryId": 21,
"name": "Week of camp"
}]
}, {
"CategoryId": 245,
"name": "47 Day",
"items": []
}, {
"CategoryId": 222,
"name": "1/27 Day",
"items": []
}, {
"CategoryId": 2222,
"name": "Age Targeted",
"items": []
}]
}, {
"name": "CREATE",
"items": [{
"CategoryId": 2567,
"name": "15 Day",
"items": []
}, {
"CategoryId": 22245,
"name": "4 Day",
"items": []
}, {
"CategoryId": 2289787,
"name": "1/2 Day",
"items": []
}]
}]
};
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<ul style="list-style-type:none" data-bind="template: { name: 'itemTmpl', foreach: data }"></ul>
<script id="itemTmpl" type="text/html">
<li>
<div class="panel panel-default" style="margin: 0 0 0 0; padding: 0 0 0 0; border-radius:0">
<div class="panel-heading" style="background-color: white">
<a>
<span class="glyphicon glyphicon-plus"></span> </a>
<a data-bind="text: name"></a>
<a class="pull-right" data-bind="click: $root.removerItem"><span class="glyphicon glyphicon-remove"></span></a>
</div>
<div class="panel-body" style="margin: 0 0 0 0; padding: 0 0 0 0 " >
<ul style="list-style-type:none" data-bind="template: { name: 'itemTmpl', foreach: $data.items }"></ul>
</div>
</div>
</li>
</script>
和 here 是相同的代码,但在 jsfiddle 中。
你的post有复现了,很好,但是还是有很多地方难以理解,其中:
- 各种样式和 bootstrap 与问题无关的内容;
- 比问题所需的数据(包括项目及其属性)多得多;
- 大量笨拙的间距使代码难以阅读;
- 散落着
debugger
个陈述;
除此之外,一些类似代码审查的评论:
- 您没有将
var
与 self
一起使用,因此它是一个隐式全局;
- 恕我直言,您使用
arguments.callee
之类的东西使事情过于复杂,只需使用内置的 indexOf
和 remove
方法即可;
- 你让
self.data
让事情变得复杂,这实际上是一个项目列表,然后通过使用 ko.mapping
.[= 来命名相同的东西 items
45=]
- 您公开了
Remover
,它可以是私有函数;
- 您使用的是大写(因此隐含构造函数)名词 ("Remover"),而小写动词 ("remove") 更有意义。
这里有一些有用的东西,上面的所有内容都已更改/修复:
var ViewModel = function(data) {
var self = this;
self.items = ko.mapping.fromJS(data.items);
self.removeItem = function(toDeleteItem) {
remove(toDeleteItem, self.items);
}
function remove(toDeleteItem, itemsObsArray) {
if (!itemsObsArray) { return false; }
if (itemsObsArray().indexOf(toDeleteItem) >= 0) {
itemsObsArray.remove(toDeleteItem);
return true;
} else {
var items = itemsObsArray();
for (var i = 0; i < items.length; i++) {
if (!!remove(toDeleteItem, items[i].items)) {
return true;
}
}
}
return false;
}
}
var data = {
items: [
{
"name": "MORPHED",
"items": [
{
"name": "5 Day",
"items": [
{ "name": "30 day countdown" },
{ "name": "Staffing your program"}
]
},
{
"name": "47 Day",
"items": []
}
]
},
{
"name": "CREATE",
"items": [
{
"name": "15 Day",
"items": []
}, {
"name": "4 Day",
"items": []
}]
}]
};
ko.applyBindings(new ViewModel(data));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<ul data-bind="template: { name: 'itemTmpl', foreach: items }"></ul>
<script id="itemTmpl" type="text/html">
<li>
<div>
<div class="panel-heading">
<span data-bind="text: name"></span>
<a href="#" data-bind="click: $root.removeItem">remove</a>
</div>
<div>
<ul data-bind="template: { name: 'itemTmpl', foreach: $data.items }"></ul>
</div>
</div>
</li>
</script>
我正在使用 knockoutJS 创建树视图,但在从树中删除某些节点时遇到了一些问题。我不知道为什么,但我的函数不检查所有树来查找节点,只检查第一个分支。这是我从树中删除节点的函数。
var ViewModel = function(){
self = this;
self.data = ko.mapping.fromJS(data.items);
self.removerItem = function(item){
debugger;
self.Remover(self.data,item);
}
self.Remover = function(data,item){
debugger;
for(i = 0; i < data().length; i++){
if(item.CategoryId == data()[i].CategoryId){
debugger;
data.remove(item);
return;
}
else{
debugger;
if(data()[i].items() != null && data()[i].items() != undefined && data()[i].items().length > 0)
arguments.callee(data()[i].items,item);
}
}
}
}
var data = {
items: [{
"CategoryId": 65,
"name": "MORPHED",
"items": [{
"name": "5 Day",
"items": [{
"CategoryId": 20,
"name": "30 day countdown"
}, {
"CategoryId": 19,
"name": "Staffing your program"
}, {
"CategoryId": 22,
"name": "Emergency/Medical Information"
}, {
"CategoryId": 18,
"name": "Promoting your program"
}, {
"CategoryId": 21,
"name": "Week of camp"
}]
}, {
"CategoryId": 245,
"name": "47 Day",
"items": []
}, {
"CategoryId": 222,
"name": "1/27 Day",
"items": []
}, {
"CategoryId": 2222,
"name": "Age Targeted",
"items": []
}]
}, {
"name": "CREATE",
"items": [{
"CategoryId": 2567,
"name": "15 Day",
"items": []
}, {
"CategoryId": 22245,
"name": "4 Day",
"items": []
}, {
"CategoryId": 2289787,
"name": "1/2 Day",
"items": []
}]
}]
};
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<ul style="list-style-type:none" data-bind="template: { name: 'itemTmpl', foreach: data }"></ul>
<script id="itemTmpl" type="text/html">
<li>
<div class="panel panel-default" style="margin: 0 0 0 0; padding: 0 0 0 0; border-radius:0">
<div class="panel-heading" style="background-color: white">
<a>
<span class="glyphicon glyphicon-plus"></span> </a>
<a data-bind="text: name"></a>
<a class="pull-right" data-bind="click: $root.removerItem"><span class="glyphicon glyphicon-remove"></span></a>
</div>
<div class="panel-body" style="margin: 0 0 0 0; padding: 0 0 0 0 " >
<ul style="list-style-type:none" data-bind="template: { name: 'itemTmpl', foreach: $data.items }"></ul>
</div>
</div>
</li>
</script>
和 here 是相同的代码,但在 jsfiddle 中。
你的post有复现了,很好,但是还是有很多地方难以理解,其中:
- 各种样式和 bootstrap 与问题无关的内容;
- 比问题所需的数据(包括项目及其属性)多得多;
- 大量笨拙的间距使代码难以阅读;
- 散落着
debugger
个陈述;
除此之外,一些类似代码审查的评论:
- 您没有将
var
与self
一起使用,因此它是一个隐式全局; - 恕我直言,您使用
arguments.callee
之类的东西使事情过于复杂,只需使用内置的indexOf
和remove
方法即可; - 你让
self.data
让事情变得复杂,这实际上是一个项目列表,然后通过使用ko.mapping
.[= 来命名相同的东西items
45=] - 您公开了
Remover
,它可以是私有函数; - 您使用的是大写(因此隐含构造函数)名词 ("Remover"),而小写动词 ("remove") 更有意义。
这里有一些有用的东西,上面的所有内容都已更改/修复:
var ViewModel = function(data) {
var self = this;
self.items = ko.mapping.fromJS(data.items);
self.removeItem = function(toDeleteItem) {
remove(toDeleteItem, self.items);
}
function remove(toDeleteItem, itemsObsArray) {
if (!itemsObsArray) { return false; }
if (itemsObsArray().indexOf(toDeleteItem) >= 0) {
itemsObsArray.remove(toDeleteItem);
return true;
} else {
var items = itemsObsArray();
for (var i = 0; i < items.length; i++) {
if (!!remove(toDeleteItem, items[i].items)) {
return true;
}
}
}
return false;
}
}
var data = {
items: [
{
"name": "MORPHED",
"items": [
{
"name": "5 Day",
"items": [
{ "name": "30 day countdown" },
{ "name": "Staffing your program"}
]
},
{
"name": "47 Day",
"items": []
}
]
},
{
"name": "CREATE",
"items": [
{
"name": "15 Day",
"items": []
}, {
"name": "4 Day",
"items": []
}]
}]
};
ko.applyBindings(new ViewModel(data));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<ul data-bind="template: { name: 'itemTmpl', foreach: items }"></ul>
<script id="itemTmpl" type="text/html">
<li>
<div>
<div class="panel-heading">
<span data-bind="text: name"></span>
<a href="#" data-bind="click: $root.removeItem">remove</a>
</div>
<div>
<ul data-bind="template: { name: 'itemTmpl', foreach: $data.items }"></ul>
</div>
</div>
</li>
</script>