高级JavaScript Day01学习总结—— 面向对象、ES6 中的类和对象、类的继承、案例:面向对象版tab 栏切换

1.面向对象编程介绍

1.1 两大编程思想

  • 面向过程
  • 面向对象

1.2 面向过程编程

面向过程编程的英文缩写是 POP(Process-oriented programming), “process”意为“过程”,“oriented”意为“面向”,“programming”在这里意为“编程”; 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。

比如 将大象装入冰箱的面向过程做法:打开冰箱门->大象装进去->关上冰箱门

总结:面向过程是按照我们分析好了的步骤,按照步骤解决问题

1.3 面向对象编程

面向对象编程的英文缩写为:OOP(Object Oriented Programming),“object”意为“对象”。

面向对象是把事务分解成为一个个对象然后由对象之间分工与合作

举个栗子:将大象装进冰箱,面向对象做法。
先找出对象,并写出这些对象的功能

  1. 大象对象
  • 进去

2.冰箱对象

  • 打开
  • 关闭

3.使用大象和冰箱的功能

总结:面向对象是将需求分析出一个一个的对象,然后在分析出对象中的属性和方法,最后按照步骤解决问题。

1.4 面向过程和面向对象的对比

面向过程面向对象
优点:性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程优点:优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护
缺点:没有面向对象易维护、易复用、易扩展缺点:性能比面向过程低

应用场景

  • 比较简单的逻辑,使用面向过程。
  • 比较复杂的逻辑,使用面向对象。

2.ES6中的类和对象

面向对象分为 具体的事物抽象的事物

  • 手机 是抽象的(指的)
  • 小米手机、华为手机(指的)

面向对象的思维特点:

  • 抽取(抽象)对象 共用的属性 和 行为组织 (封装)成一个类(模板)
  • 对类进行实例化, 获取类的对象

2.1 对象

现实生活中:万物皆对象,对象是一个具体的事物,看得见摸得着的实物。例如,一本书、一辆汽车、一个人可以是“对象”,一个数据库、一张网页、一个与远程服务器的连接也可以是“对象”。

在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象。例如字符串(String)、数值(Number)、数组、函数等。

对象是由 属性方法 组成的:

  • 属性:事物的 特征,在对象中用 属性 来表示(常用词)
  • 方法:事物的 行为,在对象中用 方法 来表示(常用词)

2.2 类 class

在 ES6 中新增加了类的概念,用 class 关键字 声明一个类,之后以这个类来实例化对象。

抽象了对象的公共部分,类泛指某一大类(class)对象特指某一个,通过类实例化一个具体的对象

汽车设计图纸(类) 、 一辆真实的宝马(对象的实例)

2.3 创建类

通过class 关键字创建类

class name {
  // class body
}  

创建实例

// 利用类创建对象 注意 new关键字
var xx = new name(); 

注意: 类必须使用 new 实例化对象

示例化代码

  <script>
      //1. 通过 class 关键字 创建一个 Star类 
        class Star {   //类名习惯性定义首字母大写
            constructor(uname, age) {  //构造函数constructor 不需要加function
                this.uname = uname;
                this.age = age
            }
        }
        // 2. 利用类创建对象 new
        let zj = new Star("张杰", 18)  //生成实例对象后面要加小括号
        let zxy = new Star("张学友", 20)
        console.log(zj)
        console.log(zxy)

        //(1) 通过 class 关键字创建类, 类名我们还是习惯性定义首字母大写
        //(2) 类里面有个 constructor 函数,可以接受传递过来的参数,同时返回实例对象
        //(3) constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数
        //(4) 生成实例 new 不能省略
        //(5) 最后注意语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function
    </script>

控制台打印输出:

在这里插入图片描述

2.4 类 constructor 构造函数

  • constructor()方法是类的构造函数(默认方法),用于传递参数,返回实例对象
  • 通过 new 命令生成对象实例时,自动调用该方法。
  • 如果没有显示定义, 类内部会自动给我们创建一个constructor()

语法:

class Person {
  constructor(name,age) {   // constructor 构造方法或者构造函数
      this.name = name;
      this.age = age;
    }
}   

创建实例:

var zj = new Person('张杰', 18); 
console.log(zj.name)  

2.5 类添加方法

语法:

class Person {
  constructor(name,age) {   // constructor 构造器或者构造函数
      this.name = name;
      this.age = age;
    }
    //方法之间不能加逗号分隔,同时方法不需要添加 function 关键字
   say() {
      console.log(this.name + '你好');
   }
} 

