美文网首页
vue中原始数据未分类的情况下怎样区分父元素有无目标子元素并添加

vue中原始数据未分类的情况下怎样区分父元素有无目标子元素并添加

作者: 落崖惊风yxy | 来源:发表于2018-01-26 11:47 被阅读0次

    最近写了一个页面,需求如下:

    部分父元素有特殊的子元素,部分父元素没有特殊的子元素;特殊子元素开始的时候是隐藏的,点击其父元素展开,再点击就隐藏。相应的,所有数据都在一个json数组里,有没有特殊子元素数据并没有对其进行区分。

    我的做法是给所有的父元素都绑定事件,然后判断该父元素有没有特殊子元素,如果有就执行对应事件,如果没有一个return就跳出了。对应的,特殊子元素的显示与隐藏可以给其绑定一个类的开关,如:class="{'showdev':item.show}",如果item.show的值为true就添加上这个类,否则就没有这个类。
    html部分如下(最终的html,开始的时候现在看到的item.show是devdetailShow,它所在的li里面的ul则没有使用v-show指令):

    <ul v-for="(item,index) in failing.testcase" :class="!item.time?'especial':''"  @click="showdevDetail(item)" >
        <li class="time" v-if="item.time">{{item.time+"s"}}</li>
        <li>{{item.name}}</li>
         <li v-if="item.devDetail" class="especial" :class="{'showdev':item.show}">
                 <ul class="devdetail" v-for="item in item.devDetail" v-show="devdetailShow">
                       <li>{{item.name}}</li>
                       <li>{{item.failure}}</li>
                 </ul>
          </li>
    </ul>
    

    开始的时候,我给了一个全局开关: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:

    <li v-if="item.devDetail" class="especial" :class="{'showdev':item.show}">
                                <ul class="devdetail" v-for="item in item.devDetail" v-show="devdetailShow">
                                    <li>{{item.name}}</li>
                                    <li>{{item.failure}}</li>
                                    <li v-if="item.tapdID">{{item.tapdID}}</li>
                                </ul>
                            </li>
    

    因为函数的参数是外层的item,而不是内层的item in item.devDetail的item,所以为避免冲突,给ul添加一个包裹层,相应的v-show="devdetailShow"也要换位置并进行改动了。如下:
    html代码:

    <li v-if="item.devDetail" class="especial" :class="{'showdev':item.show}">
           <div v-show="item.devdetailShow">
                    <ul class="devdetail" v-for="item in item.devDetail">
                            <li>{{item.name}}</li>
                            <li>{{item.failure}}</li>
                            <li v-if="item.tapdID">{{item.tapdID}}</li>
                      </ul>
             </div>
     </li>
    

    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了。

    相关文章

      网友评论

          本文标题:vue中原始数据未分类的情况下怎样区分父元素有无目标子元素并添加

          本文链接:https://www.haomeiwen.com/subject/jabiaxtx.html