JS面向对象案例(1)-Tab栏切换

功能需求实现

  1. 点击tab栏,可以切换标签页
  2. 点击+号,可以添加tab栏和内容项
  3. 点击x号,可以删除当前的tab项和内容项
  4. 双击tab项文字或者内容项文字,可以修改里面的文字内容

 抽象对象:Tab对象

  1. 该对象具有切换功能
  2. 该对象具有添加功能
  3. 该对象具有删除功能
  4. 该对象具有修改功能shoxain
class Tab {
    constructor() {

    }
    //1.切换功能
    toggleTab() {}
    //2.添加功能
    addTab() {}
    // 3.删除功能
    removeTab() {}
    // 4.修改功能
    editTab() {}
}
new Tab('#tab');

初始化对象 首先初始化 给相关元素绑定事件

class Tab {
    constructor(id) {
        //获取元素
        this.main = document.querySelector(id);
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
        this.init();
    }
    // 初始化
    init(){
        // init 初始化操作让相关元素绑定事件
        for(var i =0;i<this.lis.length;i++){
            // 存的是小li的索引号
            this.lis[i].index = i;
            this.lis[i].onclick = function() {
                console.log(this.index);//测试一下看是不是绑定成功了
            }
        }
    }
    //1.切换功能
    toggleTab() {}
    //2.添加功能
    addTab() {}
    // 3.删除功能
    removeTab() {}
    // 4.修改功能
    editTab() {}
}
new Tab('#tab');

 1.切换功能模块

var that;
class Tab {
    constructor(id) {
        //获取元素
        this.main = document.querySelector(id);
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
        this.init();
        that = this;
    }
    // 初始化
    init(){
        // init 初始化操作让相关元素绑定事件
        for(var i =0;i<this.lis.length;i++){
            // 存的是小li的索引号
            this.lis[i].index = i;
            this.lis[i].onclick = this.toggleTab;
        }
    }
    //1.切换功能
    toggleTab() {
        // !!!!!一定注意this的指向问题
        // console.log(this.index);
        // 如果必须要清除所有样式 呢么必须使用最大的对象 也就是constructor里面的对象this
        that.clearClass();
        this.className = 'liactive';
        // 必须用constrcutor 所以用that变量来使用另一个this this指向的lis[i]里面没有sections
        that.sections[this.index].className = 'conactive';
    }
    clearClass() {
        for(var i = 0;i<this.lis.length;i++){
            this.lis[i].className = '';
            this.sections[i].className = '';
        }
    }
    //2.添加功能
    addTab() {}
    // 3.删除功能
    removeTab() {}
    // 4.修改功能
    editTab() {}
}
new Tab('#tab');

2.添加功能模块

思路理解:

  1. 点击+号,可以添加tab栏和内容项
  2. 第一步 必须创建新的选项卡li和新的内容section
  3. 第二步 把创建的两个元素追加到对应的父元素里面去了

补充知识点:insertAdjacentHTML()

作用:

方法将指定的文本解析为 Element 元素,并将结果节点插入到 DOM 树中的指定位置。它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素。这避免了额外的序列化步骤,使其比直接使用 innerHTML 操作更快。 

参考链接:https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentHTML

基础语法:

element.insertAdjacentHTML(position, text);

