zoukankan      html  css  js  c++  java
  • JavaScript高级-----2.面向对象(案例 Tab栏切换)

    4. 面向对象案例



    • 第一步
    class Tab {
        constructor(id) {
            //获取元素
            this.main = document.querySelector(id); //最大的Tab盒子
            this.lis = this.main.querySelectorAll('li'); //大盒子里面的li
            this.sections = this.main.querySelectorAll('section');
            this.init();//new的时候自动调用 用于测试代码console.log(this.index);是否可以打印正确的索引号
        }
    
        //初始化模块 让相关的元素绑定事件
        init() {
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].index = i;
                this.lis[i].onclick = function() {
                    console.log(this.index);
                }
            }
        }
    
        //1. 切换功能
        toggleTab() {}
    
        //2. 添加功能
        addTab() {}
    
        //3. 删除功能
        removeTab() {}
    
        //4. 修改功能
        editTab() {}
    }
    
    //页面中可能会有很多Tab都需要使用这个功能,那就可以实例化不同的对象。
    var tab = new Tab('#tab');
    
    • 第二步
    class Tab {
        constructor(id) {
            //获取元素
            this.main = document.querySelector(id); //最大的Tab盒子
            this.lis = this.main.querySelectorAll('li'); //大盒子里面的li
            this.sections = this.main.querySelectorAll('section');
            this.init();
        }
    
        //初始化模块 让相关的元素绑定事件
        init() {
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].index = i;
                this.lis[i].onclick = this.toggleTab; //点击之后调用函数toggleTab(),函数前面的this就是函数的调用者。this.toggleTab的this就是被点击的li
            }
        }
    
        //1. 切换功能
        toggleTab() {
        //函数里面的this都指向函数的调用者
            console.log(this.index); //这个this指向当前的li,每个li都有一个index属性
        }
    
        //2. 添加功能
        addTab() {}
    
        //3. 删除功能
        removeTab() {}
    
        //4. 修改功能
        editTab() {}
    }
    
    //页面中可能会有很多Tab都需要使用这个功能,那就可以实例化不同的对象。
    var tab = new Tab('#tab');
    
    • 第三步:切换功能的实现
    var that;
    class Tab {
        constructor(id) {
            that = this;
            //获取元素
            this.main = document.querySelector(id); //最大的Tab盒子
            this.lis = this.main.querySelectorAll('li'); //大盒子里面的li
            this.sections = this.main.querySelectorAll('section');
            this.init();
        }
    
        //初始化模块 让相关的元素绑定事件
        init() {
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].index = i;
                this.lis[i].onclick = this.toggleTab; //点击之后调用函数toggleTab()
            }
        }
    
        //1. 切换功能
        toggleTab() {
            // console.log(this.index); //这个this指向当前的li,每个li都有一个index属性
            that.clearClass(); //必须要实例对象来调用这个函数
            this.className = "liactive";
            that.sections[this.index].className = "conactive"; //that指向实例化的对象(大盒子)
        }
    
        //清除其他"类"的函数
        clearClass() { //由于这里是实例对象that来调用该函数,所以该函数里的this依然指向的是调用者:实例对象Tab
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].className = '';
                this.sections[i].className = '';
            }
        }
    
        //2. 添加功能
        addTab() {}
    
        //3. 删除功能
        removeTab() {}
    
        //4. 修改功能
        editTab() {}
    }
    
    //页面中可能会有很多Tab都需要使用这个功能,那就可以实例化不同的对象。
    var tab = new Tab('#tab');
    

    对于insertAdjacentHTML():https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentHTML

    若用appendChild,那么还要经过createElement创建。。。

    • 第四步
    var that;
    class Tab {
        constructor(id) {
            that = this;
            //获取元素
            this.main = document.querySelector(id); //最大的Tab盒子
            this.lis = this.main.querySelectorAll('li'); //大盒子里面的li
            this.sections = this.main.querySelectorAll('section');
            this.add = this.main.querySelector('.tabadd');
            //li的父元素
            this.ul = this.main.querySelector('.fisrstnav ul:first-child');
            //section父元素
            this.fsection = this.main.querySelector('.tabscon');
            this.init(); //这里的this是实例对象,说明实例对象来调用的init(),那么init()里面的this都指向实例对象
        }
    
        //初始化模块 让相关的元素绑定事件
        init() {
            this.add.onclick = this.addTab;
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].index = i;
                this.lis[i].onclick = this.toggleTab; //点击之后调用函数toggleTab()
            }
        }
    
        //1. 切换功能
        toggleTab() {
            // console.log(this.index); //这个this指向当前的li,每个li都有一个index属性
            that.clearClass(); //必须要实例对象来调用这个函数
            this.className = "liactive";
            that.sections[this.index].className = "conactive"; //that指向实例化的对象(大盒子)
        }
    
        //清除其他"类"的函数
        clearClass() { //由于这里是实例对象that来调用该函数,所以该函数里的this依然指向的是调用者:实例对象Tab
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].className = '';
                this.sections[i].className = '';
            }
        }
    
        //2. 添加功能
        addTab() {
            that.clearClass();
            //创建li和section
            var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
            var section = '<section class="conactive">测试1</section>';
            //将li和section追加到父元素里
            that.ul.insertAdjacentHTML('beforeend', li);
            that.fsection.insertAdjacentHTML('beforeend', section);
        }
    
        //3. 删除功能
        removeTab() {}
    
        //4. 修改功能
        editTab() {}
    }
    
    //页面中可能会有很多Tab都需要使用这个功能,那就可以实例化不同的对象。
    var tab = new Tab('#tab');
    

    bug1:那些新增的li没有切换功能
    解决思路:由于一部分li是后来才添加的,所以要求,当点击加号后,需要重新获取所有的小li和所有的section

    var that;
    class Tab {
        constructor(id) {
            that = this;
            //获取元素
            this.main = document.querySelector(id); //最大的Tab盒子
            this.add = this.main.querySelector('.tabadd');
            //li的父元素
            this.ul = this.main.querySelector('.fisrstnav ul:first-child');
            //section父元素
            this.fsection = this.main.querySelector('.tabscon');
            this.init(); //这里的this是实例对象,说明实例对象来调用的init(),那么init()里面的this都指向实例对象
        }
    
        //获取所有的li和section
        updateNode() { //解决bug1
            this.lis = this.main.querySelectorAll('li'); //大盒子里面的li
            this.sections = this.main.querySelectorAll('section');
        }
    
        //初始化模块 让相关的元素绑定事件
        init() {
            this.updateNode(); //解决bug1
            this.add.onclick = this.addTab;
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].index = i;
                this.lis[i].onclick = this.toggleTab; //点击之后调用函数toggleTab()
            }
        }
    
        //1. 切换功能
        toggleTab() {
            // console.log(this.index); //这个this指向当前的li,每个li都有一个index属性
            that.clearClass(); //必须要实例对象来调用这个函数
            this.className = "liactive";
            that.sections[this.index].className = "conactive"; //that指向实例化的对象(大盒子)
        }
    
        //清除其他"类"的函数
        clearClass() { //由于这里是实例对象that来调用该函数,所以该函数里的this依然指向的是调用者:实例对象Tab
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].className = '';
                this.sections[i].className = '';
            }
        }
    
        //2. 添加功能
        addTab() {
            that.clearClass();
            //创建li和section
            var random = Math.random();
            var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
            var section = '<section class="conactive">测试' + random + '</section>';
            //将li和section追加到父元素里
            that.ul.insertAdjacentHTML('beforeend', li);
            that.fsection.insertAdjacentHTML('beforeend', section);
            that.init(); //解决bug1   重新绑定事件
        }
    
        //3. 删除功能
        removeTab() {}
    
        //4. 修改功能
        editTab() {}
    }
    
    //页面中可能会有很多Tab都需要使用这个功能,那就可以实例化不同的对象。
    var tab = new Tab('#tab');
    

    var that;
    class Tab {
        constructor(id) {
            that = this;
            //获取元素
            this.main = document.querySelector(id); //最大的Tab盒子
            this.add = this.main.querySelector('.tabadd');
            //li的父元素
            this.ul = this.main.querySelector('.fisrstnav ul:first-child');
            //section父元素
            this.fsection = this.main.querySelector('.tabscon');
    
            this.init(); //这里的this是实例对象,说明实例对象来调用的init(),那么init()里面的this都指向实例对象
        }
    
        //获取所有的li和section和❌
        updateNode() { //解决bug1
            this.lis = this.main.querySelectorAll('li'); //大盒子里面的li
            this.sections = this.main.querySelectorAll('section');
            //获取❌
            this.remove = this.main.querySelectorAll('.icon-guanbi');
        }
    
        //初始化模块 让相关的元素绑定事件
        init() {
            this.updateNode(); //解决bug1
            this.add.onclick = this.addTab;
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].index = i;
                this.lis[i].onclick = this.toggleTab; //点击之后调用函数toggleTab()
                this.remove[i].onclick = this.removeTab;
            }
        }
    
        //1. 切换功能
        toggleTab() {
            // console.log(this.index); //这个this指向当前的li,每个li都有一个index属性
            that.clearClass(); //必须要实例对象来调用这个函数
            this.className = "liactive";
            that.sections[this.index].className = "conactive"; //that指向实例化的对象(大盒子)
        }
    
        //清除其他"类"的函数
        clearClass() { //由于这里是实例对象that来调用该函数,所以该函数里的this依然指向的是调用者:实例对象Tab
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].className = '';
                this.sections[i].className = '';
            }
        }
    
        //2. 添加功能
        addTab() {
            that.clearClass();
            //创建li和section
            var random = Math.random();
            var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
            var section = '<section class="conactive">测试' + random + '</section>';
            //将li和section追加到父元素里
            that.ul.insertAdjacentHTML('beforeend', li);
            that.fsection.insertAdjacentHTML('beforeend', section);
            that.init(); //解决bug1
        }
    
        //3. 删除功能
        removeTab(e) {
            e.stopPropagation(); //阻止点击事件冒泡,❌有点击事件,li也有点击事件(导致li切换)。若不阻止冒泡,点击❌的时候会导致li切换toggleTab() 
            var index = this.parentNode.index; //也就是得到 所在li的索引号
            console.log(index);
            //根据索引号删除对应的li和section   remove()可以直接删除指定的元素
            that.lis[index].remove();
            that.sections[index].remove();
            //删除之后也要重新获取一下当前的元素
            that.init();
        }
    
        //4. 修改功能
        editTab() {}
    }
    
    //页面中可能会有很多Tab都需要使用这个功能,那就可以实例化不同的对象。
    var tab = new Tab('#tab');
    

    现在进一步优化删除操作:希望将选中的li删除之后,程序自动将其前一个li看作选中的li,否则会出现没有选中li的情况,如下:

    //3. 删除功能
    removeTab(e) {
        e.stopPropagation(); //阻止点击事件冒泡,❌有点击事件,li也有点击事件(导致li切换)。若不阻止冒泡,点击❌的时候会导致li切换toggleTab() 
        var index = this.parentNode.index; //也就是得到 所在li的索引号
        console.log(index);
        //根据索引号删除对应的li和section   remove()可以直接删除指定的元素
        that.lis[index].remove();
        that.sections[index].remove();
        //删除之后也要重新获取一下当前的元素
        that.init();
        //当我们删除了选中状态这个li的时候,让它的前一个li处于选中状态
        index--;
        that.lis[index].click(); //让前一个小li自动做一个点击动作
    }
    

    进一步优化:若当前是第一个li,那么点击删除之后,index==-1,程序就会报错,解决办法如下:

    //3. 删除功能
    removeTab(e) {
        e.stopPropagation(); //阻止点击事件冒泡,❌有点击事件,li也有点击事件(导致li切换)。若不阻止冒泡,点击❌的时候会导致li切换toggleTab() 
        var index = this.parentNode.index; //也就是得到 所在li的索引号
        console.log(index);
        //根据索引号删除对应的li和section   remove()可以直接删除指定的元素
        that.lis[index].remove();
        that.sections[index].remove();
        //删除之后也要重新获取一下当前的元素
        that.init();
        //当我们删除了选中状态这个li的时候,让它的前一个li处于选中状态
        index--;
        that.lis[index] && that.lis[index].click(); //如果有这个li(即索引号大于等于0),就让前一个小li自动做一个点击动作
    }
    

    有出现一个问题:若选中的li是第4个,要删除的li是第2个,那么在删除2之后,选中的li自动更换为第1个,我们希望的是选中的li不会更换,这样更友好。

    //3. 删除功能
    removeTab(e) {
        e.stopPropagation(); //阻止点击事件冒泡,❌有点击事件,li也有点击事件(导致li切换)。若不阻止冒泡,点击❌的时候会导致li切换toggleTab() 
        var index = this.parentNode.index; //也就是得到 所在li的索引号
        console.log(index);
        //根据索引号删除对应的li和section   remove()可以直接删除指定的元素
        that.lis[index].remove();
        that.sections[index].remove();
        //删除之后也要重新获取一下当前的元素
        that.init();
        //当我们删除了不是选中状态这个li的时候,原来选中状态的li保持不变
        if (document.querySelector(".liactive")) return; //如果当前还有选中状态的li,就不执行以下代码( 若只有一个if可以不加{})
        //当我们删除了选中状态这个li的时候,让它的前一个li处于选中状态
        index--;
        that.lis[index] && that.lis[index].click(); //如果有这个li(即索引号大于等于0),就让前一个小li自动做一个点击动作
    }
    

    window.getSelection?window.getSelection().removeAllRanges():document.section.empty();
    

    上述代码可以禁止双击时选中文字

    var that;
    class Tab {
        constructor(id) {
            that = this;
            //获取元素
            this.main = document.querySelector(id); //最大的Tab盒子
            this.add = this.main.querySelector('.tabadd');
            //li的父元素
            this.ul = this.main.querySelector('.fisrstnav ul:first-child');
            //section父元素
            this.fsection = this.main.querySelector('.tabscon');
            this.init(); //这里的this是实例对象,说明实例对象来调用的init(),那么init()里面的this都指向实例对象
        }
    
        //获取所有的li和section和❌
        updateNode() { //解决bug1
            this.lis = this.main.querySelectorAll('li'); //大盒子里面的li
            this.sections = this.main.querySelectorAll('section');
            //获取❌
            this.remove = this.main.querySelectorAll('.icon-guanbi');
            //获取span
            this.spans = this.main.querySelectorAll('.fisrstnav li span:first-child');
        }
    
        //初始化模块 让相关的元素绑定事件
        init() {
            this.updateNode(); //解决bug1
            this.add.onclick = this.addTab;
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].index = i;
                this.lis[i].onclick = this.toggleTab; //点击之后调用函数toggleTab()
                this.remove[i].onclick = this.removeTab;
                this.spans[i].ondblclick = this.editTab;
            }
        }
    
        //1. 切换功能
        toggleTab() {
            // console.log(this.index); //这个this指向当前的li,每个li都有一个index属性
            that.clearClass(); //必须要实例对象来调用这个函数
            this.className = "liactive";
            that.sections[this.index].className = "conactive"; //that指向实例化的对象(大盒子)
        }
    
        //清除其他"类"的函数
        clearClass() { //由于这里是实例对象that来调用该函数,所以该函数里的this依然指向的是调用者:实例对象Tab
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].className = '';
                this.sections[i].className = '';
            }
        }
    
        //2. 添加功能
        addTab() {
            that.clearClass();
            //创建li和section
            var random = Math.random();
            var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
            var section = '<section class="conactive">测试' + random + '</section>';
            //将li和section追加到父元素里
            that.ul.insertAdjacentHTML('beforeend', li);
            that.fsection.insertAdjacentHTML('beforeend', section);
            that.init(); //解决bug1
        }
    
        //3. 删除功能
        removeTab(e) {
            e.stopPropagation(); //阻止点击事件冒泡,❌有点击事件,li也有点击事件(导致li切换)。若不阻止冒泡,点击❌的时候会导致li切换toggleTab() 
            var index = this.parentNode.index; //也就是得到 所在li的索引号
            console.log(index);
            //根据索引号删除对应的li和section   remove()可以直接删除指定的元素
            that.lis[index].remove();
            that.sections[index].remove();
            //删除之后也要重新获取一下当前的元素
            that.init();
            //当我们删除了不是选中状态这个li的时候,原来选中状态的li保持不变
            if (document.querySelector(".liactive")) return; //如果当前还有选中状态的li,就不执行以下代码( 若只有一个if可以不加{})
            //当我们删除了选中状态这个li的时候,让它的前一个li处于选中状态
            index--;
            that.lis[index] && that.lis[index].click(); //如果有这个li(即索引号大于等于0),就让前一个小li自动做一个点击动作
        }
    
        //4. 修改功能
        editTab() {
            //双击禁止选定文字
            window.getSelection ? window.getSelection().removeAllRanges() : document.section.empty();
            //双击生成文本框
            this.innerHTML = '<input type="text" />'; //这个this指向当前被点击的span
        }
    }
    
    //页面中可能会有很多Tab都需要使用这个功能,那就可以实例化不同的对象。
    var tab = new Tab('#tab');
    

    完善

    //4. 修改功能
    editTab() {
        //这里的this指向当前被点击的span
        //先获取span中原先的文字
        var str = this.innerHTML;
        //双击禁止选定文字
        window.getSelection ? window.getSelection().removeAllRanges() : document.section.empty();
        //双击生成文本框
        this.innerHTML = '<input type="text" />';
        //获取文本框
        var input = this.children[0];
        //将原先span中的内容赋值给文本框
        input.value = str;
        //让文本框里的默认文字处于选定状态,这样用户可以直接删除或修改原先的内容,不需要一个字一个字地删
        input.select();
        //当文本框失去焦点,就将文本框里的值给span
        input.onblur = function() {
            //这里的this指向input
            this.parentNode.innerHTML = this.value; //this.parentNode即input的父亲即span
        }
    }
    

    继续优化:希望按下回车键,也可以将input内容给span

    //4. 修改功能
    editTab() {
        //这里的this指向当前被点击的span
        //先获取span中原先的文字
        var str = this.innerHTML;
        //双击禁止选定文字
        window.getSelection ? window.getSelection().removeAllRanges() : document.section.empty();
        //双击生成文本框
        this.innerHTML = '<input type="text" />';
        //获取文本框
        var input = this.children[0];
        //将原先span中的内容赋值给文本框
        input.value = str;
        //让文本框里的默认文字处于选定状态,这样用户可以直接删除或修改原先的内容,不需要一个字一个字地删
        input.select();
        //当文本框失去焦点,就将文本框里的值给span
        input.onblur = function() {
                //这里的this指向input
                this.parentNode.innerHTML = this.value; //this.parentNode即input的父亲即span
            }
            // 按下回车键,也可以将input内容给span  
        input.onkeyup = function(e) {
            //这里的this指向input
            if (e.keyCode === 13) { //回车键的ASCII是13
                this.blur(); //手动调用失去焦点事件  不用加on
            }
        }
    }
    

    下面继续写对section修改内容

    //初始化模块 让相关的元素绑定事件
        init() {
            this.updateNode(); //解决bug1
            this.add.onclick = this.addTab;
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].index = i;
                this.lis[i].onclick = this.toggleTab; //点击之后调用函数toggleTab()
                this.remove[i].onclick = this.removeTab;
                this.spans[i].ondblclick = this.editTab;
                this.sections[i].ondblclick = this.editTab;
            }
        }
    
  • 相关阅读:
    机器学习
    机器学习
    JavaWeb之tomcat安装、配置与使用(一)
    Tomcat安装、配置和部署笔记
    Java配置----JDK开发环境搭建及环境变量配置
    安装SQL2012
    SQLServer 数据库变成单个用户后无法访问问题的解决方法
    临时记录
    SQL Server 动态生成数据库所有表Insert语句
    SQL2000查看表的大小
  • 原文地址:https://www.cnblogs.com/deer-cen/p/12376320.html
Copyright © 2011-2022 走看看