创建实例:

var zj = new Person('张杰', 18); 
zj.say() 

注意👑:

  • 方法之间不能加逗号分隔,同时方法不需要添加 function 关键字
  • 类里面所有的函数不需要写function
  • 多个函数方法之间不需要添加逗号分隔

示例化代码

<script>
    
        // 1. 创建类 class  创建一个 明星类
        class Star {
            // 类的共有属性放到 constructor 里面
            constructor(name, age) {
                this.name = name;
                this.age = age;
            }
            sing(song) {
                console.log(this.name + song);

            }
        }

        // 2. 利用类创建对象 new实例化对象Star
        var zj = new Star('张杰', 18);
        var zxy = new Star('张学友', 20);
        console.log(zj);
        console.log(zxy);
        // (1) 我们类里面所有的函数不需要写function 
        //(2) 多个函数方法之间不需要添加逗号分隔
        zj.sing('剑伤');
        zxy.sing('李香兰');
   
    </script>

3.类的继承

3.1 继承

现实中的继承:子承父业,比如我们都继承了父亲的姓

程序中的继承:子类可以继承父类的一些属性和方法

语法:

class Father{   // 父类
} 
class  Son extends Father {  // 子类继承父类
}  

实例:

class Father {
      constructor(surname) {
        this.surname= surname;
      }
      say() {
        console.log('你的姓是' + this.surname);

       }
}
class Son extends Father{  // 这样子类就继承了父类的属性和方法

}
var damao= new Son('刘');
damao.say(); 

3.2 super关键字

super 关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数

语法:

class Person {   // 父类
      constructor(surname){
         this.surname = surname;
     }
} 
class  Student extends Person {       // 子类继承父类
     constructor(surname,firstname){
          super(surname);             // 调用父类的constructor(surname)
	this.firstname = firstname; // 定义子类独有的属性
     }
}  

注意: 子类在构造函数中使用super, 必须放到 this 关键字之前 (必须先调用父类的构造方法,再使用子类构造方法)

案例:

 class Father {
    constructor(surname) {
        this.surname = surname;
     }
    saySurname() {
      console.log('我的姓是' + this.surname);
    }
}
class Son extends Father { // 这样子类就继承了父类的属性和方法
    constructor(surname, fristname) {
       //子类在构造函数中使用super, 必须放到 this 关键字之前
         super(surname);   // 调用父类的constructor(surname)
         this.fristname = fristname;
     }
    sayFristname() {
         console.log("我的名字是:" + this.fristname);
    }
}
var damao = new Son('刘', "德华");
damao.saySurname();
damao.sayFristname();    

super关键字 用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数

示例:

<script>
// 父类有加法方法
        class Father {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }
            sum() {
                console.log(this.x + this.y);
            }
        }
        // 子类继承父类加法方法 同时 扩展减法方法
        class Son extends Father {
            //固定写法:如果重写构造函数,就必须先调用super(x,y),并且是在第一行
            constructor(x, y) {
                // ⭐利用super 调用父类的构造函数
                // ⭐super 必须在子类this之前调用
                super(x, y);
                this.x = x;
                this.y = y;

            }
            //子类扩展减法方法
            subtract() {
                console.log(this.x - this.y);

            }
        }
        var son = new Son(5, 3);
        son.subtract();
        son.sum();
    </script>

三个注意点:

  • 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象.
  • 类里面的共有属性和方法一定要加this使用.
  • 类里面的⭐this指向问题.
  • constructor 里面的this指向实例对象, 方法里面的this 指向这个方法的调用者
<body>
    <button>点击</button>
    <script>
        var that;
        var _that;
        class Star {
            constructor(uname, age) {
                // constructor 里面的this 指向的是 创建的实例对象
                that = this;
                console.log(this);

                this.uname = uname;
                this.age = age;
                // this.sing();
                this.btn = document.querySelector('button');
                this.btn.onclick = this.sing;
            }
            sing() {
                // 这个sing方法里面的this 指向的是 btn 这个按钮,因为这个按钮调用了这个函数
                console.log(this);

                console.log(that.uname); // that里面存储的是constructor里面的this
            }
            dance() {
                // 这个dance里面的this 指向的是实例对象 ldh 因为ldh 调用了这个函数
                _that = this;
                console.log(this);

            }
        }

        var ldh = new Star('刘德华');
        console.log(that === ldh);
        ldh.dance();
        console.log(_that === ldh);

        // 1. 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象

        // 2. 类里面的共有的属性和方法一定要加this使用.
    </script>
