最近写了一个页面,需求如下:
部分父元素有特殊的子元素,部分父元素没有特殊的子元素;特殊子元素开始的时候是隐藏的,点击其父元素展开,再点击就隐藏。相应的,所有数据都在一个json数组里,有没有特殊子元素数据并没有对其进行区分。
我的做法是给所有的父元素都绑定事件,然后判断该父元素有没有特殊子元素,如果有就执行对应事件,如果没有一个return就跳出了。对应的,特殊子元素的显示与隐藏可以给其绑定一个类的开关,如:class="{'showdev':item.show}"
,如果item.show的值为true就添加上这个类,否则就没有这个类。
html部分如下(最终的html,开始的时候现在看到的item.show是devdetailShow,它所在的li里面的ul则没有使用v-show指令):
- {{item.time+"s"}}
- {{item.name}}
-
- {{item.name}}
- {{item.failure}}
开始的时候,我给了一个全局开关:devdetailShow:false
对应的点击事件代码:
showdevDetail:function(item){
//判断是否存在特殊子元素对应的数据,如果有,则执行对应的隐藏与展开的交互;否则不执行
if(item.devDetail){
this.devdetailShow=!this.devdetailShow;
}else{
return;
}
}
函数中的item在绑定事件时传入的是父元素的数据名称,item.devDetail则是特殊子元素的数据名称。
但是实际效果却是无论是哪个元素(有特殊子元素的父元素)触发事件,都会导致所有有特殊子元素的父元素及其子元素都受到影响,然而输出的item又的确是唯一的触发事件的元素的item。这是为什么呢?
原因在于虽然item是针对e.target的,但是开关devdetailShow是针对所有特殊子元素的。无论e.target是哪一个,都会改变全局开关devdetailShow。
既然如此,这个开关就得是针对唯一的e.target的。因为原始数据中并没有相应的可用的开关,所以需要自己添加。
对应的代码如下:
showdevDetail:function(item){
var me=this;
if(item.devDetail){
if(typeof item.show=="undefined"){
me.$set(item,"show",true)
}else{
item.show=!item.show;
}
}else{
return;
}
}
因为原始数据里并没有show字段,第一次点击显示也就是show的值为true,第二次点击隐藏也就是show的值为false,点三次点击show的值为true......如此循环。如果没有点击过,那么item.show就不存在,否则不是true就是false。因此并不知道是第几次点击的,所以要先判断item.show是否存在,也就是判断typeof item.show=="undefined"为true还是false。
那么看一下效果,未点击之前,特殊子元素显示了;第一次点击显示,第二次点击隐藏,第三次点击显示.....
不符合需求对不对?需求是未点击之前是隐藏的。查看了一下html部分的代码,产生的一个想法,那就是控制特殊子元素(especial)的子元素(child)的显示与隐藏。一开始就把child隐藏掉,第一次点击后让其显示,然后不管它了。从此以后,especial显示它就显示,especial隐藏它就看不到了,给它的开关是不是全局的都无所谓了。在此我又用上了一开始设置的那个开关devdetailShow,只不过给其换了位置。
对应的代码如下:
showdevDetail:function(item){
var me=this;
if(item.devDetail){
if(typeof item.show=="undefined"){
me.$set(item,"show",true)
//给child设置开关
me.devdetailShow=!me.devdetailShow;
}else{
item.show=!item.show;
}
}else{
return;
}
}
可是,发现了吗?目前有两个especial,点击其中一个especial的父元素受到影响的却是另一个especial。第二次点击该especial的父元素,它才产生相应的交互。一旦收起especial,就再也点不开了。这是什么鬼?!!!
看看上边的代码就会发现,开始的时候devdetailShow的值为false,如果是第一次点击devdetailShow就设置为me.devdetailShow=!me.devdetailShow也就是true;那第二次第三次...点击它始终都是false,不显示了呀。
所以,还是需要改动滴,如下:
showdevDetail:function(item){
var me=this;
if(item.devDetail){
if(typeof item.show=="undefined"){
me.$set(item,"show",true)
me.devdetailShow=true;
}else{
item.show=!item.show;
me.devdetailShow=true;
}
}else{
return;
}
}
现在的效果是,点击其中一个especial的父元素受到影响的却是另一个especial。第二次点击该especial的父元素,它才产生相应的交互。以后每次点击有都是正常的。
没啥说的,再改!显然,全局的快关devdetailShow不行。那就针对性的来吧。类似于设置开关show。
看下下面段html:
- {{item.name}}
- {{item.failure}}
- {{item.tapdID}}
因为函数的参数是外层的item,而不是内层的item in item.devDetail的item,所以为避免冲突,给ul添加一个包裹层,相应的v-show="devdetailShow"也要换位置并进行改动了。如下:
html代码:
- {{item.name}}
- {{item.failure}}
- {{item.tapdID}}
js代码:
showdevDetail:function(item){
var me=this;
if(typeof item.devdetailShow=="undefined"){
me.$set(item,"devdetailShow",true)
}else{
// item.devdetailShow=!item.devdetailShow;
item.devdetailShow=true;
}
if(item.devDetail){
if(typeof item.show=="undefined"){
me.$set(item,"show",true)
}else{
item.show=!item.show;
}
}else{
return;
}
}
问题终于得以解决。但是还有一点瑕疵哦!就是第一次点击父元素时要双击才能显示对应的especial,以后的每次点击单击就ok了。