关于Java Script的DOM操作classList.toggle()在vue.js中的切换使用与无法切换的问题,及其思考与解决

目录

第一个大问题(CSS内联样式表的顺序问题)

第二个大问题(分离display属性):

全部完整的练习源码如下


个人小练习的小小体会,classList.toggle()在vue.js中的切换使用与CSS样式内联表的顺序问题

先说明一个学校里小练习的题目:

这需要初学者的一点DOM知识以及JS和vue的知识,才能理解

<!--

练习:

①有一个购物车功能,需要实时计算商品数量和总价,并在页面上显示。请完成以下任务:

②创建一个 Vue 组件,包含一个商品列表,每个商品包含名称、数量、价格等信息,以及一个显示商品数量和总价的区域。

③使用 computed 属性计算商品数量和总价,并在页面上显示。

④使用 watch 监听商品数量和价格的变化,并在变化时更新商品数量和总价。

⑤实现增加和删除商品的功能,包括修改数量和价格,并在更新商品信息后自动计算商品数量和总价。

⑥在组件的 created 生命周期钩子函数中添加 watch 监听器,而在 beforeUnmount 生命周期钩子函数中取消监听器

-->

而其中要使用的classList.toggle()属性就是为了解决其中的“增加商品”的功能,我想要实现的是在一个界面中,点击一个按钮,可以通过切换css中的display样式,来实现一个增加商品的表单的 出现和消失。

首先在js中定义一个数组用来存放需要增加的商品信息

然后再methods里定义一个方法addPageDisplay()来控制添加信息的出现

以及另一个方法addComdy()来提交信息

<script type="module">

        let id='2500100';//id作用起始id,通过自增来依次赋值
    
        const shopping=Vue.createApp({
            data(){
                return{
                    //定义一个新的对象模板来依次赋值
                    addNew_arr: {comdy_id:'',comdy_name:'',comdy_number:'',comdy_price:'',comdy_decr:''}

                }
            } ,
            methods :{
            addPageDisplay(){},
            addComdy(){}      

            }

      
        });
    
        shopping.mount('#shopping')

    </script>

然后需要在body里定义一个<div>

    <div id="shopping">
        <button type="button"  @click="addPageDisplay">添加商品</button>
        <div class="submitForm" >
            <form action="">
                    <table>
                    <!--通过直接读取数组里的comdy_name属性,再通过v-model来动态绑定数组里的信息-->
                        <tr>商品名称: <input type="text" v-model="addNew_arr.comdy_name"></tr>
                        <tr>商品数量: <input type="text" v-model="addNew_arr.comdy_number"></tr>
                        <tr>商品价格: <input type="text" v-model="addNew_arr.comdy_price"></tr>
                        <tr>商品描述: <input type="text" v-model="addNew_arr.comdy_decr"></tr>
                        <tr><button type="button"  @click="addComdy">提交</button></tr>  
                    </table>                                          
                
            </form>
        </div>        
    </div>

这时我们需要定义css的样式,其中一个样式为submiForm,另一个样式为hidden,

当我们点击“添加商品”的按钮时,submiForm的样式会被切换成hidden的样式,css格式为:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>测试toggle的问题</title>
    <script src="cdn.staticfile.org_vue_3.0.5_vue.global.js"></script>
    <style>
         
        .block{
           display: block; /*设置为显示*/
        }
        
        
         .submitForm{ 
            display:none;     /*设置隐藏其显示*/               
            top: 10px;
            width: 60%;
            height: 60%;
            justify-content: center;
            align-items: center;
        }

    </style>
</head>

 注意以上的顺序,其中.hidden样式设置为第一项,.submitForm为第二项,因为html是顺序解构的,会从上往下依次向下读取文件

这时候只要设置点击“添加商品的方法”,让.submitForm的display:none显示属性转变为display:block就可以了,因此:

addPageDisplay(){
                    //通过DOM的document.querySelector找寻上下文里所有的名为'.submitForm'的类,被将其赋值给新定义的常量const submitForm
                    const submitForm = document.querySelector('.submitForm');            
                    //随后通过调用DOM里的classList属性里的toggle方法,实现属性的切换
                    //如果属性存在,则删除原本的属性,如果属性不存在,则添加属性
                    //即,原先submitForm中存在display:none的属性
                        submitForm.classList.toggle('block');              
    
                },

classList的方法应用

第一个大问题(CSS内联样式表的顺序问题)

那么第一个问题来了,实现了以上的方法后,是否能实现通过button的“添加商品”按钮实现form表单的显示和隐藏呢?