</body>

4.面向对象案例:面向对象版 tab 栏切换

4.1 功能需求

  • 点击 tab栏,可以切换效果. (toggleTab)
  • 点击 + 号, 可以添加 tab 项和内容项.(addTab)
  • 点击 x 号, 可以删除当前的tab项和内容项.(removeAdd)
  • 双击tab项文字或者内容项文字,可以修改里面的文字内容 (editTab)

tab栏目切换实例图:

在这里插入图片描述

4.2 面向对象版tab 栏切换相关代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>面向对象 Tab</title>
    <link rel="stylesheet" href="./styles/tab.css">
    <link rel="stylesheet" href="./styles/style.css">
</head>

<body>

    <main>
        <h4>
            Js 面向对象 动态添加标签页
        </h4>
        <div class="tabsbox" id="tab">
            <!-- tab 标签 -->
            <nav class="fisrstnav">
                <ul>
                    <li class="liactive"><span>测试1</span><span class="iconfont icon-guanbi"></span></li>
                    <li><span>测试2</span><span class="iconfont icon-guanbi"></span></li>
                    <li><span>测试3</span><span class="iconfont icon-guanbi"></span></li>
                </ul>
                <div class="tabadd">
                    <span>+</span>
                </div>
            </nav>


            <!-- tab 内容 -->
            <div class="tabscon">
                <section class="conactive">测试1</section>
                <section>测试2</section>
                <section>测试3</section>
            </div>
        </div>
    </main>

    <script src="js/tab.js">
    </script>
</body>

</html>
index.css 
* {
    margin: 0;
    padding: 0;
}

ul li {
    list-style: none;
}

main {
    width: 960px;
    height: 500px;
    border-radius: 10px;
    margin: 50px auto;
}

main h4 {
    height: 100px;
    line-height: 100px;
    text-align: center;
}

.tabsbox {
    width: 900px;
    margin: 0 auto;
    height: 400px;
    border: 1px solid lightsalmon;
    position: relative;
}

nav ul {
    overflow: hidden;
}

nav ul li {
    float: left;
    width: 100px;
    height: 50px;
    line-height: 50px;
    text-align: center;
    border-right: 1px solid #ccc;
    position: relative;
}

nav ul li.liactive {
    border-bottom: 2px solid #fff;
    z-index: 9;
}

#tab input {
    width: 80%;
    height: 60%;
}

nav ul li span:last-child {
    position: absolute;
    user-select: none;
    font-size: 12px;
    top: -18px;
    right: 0;
    display: inline-block;
    height: 20px;
}

.tabadd {
    position: absolute;
    /* width: 100px; */
    top: 0;
    right: 0;
}

.tabadd span {
    display: block;
    width: 20px;
    height: 20px;
    line-height: 20px;
    text-align: center;
    border: 1px solid #ccc;
    float: right;
    margin: 10px;
    user-select: none;
}

.tabscon {
    width: 100%;
    height: 300px;
    position: absolute;
    padding: 30px;
    top: 50px;
    left: 0px;
    box-sizing: border-box;
    border-top: 1px solid #ccc;
}

.tabscon section,
.tabscon section.conactive {
    display: none;
    width: 100%;
    height: 100%;
}

.tabscon section.conactive {
    display: block;
}

tab.js

模块划分:实例化对象Tab,Tab里面有四个我们需要完成的功能分别是 切换功能 、 添加功能、删除功能、修改功能(接下来分别一一来完成这四个功能),每个类有一个constructor用来接收传递过来的参数,然后获取元素,时刻注意this的指向问题页面一加载给所有的元素绑定每一个事件,init 初始化操作让相关的元素绑定事件。

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() {
        // init 初始化操作让相关的元素绑定事件
        for (var i = 0; i < this.lis.length; i++) {
            this.lis[i].index = i;   //让每个小li都有一个单独的索引号
            this.lis[i].onclick = function() {
                console.log(this.index);
            };
        }
    };
    // 1. 切换功能
    toggleTab() {

    };
    // 2. 添加功能
    addTab() {

    };
    // 3. 删除功能
    removeTab() {

    };
    // 4. 修改功能
    editTab() {

    };

};
new Tab('#tab');
4.2.1 切换功能