var that;
class Tab {
    constructor(id) {
        that = this;
        //获取元素
        this.main = document.querySelector(id);
        this.add = this.main.querySelector('.tabadd');
        // li的父元素
        // css3选择器
        this.ul = this.main.querySelector('.fisrstnav ul:first-child');
        this.fsection = this.main.querySelector('.tabscon');
        this.init();
    }
    // 获取所有的li和section
    updateNode() {
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
    }
    // 初始化
    init(){
        this.updateNode();
        this.add.onclick = this.addTab;
        // init 初始化操作让相关元素绑定事件
        for(var i =0;i<this.lis.length;i++){
            // 存的是小li的索引号
            this.lis[i].index = i;
            this.lis[i].onclick = this.toggleTab;
        }
    }
    //1.切换功能
    toggleTab() {
        // !!!!!一定注意this的指向问题
        // console.log(this.index);
        // 如果必须要清除所有样式 呢么必须使用最大的对象 也就是constructor里面的对象this
        that.clearClass();
        this.className = 'liactive';
        // 必须用constrcutor 所以用that变量来使用另一个this this指向的lis[i]里面没有sections
        that.sections[this.index].className = 'conactive';
    }
    clearClass() {
        for(var i = 0;i<this.lis.length;i++){
            this.lis[i].className = '';
            this.sections[i].className = '';
        }
    }
    //2.添加功能
    addTab() {
        that.clearClass();
        var random = Math.random();
        // alert(11); 测试用例
        var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
        var section = '<section class="conactive">测试1'+random+'</section>';
        that.ul.insertAdjacentHTML('beforeend',li);
        that.fsection.insertAdjacentHTML('beforeend',section);
        that.init();
    }
    // 3.删除功能
    removeTab() {}
    // 4.修改功能
    editTab() {}
}
new Tab('#tab');

3.删除功能模块

!!!y要注意元素的值是有变化的 所以必须实时更新数据

补充知识

remove()方法:Element.remove() 方法,把对象从它所属的 DOM 树中删除。

参考链接:https://developer.mozilla.org/zh-CN/docs/Web/API/Element/remove

 语法使用:

node.remove();
var that;
class Tab {
    constructor(id) {
        that = this;
        //获取元素
        this.main = document.querySelector(id);
        this.add = this.main.querySelector('.tabadd');
        // li的父元素
        // css3选择器
        this.ul = this.main.querySelector('.fisrstnav ul:first-child');
        this.fsection = this.main.querySelector('.tabscon');
        this.init();
    }
    // 获取所有的li和section
    updateNode() {
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
        this.remove = this.main.querySelectorAll('.icon-guanbi');
    }
    // 初始化
    init(){
        this.updateNode();
        this.add.onclick = this.addTab;
        // init 初始化操作让相关元素绑定事件
        for(var i =0;i<this.lis.length;i++){
            // 存的是小li的索引号
            this.lis[i].index = i;
            this.lis[i].onclick = this.toggleTab;
            this.remove[i].onclick = this.removeTab;
        }
    }
    //1.切换功能
    toggleTab() {
        // !!!!!一定注意this的指向问题
        // console.log(this.index);
        // 如果必须要清除所有样式 呢么必须使用最大的对象 也就是constructor里面的对象this
        that.clearClass();
        this.className = 'liactive';
        // 必须用constrcutor 所以用that变量来使用另一个this this指向的lis[i]里面没有sections
        that.sections[this.index].className = 'conactive';
    }
    clearClass() {
        for(var i = 0;i<this.lis.length;i++){
            this.lis[i].className = '';
            this.sections[i].className = '';
        }
    }
    //2.添加功能
    addTab() {
        that.clearClass();
        var random = Math.random();
        // alert(11); 测试用例
        var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
        var section = '<section class="conactive">测试1'+random+'</section>';
        that.ul.insertAdjacentHTML('beforeend',li);
        that.fsection.insertAdjacentHTML('beforeend',section);
        that.init();
    }
    // 3.删除功能
    removeTab(e) {
        // 消除冒泡现象 防止触发li的点击事件
        e.stopPropagation();
        var index  = this.parentNode.index;
        console.log(index);
        // Element.remove() 方法,把对象从它所属的 DOM 树中删除。
        that.lis[index].remove();
        that.sections[index].remove();
        that.init();
        //如果有选定状态了 呢么就不需要调用下面的点击事件  直接返回就好了
        if(document.querySelector('.liactive')) return;
        // 当我们删除了选定状态的li的时候 让他的前一个li赋予选定状态
        index--;
        //手动调用点击事件 不需要鼠标来触发
        //前面为真才触发
        that.lis[index]&&that.lis[index].click();
    }
    // 4.修改功能
    editTab() {}
}
new Tab('#tab');

 4.编辑功能

 核心思路:双击文字的时候 在里面生成一个文本框 当失去焦点或者按下回车然后把文本框输入的值给原先元素即可。

