2、super 关键字
super 关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数。
- 调用构造函数(super作为函数时的使用)
//定义了父类 class Father { constructor(x, y) { this.x = x; this.y = y; } sum() { console.log(this.x + this.y); } } //子元素继承父类 class Son extends Father { constructor(x, y) { super(x, y); //使用super调用了父类中的构造函数 } } var son = new Son(1, 2); son.sum(); //结果为3
- 调用普通函数(super作为对象时的使用)
class Father { say() { return "我是爸爸"; } } class Son extends Father { say() { console.log(super.say() + "的儿子"); // super.say() 调用父类的普通函数 } } var son = new Son(); son.say(); // 我是爸爸的儿子
- 子类拓展自己方法
// 父类有加法方法 class Father { constructor(x, y) { this.x = x; this.y = y; } sum() { console.log(this.x + this.y); } } // 子类继承父类加法方法 同时 扩展减法方法 class Son extends Father { constructor(x, y) { // 利用super 调用父类的构造函数 super 必须在子类this之前调用,放到this之后会报错 super(x, y); this.x = x; this.y = y; } substract() { console.log(this.x - this.y); } } var son = new Son(5, 3); son.substract(); // 2 son.sum(); // 8
注意:(查找原则以及调用父类普通函数方法)
- 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的。
- 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)。
- 如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用 super 调用父类的构造函数,super 必须在子类this之前调用。
3、使用类的注意事项
- 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象。
- 类里面使用公有属性和方法的时候,必须通过this去调用。
- 时刻注意this的指向问题,类里面的共有的属性和方法一定要加this使用。
- constructor 中的this指向的是new出来的实例对象。
- 自定义的方法,一般也指向的new出来的实例对象。
- 绑定事件之后this指向的就是触发事件的事件源。
四、面向对象版tab 栏切换
1、功能需求
- 点击 tab栏,可以切换效果 (切换)
- 点击 + 号, 可以添加 tab 项和内容项(添加)
- 点击 x 号, 可以删除当前的tab项和内容项(删除)
- 双击tab项文字或者内容项文字可以修改里面的文字内容(修改)
2、案例准备
抽取对象:
1、该对象具有切换功能
2、该对象具有添加功能
3、该对象具有删除功能
4、该对象具有修改功能
核心代码:
var that = null; class Tab { constructor(id) { that = this; // 获取元素 this.main = document.querySelector(id); // 获取所有的 li this.lis = this.main.querySelectorAll("li"); // 获取所有的 section this.sections = this.main.querySelectorAll("section"); // 实例化对象就进行初始化 this.init(); } // 初始化函数,给相关元素绑定事件 init() { this.updateNode(); 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() {} } var tab = new Tab("#tab");
3、切换功能
核心代码:
// 1、切换 toggleTab() { that.clearClass(); this.className = "liactive"; that.sections[this.index].className = "conactive"; } // 排他思想,清除其他类名 clearClass() { for (let i = 0; i < this.lis.length; i++) { this.lis[i].className = ""; this.sections[i].className = ""; } }
4、添加功能
实现思路:
1、创建新的选项卡 li 和新的内容 section。
2、把创建的两个元素追加到对应的父元素中。
补充:直接将字符串插入到 dom 节点中 insertAdjacentHTML
,点击查看文档 。
核心代码
// 重新获取元素 updateNode() { this.lis = this.main.querySelectorAll("li"); this.sections = this.main.querySelectorAll("section"); } // 2、添加功能 addTab() { that.clearClass(); var random = Math.random(); var li = '<li class="liactive"><span>测试1</span><span class="iconfont icon-guanbi"></span></li>'; var section = '<section class="conactive">' + random + "</section>"; that.ul.insertAdjacentHTML("beforeend", li); that.fsection.insertAdjacentHTML("beforeend", section); that.init(); }
5、删除功能
实现思路:
1、点击 x 可以删除当前的1选项卡和当前的section
2、x 是没有索引号的,但是它的父亲 li 有索引号,这个素引号正是我们想要的索引号
3、所以核心思路是:点击 × 号可以删除这个索引号对应的 li 和 section
核心代码:
// 3、删除功能 removeTab(e) { e.stopPropagation(); var index = this.parentNode.index; that.lis[index].remove(); that.sections[index].remove(); that.init(); if (document.querySelector(".liactive")) return; index--; that.lis[index] && that.lis[index].click(); }
6、编辑功能
实现思路:
1、双击选项卡 li 或者 section 里面的文字,可以实现修改功能
2、双击事件是:ondblclick
3、如果双击文字,会默认选定文字,此时需要双击禁止选中文字
4、核心思路:双击文字的时候在里面生成—个文本框,当失去焦点或者按下回车然后把文本框输入的值给原先元素即可
禁止选中文字代码:
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
核心代码:
// 4、修改功能 editTab() { var str = this.innerHTML; window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty(); // 生成文本框 this.innerHTML = '<input type="text" />'; var input = this.children[0]; input.value = str; input.select(); input.onblur = function () { this.parentNode.innerHTML = input.value; }; input.onkeyup = function (e) { if (e.keyCode === 13) { this.blur(); } }; }