文档章节

knockout不操作dom来实现带管理功能的树形菜单

d
 doliangzhe
发布于 2013/05/13 13:24
字数 809
阅读 483
收藏 4

knockout已经使用一段时间了,但真正感觉到一些东西了,还是从下面这个例子开始的。不需要直接操作dom,有个绑定(当然是双向的)即可,将数据和dom元素联系起来,免去了在定位dom。

一个tree树的例子,带有复选框、删除节点及重命名功能。

效果图:



可以从这里查看  演示效果

Css代码


<script type='text/javascript' src='http://www.see-source.com/js/knockout-2.2.0.js'></script>
<style type="text/css">
  li {list-style:none; font-size:14px;}
  ul {padding-left:25px;}
  .operaterDiv{width:100px; margin-left:100px;; z-index:100px;position:absolute;margin-top:-5px; border:1px solid #000;background-color:#FFF}
  .operaterDiv li{list-style-type:none; padding:1px; margin-left:20px;}
  .operaterDiv a:link {text-decoration: underline; color:blue;}
  .operaterDiv a:visited{text-decoration: underline;; color:blue;}
  .operaterDiv a:hover {text-decoration: none; color:blue;}
  .close{float:right; font-size:5px; color:red;}
  .highLight{background-color:#009; color:#FFF;}
</style>
Html代码


<ul  data-bind="template: { name: 'guideTmpl', foreach: menus}"></ul><br/>
<a href="javascript:void(0)"  onClick="getSelectedValues()">查看选中值</a><br/>
Js代码


<!--节点模板模板-->
<script id="guideTmpl" type="text/html">
    <li>	    
	    <img data-bind="attr: {src:imageUrl}, click:$root.openOrClose"/>
		<input type="checkbox" data-bind="checked:selected"/>
		<span data-bind="text: name, visible:switchS, css:{highLight:editOpened}, event:{contextmenu:$root.myContextmenu, click:$root.openOrClose}, clickBubble: false"></span>
		<span data-bind="visible:!switchS()"><input type="text" data-bind="value:name,event:{blur:$root.closeAllOpenedDiv}"/></span>
		<div  data-bind="visible: editOpened" class="operaterDiv">
		    <span class="close" data-bind="click:$root.closeOpenedDiv">关闭</span>
		    <ul style="padding:0;margin:0; margin-top:5px;">
			   <li><a href="#"  data-bind="click:function(){if(confirm('确定要删除吗?')){$parent.children.remove(this)}; this.editOpened(false);}, clickBubble: false">Delete</a></li>
			   <li><a href="#"  data-bind="click:$root.doSwitch, clickBubble: false">Rename</a></li>
			</ul>
		</div>
		<ul data-bind="template: { name: 'guideTmpl', foreach: children }, visible:opened"></ul>		
		
	</li>
</script>
<script type="text/javascript">
var index = 1;//用于模拟value值(实际中应是每个节点的唯一标识)
var Menu = function(name, children, opened, imageUrl, selected, value) {//节点对应的js对象
    this.name = ko.observable(name);
	this.children = ko.observableArray(children || []);	//下级子节点
	this.opened = ko.observable(opened); //true:展开  false:折叠
	this.imageUrl = ko.observable("http://www.dhtmlgoodies.com/scripts/drag-drop-folder-tree/images/dhtmlgoodies_plus.gif"); //true:展开  false:折叠
	this.selected = ko.observable(false);
	this.value = "000" + index++;
	this.editOpened = ko.observable(false);
	this.switchS  = ko.observable(true);
};

var MenuModel = function() {
    var self = this;
    self.menus = ko.observableArray([
	    new Menu("Twitter BootStrap", [
		    new Menu("bootstrap介绍", [new Menu("2222")]),
			new Menu("响应式设计"),
			new Menu("JavaScript插件")
		]),
		new Menu("Knockout", [
		    new Menu("监控属性(Observables)"),
			new Menu("控制流绑定(Control flow)"),
			new Menu("表单域绑定(Form fields)"),
			new Menu("自定义绑定(Custom)")
		])
	]);
	//展开、折叠操作
	self.openOrClose = function(source){
	   self.closeAllOpenedDiv();
	   var opened = source.opened();
	   if(source.children() == 0)
	      return ;
	   if(opened){
	       source.opened(false);
		   source.imageUrl("http://www.dhtmlgoodies.com/scripts/drag-drop-folder-tree/images/dhtmlgoodies_plus.gif");
	   }else{
	       source.opened(true);
		   source.imageUrl("http://www.dhtmlgoodies.com/scripts/drag-drop-folder-tree/images/dhtmlgoodies_minus.gif");
	   }
	   var children = source.children();
	   for (var i in children){
	       if(children[i].children().length == 0 ){//存在子节
		      children[i].imageUrl("http://www.see-source.com/images/dhtmlgoodies_white.gif");
		   }
	   } 	   
	};
	//获得复选框所有选中的value值
	self.selectedValues = function(){
	    var valuesStr = "";
		var menus = self.menus();
		for (var i in menus){
		    if(menus[i].selected()){
			   valuesStr += ",";
			   valuesStr += menus[i].value;			   
			}
			var qiantao = function(child){
			    for (var i in child){
				    if(child[i].selected()){
			           valuesStr += ",";
			           valuesStr += child[i].value;			   
			        } 
					qiantao(child[i].children());
				}
			}
			qiantao(menus[i].children());
		}
		return valuesStr;
	};
	//右键事件(弹出操作层)
	self.myContextmenu = function(source){
	    self.closeAllOpenedDiv();
	    source.editOpened(true);
	};
	//切换
	self.doSwitch = function(source){
	    source.switchS(false);
		source.editOpened(false);
	};
	//关闭所有弹出操作层
	self.closeAllOpenedDiv = function(){
	   var menus = self.menus();
		for (var i in menus){		    
			var qiantao = function(child){
			    for (var i in child){
				    child[i].editOpened(false);
					child[i].switchS(true);
					qiantao(child[i].children());
				}
			}
			qiantao(menus[i].children());
			menus[i].editOpened(false);
			menus[i].switchS(true);			
		}
	};
	//关闭当前弹出操作层
	this.closeOpenedDiv = function(source){
	    source.editOpened(false);
	}
};
var myMenuModel = new MenuModel();
ko.applyBindings(myMenuModel);
var children = myMenuModel.menus();
for (var i in children){
	if(children[i].children().length == 0 ){//存在子节
		 children[i].imageUrl("http://www.see-source.com/images/dhtmlgoodies_white.gif");
	}
} 

</script>

<script type="text/javascript">
function getSelectedValues(){  //查看选中的值列表  
    var values = myMenuModel.selectedValues();
	if(values.length != 0){
	    values = values.substring(1);
	}
    alert(values);
}
</script>
以上代码可直接粘贴运行。




© 著作权归作者所有

d
粉丝 2
博文 14
码字总数 11064
作品 0
海淀
私信 提问
基于adminlte的后台管理系统开发

前言 现在的大前端技术来势凶猛,Vue&React&Angular三足鼎立,让我们这些后端开发人员瑟瑟发抖。为了开发一个内部使用的管理系统需要去学习Node&Webpack等各种新概念,况且我们的系统并没有那...

gongxufan
2018/06/21
0
0
个人整理的Knockout.js文档,有兴趣的朋友可以直接下载!

上周四在看Knockout.js的官方文档,阅读过程中顺便将其整理成了一份完整的文档,如果你此有兴趣,可以从这里下载。 P.S. Knockout.js简介[来自百度百科] Knockout是一个轻量级的UI类库,通过...

长平狐
2012/09/04
327
0
Winform开发主界面菜单的动态树形列表展示

我在之前很多文章里面,介绍过Winform主界面的开发,基本上都是标准的界面,在顶部放置工具栏,中间区域则放置多文档的内容,但是在顶部菜单比较多的时候,就需要把菜单分为几级处理,如可以...

walb呀
2017/12/04
0
0
前端开发框架Bootstrap和Knockout.js

江湖中那场异常惨烈的厮杀,如今都快被人遗忘了。当年,所有的武林同道为了同一个敌人都拼尽了全力,为数不多的幸存者心灰意冷,隐姓埋名,远赴他乡,他们将唯一的希望寄托给时间。少年子弟江...

我心悠悠
2013/09/22
9.7K
4
Knockout.js 3.5.0 Beta 发布,JavaScript 的 UI 库

Knockout.js 3.5.0 beta 发布了。Knockout 是个 JavaScript library,帮助创建丰富的显示和编辑器 UI,通过干净的底层数据模型。你可以在任何时候动态更新 U I的所选择部分。 更新内容:此版...

周其
2017/12/30
813
7

没有更多内容

加载失败,请刷新页面

加载更多

vue 2打包注意点

使用npm run build打包之后往往直接本地运行,路径类似这样:http://127.0.0.1:5500/xa/dist/index.html 或者http://127.0.0.1:5500/dist/index.html。然后页面打开是空白的,打开控制台查看...

牧云橙
10分钟前
4
0
归并排序

1.原理图 2.代码 public static void merge(int []a,int left,int mid,int right){ int []tmp=new int[a.length];//辅助数组 int p1=left,p2=mid+1,k=left;//p1、p2是检测......

wen123
14分钟前
4
0
css实现透明的两种方法

一、opacity:0~1 值越高,透明度越低: div{opacity:0.5 } 选择器匹配到的节点们,包括节点们的孩子节点,都会实现%50透明,另 0.5 可直接写成 .5 二、rgba(0~255,0~255,0~255,0~1) r...

Bing309
17分钟前
3
0
Tomcat 配置访问路径

此处只是部署完成后idea打开的默认路径,并非项目部署路径, 此处才是项目实际部署路径,可以有多个项目部署路径,idea可以配置默认打开一个

Aeroever
20分钟前
4
0
将ApiBoot Logging采集的日志上报到Admin

通过ApiBoot Logging可以将每一条请求的详细信息获取到,在分布式部署方式中,一个请求可能会经过多个服务,如果是每个服务都独立保存请求日志信息,我们没有办法做到统一的控制,而且还会存...

恒宇少年
20分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部