答案是错误,并不能实现,因为在刚定义时,CSS的内联样式表顺序反了。

 在其解构时,html文件会先读取第一个.block再读取第二个.submitForm

也就是说后来的会覆盖前面的,第二项的css会覆盖第一项的css,第二项的优先级高于第一项

也就是说,第二项的display的优先级会覆盖第一项

这时候我们需要把第一项调为第二项,第二项调为第一项,让.submitForm的优先级大于.block的优先级,这个时候就可以用“添加按钮来切换了”

即:

调整位置后就可以实现了

第二个大问题(分离display属性):

虽然第一个问题解决了,但是第二个问题是,我想在提交表单这个动作完成的一瞬间,触发click事件,去关闭表单,让因为第一步的原因,表单的display:block重新变回display:none,让表格重新隐藏起来。可是如果再用一次第一次中的方法时,会发现,因为这个时候.block的优先级已经大于了.submitForm,此时再去切换的话已经切换不回去了。

对应的就是下面这个提交操作

所以需要指令,但因为优先级问题无法再读取回原来的样式


                    const submitForm = document.querySelector('.submitForm');            

                        submitForm.classList.toggle('submitForm');              
                      //无法再重新读取回原来的样式

所以这个时候需要再定义一个类样式,专门用来隐藏,即为 .hidden

但是即便如此,也不能实现目的,因为.hidden的优先级还是小于.block,只是相当于把display:none从.submitForm中单独拿了出来而已。

所以此时需要双重切换:

首先我们需要再div中将单独分离出来的display:none属性给加回class里,让<div>同时具备两种属性

即:

<div id="shopping">
        <button type="button"  @click="addPageDisplay">添加商品</button>
        <!--注意这里的class里多了个hidden-->
        <div class="submitForm hidden" >
            <form action="">
                    <table>
                        <tr>商品名称: <input type="text" v-model="addNew_arr.comdy_name"></tr>
                        <tr>商品数量: <input type="text" v-model="addNew_arr.comdy_number"></tr>
                        <tr>商品价格: <input type="text" v-model="addNew_arr.comdy_price"></tr>
                        <tr>商品描述: <input type="text" v-model="addNew_arr.comdy_decr"></tr>
                        <tr><button type="button"  @click="addComdy">提交</button></tr>  
                    </table>                                          
                
            </form>
        </div>        
    </div>

**同时注意,一个class里定义多个类名,不会有优先级的冲突,它们都同时作用于同一个div,所以无论是取名为class=“submitForm hidden”还是取名为class=“hidden submitForm”都不会有影响,取名顺序不会影响其优先级,但是CSS内联样式表的顺序还是会影响,就跟前面一样,这里的class虽不受取名顺序影响,但如果在样式表中submitForm在hidden前面,则submitForm会覆盖hidden里相同的属性,反之亦然**

同时需要更改一下原先methods方法里的代码:

当我们第一次点击时会发生以下事件:

addPageDisplay(){
                    //第一次点击时:第一步通过DOM的querySelector获取对应的类,如果是id的话就用getElementById,效果一样的
                    const submitForm = document.querySelector('.submitForm');              
                    //第一次点击时:第二步,通过toggle切换css样式,根据原则“如果有则删除,如果没有则添加,如果不一样则修改”,原先的submitForm里有hidden的display:none,所以这里就先删除了submitForm里的display属性
                        submitForm.classList.toggle('hidden'); 
                    //第一次点击时:第三步,因为.block的优先级最大,且第二步的时候删除了display:none属性,所以第三步就会往原本的.submitForm里添加display:block属性,就会从隐藏变为显示了
                        submitForm.classList.toggle('block');              
    
                },

 随后当我们第二次点击时又会发生以下事件:

addPageDisplay(){
                    //第一次点击时:第一步通过DOM的querySelector获取对应的类,如果是id的话就用getElementById,效果一样的

                    //当第二次点击时,同样第一步先获取DOM对象
                    const submitForm = document.querySelector('.submitForm');              
                    //第一次点击时:第二步,通过toggle切换css样式,根据原则“如果有则删除,如果没有则添加,如果不一样则修改”,原先的submitForm里有hidden的display:none,所以这里就先删除了submitForm里的display属性

                    //当第二次点击时:因为第一次点击时最后一步的残留影响,效果为.block的display:block,所以此时如果要切换为hidden的话,根据内联样式表的顺序,.hidden的优先级小于.block,所以会添加上hidden但不能覆盖.blcok
                        submitForm.classList.toggle('hidden'); 

                    //第一次点击时:第三步,因为.block的优先级最大,且第二步的时候删除了display:none属性,所以第三步就会往原本的.submitForm里添加display:block属性,就会从隐藏变为显示了

                    //当第二次点击时:因为CSS样式为display:block,还是原本的样式,根据原则“如果有则删除,如果没有则添加,如果不一样则修改”,会删除掉.block的样式,只会留下.submitForm和.hidden的,所以这时候又会被隐藏起来了
                        submitForm.classList.toggle('block');              
    
                },
    
                addComdy(){
                    this.addNew_arr.comdy_id=id++;
                    const submitForm = document.querySelector('.submitForm')  ;             
                    submitForm.classList.toggle('block');
                    submitForm.classList.toggle('hidden');
                    this.addNew_arr={comdy_id:id++,comdy_name:'',comdy_number:'',comdy_price:'',comdy_decr:''}
                    alert('提交成功!');
                } 

 据此,个人剖析完毕。其中留了一个addComdy的方法,没有打上注释,可以给小白们自己分析一下,像一个练习一样吧~