var that;
class Tab {
    constructor(id) {
        that = this;
        //获取元素
        this.main = document.querySelector(id);
        this.add = this.main.querySelector('.tabadd');
        // li的父元素
        // css3选择器
        this.ul = this.main.querySelector('.fisrstnav ul:first-child');
        this.fsection = this.main.querySelector('.tabscon');
        this.init();
    }
    // 获取所有的li和section
    updateNode() {
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
        this.remove = this.main.querySelectorAll('.icon-guanbi');
        this.spans = this.main.querySelectorAll('.fisrstnav li span:first-child');
    }
    // 初始化
    init(){
        this.updateNode();
        this.add.onclick = this.addTab;
        // init 初始化操作让相关元素绑定事件
        for(var i =0;i<this.lis.length;i++){
            // 存的是小li的索引号
            this.lis[i].index = i;
            this.lis[i].onclick = this.toggleTab;
            this.remove[i].onclick = this.removeTab;
            // 鼠标双击事件
            this.spans[i].ondblclick = this.editTab;
            this.sections[i].ondblclick = this.editTab;
        }
    }
    //1.切换功能
    toggleTab() {
        // !!!!!一定注意this的指向问题
        // console.log(this.index);
        // 如果必须要清除所有样式 呢么必须使用最大的对象 也就是constructor里面的对象this
        that.clearClass();
        this.className = 'liactive';
        // 必须用constrcutor 所以用that变量来使用另一个this this指向的lis[i]里面没有sections
        that.sections[this.index].className = 'conactive';
    }
    clearClass() {
        for(var i = 0;i<this.lis.length;i++){
            this.lis[i].className = '';
            this.sections[i].className = '';
        }
    }
    //2.添加功能
    addTab() {
        that.clearClass();
        var random = Math.random();
        // alert(11); 测试用例
        var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
        var section = '<section class="conactive">测试1'+random+'</section>';
        that.ul.insertAdjacentHTML('beforeend',li);
        that.fsection.insertAdjacentHTML('beforeend',section);
        that.init();
    }
    // 3.删除功能
    removeTab(e) {
        // 消除冒泡现象 防止触发li的点击事件
        e.stopPropagation();
        var index  = this.parentNode.index;
        console.log(index);
        // Element.remove() 方法,把对象从它所属的 DOM 树中删除。
        that.lis[index].remove();
        that.sections[index].remove();
        that.init();
        //如果有选定状态了 呢么就不需要调用下面的点击事件  直接返回就好了
        if(document.querySelector('.liactive')) return;
        // 当我们删除了选定状态的li的时候 让他的前一个li赋予选定状态
        index--;
        //手动调用点击事件 不需要鼠标来触发
        //前面为真才触发
        that.lis[index]&&that.lis[index].click();
    }
    // 4.修改功能
    editTab() {
        // 把span里面原先的文字内容赋值给一个str变量
        var str = this.innerHTML;
        // 双击禁止选定文字
        window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
        // alert(11);
        this.innerHTML = '<input type="text"/>'
        var input = this.children[0];
        input.value = str;
        // 文本框里的文字处于选定状态
        input.select();
        // 当我们离开文本框 把值给span
        // onblur失去焦点事件
        input.onblur = function() {
            this.parentNode.innerHTML = this.value;
        }
        //按下回车也可以把文本框里面的值给span
        input.onkeyup = function(e) {
            if(e.keyCode === 13){
                this.blur();
            }
        }
    }
}
new Tab('#tab');

注:案例所需要的html和css 

链接:https://pan.baidu.com/s/1A4LmUbFEhHT6lYVrw00Zxg?pwd=1234 

每天一个自我思考:面向对象和面向过程的区别是什么?评论区告诉我!!!!  

 

下期重磅预告:js原型链 构造函数.........................

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值