当我们点击了某个小li,此时就可以做切换功能,特别注意this的指向问题,我们把 constructor里面的this复制给了全局变量that,然后可以在 toggleTab 里面调用 clearClass方法sections

let that;
class Tab {
    constructor(id) {
        that = this //将constructor中的this赋值给that,在事件函数中使用
        // 获取元素
        this.main = document.querySelector(id);
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
        this.init(); //(在此调用原因)想要页面一打开一加载就立马调用init()
    }
    init() {
        // init 初始化操作让相关的元素绑定事件
        for (var i = 0; i < this.lis.length; i++) {
            // 让每个li都有索引
            this.lis[i].index = i; //让每个小li都有一个单独的索引号
            this.lis[i].onclick = this.toggleTab; //注意这里的toggleTab不要加括号,我们需要点击完之后再调用
        };
    };

   // 1. 切换功能 (这个方法是li点击事件的处理程序,所以this指向的是点击的li)
    toggleTab() { // 区分方法:是否为事件处理程序,如果是,那么this指向事件源
        that.clearClass(); //调用实例对象的clearClass方法
        this.className = 'liactive';
        that.sections[this.index].className = 'conactive'; //让对应的section显示
    };
    // 清除所有li 和section 的类
    clearClass() {
           //clearClass是用that来调用的,constructor中的that = this 
            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');
4.2.2 添加功能

1. 点击 + 可以实现添加新的选项卡内容
2. 第一步: 创建新的选项卡li 和 新的 内容 section
3. 第二步: 把创建的两个元素追加到对应的父元素中.
4. 以前的做法: 动态创建元素 createElement , 但是元素里面内容较多, 需要innerHTML赋值,在 appendChild 追加到父元素里面.
5.(现在)动态创建元素高级做法: 利用 insertAdjacentHTML() 可以直接把字符串格式元素添加到父元素中
5. appendChild 不支持追加字符串的子元素, insertAdjacentHTML 支持追加字符串的元素
6. insertAdjacentHTML( 追加的位置 , ‘要追加的字符串元素’ )
7. 追加的位置有: beforeend 插入元素内部的最后一个子节点之后
8. insertAdjacentHTML方法地址:

https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentHTML 

添加:

var that;
class Tab {
    constructor(id) {
        // 获取元素
        that = this;
        this.main = document.querySelector(id);
        // 删掉以下两行,放到updateNode方法中
        // this.lis = this.main.querySelectorAll('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();
    }
    init() {
        //每次初始化都要调用更新节点方法
        this.updateNode();
        // 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;

        }
    };
    // 因为我们动态添加元素 需要从新获取对应的元素
    updateNode() {
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
    };
    // 1. 切换功能
    toggleTab() {
        // console.log(this.index);
        that.clearClass();
        this.className = 'liactive';
        that.sections[this.index].className = 'conactive';
    };
    // 清除所有li 和 section 的类
    clearClass() {
        for (var i = 0; i < this.lis.length; i++) {
            this.lis[i].className = '';
            this.sections[i].className = '';
        }
    };
    // 2. 添加功能
    addTab() {
        that.clearClass();
        // (1) 创建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>';
        // (2) 把这两个元素追加到对应的父元素里面
        that.ul.insertAdjacentHTML('beforeend', li);
        that.fsection.insertAdjacentHTML('beforeend', section);
        that.init();
    };
    // 3. 删除功能
    removeTab(e) {

    };
    // 4. 修改功能
    editTab() {

    };

};
new Tab('#tab');
4.2.3 删除功能
  • 点击 × 可以删除当前的 li选项卡当前的section
  • X 是没有索引号的, 但是它的 父亲li 有索引号, 这个索引号正是我们想要的索引号
  • 所以核心思路是: 点击 x 号 可以删除 这个索引号对应的 lisection
  • 但是,当我们动态删除 新的li 和 索引号时,也需要重新获取 x 这个元素. 需要调用init 方法
var that;
class Tab {
    constructor(id) {
        // 获取元素
        that = this;
        this.main = document.querySelector(id);
        // 删掉以下两行,放到updateNode方法中
        // this.lis = this.main.querySelectorAll('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();
    }
    init() {
        this.updateNode();
        // 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;
            this.remove[i].onclick = this.removeTab;

        }
    };
    // 因为我们动态添加元素 需要从新获取对应的元素
    updateNode() {
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
        this.remove = this.main.querySelectorAll('.icon-guanbi');
    };
    // 1. 切换功能
    toggleTab() {
        // console.log(this.index);
        that.clearClass();
        this.className = 'liactive';
        that.sections[this.index].className = 'conactive';
    };
    // 清除所有li 和section 的类
    clearClass() {
        for (var i = 0; i < this.lis.length; i++) {
            this.lis[i].className = '';
            this.sections[i].className = '';
        }
    };
    // 2. 添加功能
    addTab() {
        that.clearClass();
        // (1) 创建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>';
        // (2) 把这两个元素追加到对应的父元素里面
        that.ul.insertAdjacentHTML('beforeend', li);
        that.fsection.insertAdjacentHTML('beforeend', section);
        that.init();
    };
    // 3. 删除功能
    removeTab(e) {
        e.stopPropagation(); // 阻止冒泡 防止触发li 的切换点击事件
        var index = this.parentNode.index;
        console.log(index);
        // 根据索引号删除对应的li 和section   remove()方法可以直接删除指定的元素
        that.lis[index].remove();
        that.sections[index].remove();
        // that.init();
        // 当我们删除的不是选中状态的li 的时候,原来的选中状态li保持不变
        if (document.querySelector('.liactive')) return;
        // 当我们删除了选中状态的这个li 的时候, 让它的前一个li 处于选定状态
        index--;
        // 手动调用我们的点击事件  不需要鼠标触发
        that.lis[index] && that.lis[index].click();
    };
    // 4. 修改功能
    editTab() {

    };

};
new Tab('#tab');
4.2.4 编辑功能
  • 双击选项卡li或者 section里面的文字,可以实现修改功能
  • 双击事件是: ondblclick
  • 如果双击文字,会默认选定文字,此时需要双击禁止选中文字
  • window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
  • 核心思路: 双击文字的时候, 在 里面生成一个文本框, 当失去焦点或者按下回车然后把文本框输入的值给原先元素即可.