全部完整的练习源码如下

有兴趣的可以看看:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>测试toggle的问题</title>
    <script src="cdn.staticfile.org_vue_3.0.5_vue.global.js"></script>
    <style>

        .submitForm{  
           /*
                display:none  ?
                display:block ?
            */            
            top: 10px;
            width: 60%;
            height: 60%;
            justify-content: center;
            align-items: center;
        }

        
        .hidden{
           display: none;
        }

        .block{
            display: block;
        }
        
        

    </style>
</head>
<body>

    <div id="shopping">
        <button type="button"  @click="addPageDisplay">添加商品</button>
        <div class="submitForm hidden" >
            <form action="">
                    <table>
                        <tr>商品名称: <input type="text" v-model="addNew_arr.comdy_name"></tr>
                        <tr>商品数量: <input type="text" v-model="addNew_arr.comdy_number"></tr>
                        <tr>商品价格: <input type="text" v-model="addNew_arr.comdy_price"></tr>
                        <tr>商品描述: <input type="text" v-model="addNew_arr.comdy_decr"></tr>
                        <tr><button type="button"  @click="addComdy">提交</button></tr>  
                    </table>                                          
                
            </form>
        </div>        
    </div>

    <script type="module">

        let id='2500100';
    
    
        const shopping=Vue.createApp({
            data(){
                return{
                    
                    addNew_arr: {comdy_id:'',comdy_name:'',comdy_number:'',comdy_price:'',comdy_decr:''},
 
                }
            },   
    
            methods:{   
                addPageDisplay(){
                    //第一次点击时:第一步通过DOM的querySelector获取对应的类,如果是id的话就用getElementById,效果一样的

                    //当第二次点击时,同样第一步先获取DOM对象
                    const submitForm = document.querySelector('.submitForm');              
                    //第一次点击时:第二步,通过toggle切换css样式,根据原则“如果有则删除,如果没有则添加,如果不一样则修改”,原先的submitForm里有hidden的display:none,所以这里就先删除了submitForm里的display属性

                    //当第二次点击时:因为第一次点击时最后一步的残留影响,效果为.block的display:block,所以此时如果要切换为hidden的话,根据内联样式表的顺序,.hidden的优先级小于.block,所以会添加上hidden但不能覆盖.blcok
                        submitForm.classList.toggle('hidden'); 

                    //第一次点击时:第三步,因为.block的优先级最大,且第二步的时候删除了display:none属性,所以第三步就会往原本的.submitForm里添加display:block属性,就会从隐藏变为显示了

                    //当第二次点击时:因为CSS样式为display:block,还是原本的样式,根据原则“如果有则删除,如果没有则添加,如果不一样则修改”,会删除掉.block的样式,只会留下.submitForm和.hidden的,所以这时候又会被隐藏起来了
                        submitForm.classList.toggle('block');              
    
                },
    
                addComdy(){
                    this.addNew_arr.comdy_id=id++;
                    const submitForm = document.querySelector('.submitForm')  ;             
                    submitForm.classList.toggle('block');
                    submitForm.classList.toggle('hidden');
                    this.addNew_arr={comdy_id:id++,comdy_name:'',comdy_number:'',comdy_price:'',comdy_decr:''}
                    alert('提交成功!');
                }  
            }   
        });
    
        shopping.mount('#shopping')

    </script>


<!-- 
    结论:submitForm作为主类的话,其中的display会被覆盖,为最高优先级,无法被toggle通过其它类去改变修改,解决方法只能定义两个类
    用其他类作为辅助属性,并在style中设定顺序,其顺序决定了它们的优先级问题
 -->
    
</body>
</html>

测试toggle的问题

猜你喜欢

转载自blog.csdn.net/m0_72159389/article/details/130657647
今日推荐