var that;
class Tab {
    constructor(id) {
        // 获取元素
        that = this;
        this.main = document.querySelector(id);
        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();
    }
    init() {
            this.updateNode();
            // 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;
                this.remove[i].onclick = this.removeTab;
                this.spans[i].ondblclick = this.editTab;
                //section添加双击事件,可以编辑
                this.sections[i].ondblclick = this.editTab;
            }
        }
        // 因为我们动态添加元素 需要从新获取对应的元素
    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');
        }
        // 1. 切换功能
    toggleTab() {
            // console.log(this.index);
            that.clearClass();
            this.className = 'liactive';
            that.sections[this.index].className = 'conactive';
        }
        // 清除所有li 和section 的类
    clearClass() {
            for (var i = 0; i < this.lis.length; i++) {
                this.lis[i].className = '';
                this.sections[i].className = '';
            }
        }
        // 2. 添加功能
    addTab() {
            that.clearClass();
            // (1) 创建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>';
            // (2) 把这两个元素追加到对应的父元素里面
            that.ul.insertAdjacentHTML('beforeend', li);
            that.fsection.insertAdjacentHTML('beforeend', section);
            that.init();
        }
        // 3. 删除功能
    removeTab(e) {
        e.stopPropagation(); // 阻止冒泡 防止触发li 的切换点击事件
        var index = this.parentNode.index;
        console.log(index);
        // 根据索引号删除对应的li 和section   remove()方法可以直接删除指定的元素
        that.lis[index].remove();
        that.sections[index].remove();
        that.init();
        // 当我们删除的不是选中状态的li 的时候,原来的选中状态li保持不变
        if (document.querySelector('.liactive')) return;
        // 当我们删除了选中状态的这个li 的时候, 让它的前一个li 处于选定状态
        index--;
        // 手动调用我们的点击事件  不需要鼠标触发
        that.lis[index] && that.lis[index].click();
    };
    // 4. 修改功能
    editTab() {
        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 
        input.onblur = function() {
            this.parentNode.innerHTML = this.value;
        };
        // 按下回车也可以把文本框里面的值给span
        input.onkeyup = function(e) {
            if (e.keyCode === 13) {
                // 手动调用表单失去焦点事件  不需要鼠标离开操作
                this.blur();
            }
        }
    };

}
new Tab('#tab');
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心平气荷.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值