1.constructor()
constructor()方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过new命令生成对象实例时,自动调用该方法,如果没有显示定义,类内部会自动给我们创建一个constructor()
class Star {
constructor(uname) {
this.uname = uname //this指向创建的实例,下面分布指向变量ldh和zxy
this.age = age
}
sing(song){
console.log(this.name,song)
}
}
var ldh = new Star('刘德华',15);
console.log(ldh.uname,ldh.age) //刘德华 15
ldh.sing('冰雨') //刘德华 冰雨
var zxy = new Star('张学友',20);
console.log(zxy.uname,zxy.age) //张学友 20
zxy.sing('吻别')
2.extends和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); //调用了父类中的构造函数constructor
}
}
var son = new Son(1,2);
var son1 = new Son(11,22);
son.sum() //3
son1.sum() //33
通过super调用父类普通函数
class Father {
say(){
return '我是爸爸'
}
}
class Son extends Father {
say(){
console.log('我是儿子')
console.log(super.say())
}
}
var son = new Son();
son.say() //我是儿子 就近原则
//我是爸爸 通过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调用父类的构造函数,super必须在子类this之前调用
this.x = x;
this.y = y;
}
sub(){
console.log(this.x - this.y)
}
}
var son = new Son(5,2);
son.sub() //3
son.sum() //7
注意
- 没有变量提升,所以必须先定义类,才能通过类实例化对象;
- 类里面的共有属性和方法,要加 this使用;
- constructor里面的this指向实例对象,方法里的this指向方法的调用者;
练习
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
.tabsbox nav{
display: flex;
justify-content: space-between;
align-items: center;
background: #f0f0f0;
border: #e1e1e1 1px solid;
}
.tabsbox nav ul{
display: flex;
justify-content: space-between;
list-style: none;
}
.tabsbox nav ul li{
position: relative;
width: 80px;
cursor: pointer;
text-align: center;
margin-right: 10px;
}
.tabsbox nav ul li span:first-child{
/* border: 1px solid red; */
}
.tabsbox nav ul li span:first-child:hover{
background: #ffaae2;
}
.tabsbox nav ul li span:last-child{
position: absolute;
top: -15px;
right: 0px;
background: #1780e2;
color: #fff;
width: 20px;
height: 20px;
display: inline-block;
cursor: pointer;
}
.tabsbox nav ul li input{
width: 40px;
height: 20px;
}
.liactive{
color: deeppink;
}
.conactive{
color: #02A6B5;
}
.tabadd{
background: #dddddd;
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
line-height: 50px;
cursor: pointer;
}
.tabscon{
height: 300px;
padding: 8px;
background: #f3f3f3;
border: #e1e1e1 1px solid;
border-top: none;
}
.tabscon input{
width: 100%;
height: 100%;
}
.tabscon section{
display: none;
width: 100%;
height: 100%;
}
.conactive{
display: block !important;
}
</style>
</head>
<body>
<div class="tabsbox" id="tab">
<!-- tab标签 -->
<nav class="firstnav">
<ul>
<li class="liactive"><span>测试0</span><span>x</span></li>
<li><span>测试1</span><span>x</span></li>
<li><span>测试2</span><span>x</span></li>
</ul>
<div class="tabadd">
<span>+</span>
</div>
</nav>
<!-- tab内容 -->
<div class="tabscon">
<section class="conactive">测试0</section>
<section>测试1</section>
<section>测试2</section>
</div>
</div>
<script type="text/javascript">
// 功能:增、删、改、切换
// 对象:tab栏
var that; //constructor里的this指向被调用的对象,事件里的this指向执行元素
class Tab {
constructor(id) {
// 获取元素
that = this;
this.main = document.querySelector(id)
this.add = this.main.querySelector('.tabadd')
this.ul = this.main.querySelector('ul')
this.fsections = this.main.querySelector('.tabscon')
this.init()
}
// 初始化
init(){
// 给加号添加事件
this.add.onclick = this.addTab;
// 更新li和section
this.updateNode()
// 给所有的li添加index,增加事件 span添加删除事件
for(let i = 0; i < this.lis.length; i++){
this.lis[i].index = i
// console.log(this.lis[i])
this.lis[i].onclick = this.toggleTab;
// 删除事件
// console.log(this.lis[i].lastChild)
this.lis[i].lastChild.onclick = this.removeTab
// 编辑事件
this.spans[i].ondblclick = this.editTab;
this.sections[i].ondblclick = this.editTab;
}
}
// 切换
toggleTab(){
// console.log(this.index)
// console.log(this)
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 = '';
// this.spans[i].className = 'aaaaa'
}
}
// 更新li和section
updateNode(){
this.lis = this.main.querySelectorAll('li')
this.sections = this.main.querySelectorAll('section')
this.spans = this.main.querySelectorAll('.firstnav li') // 所有li
// console.log(this.spans)
}
// 添加
addTab(){
that.clearClass()
// 创建元素
let li = `<li class="liactive"><span>新选项卡</span><span>x</span></li>`;
let section = '<section class="conactive">新内容</section>'
// 追加元素
that.ul.insertAdjacentHTML('beforeend',li);
that.fsections.insertAdjacentHTML('beforeend',section)
that.init()
}
// 删除
removeTab(e){
// 阻止冒泡
e.stopPropagation()
let index = this.parentNode.index;
console.log('删除',index)
that.lis[index].remove();
that.sections[index].remove()
that.init()
// 删除li后,只需要关闭对应的tab
if(document.querySelector('.liactive')) return
// 删除li后,让前一个处于选中状态
index--
// 前真? 取后 前假? 不取后 callback && callback()
that.lis[index] && that.lis[index].click();
}
// 修改
editTab(){
// 双击事件 ondblclick
// 双击禁止选中文字
window.getSelection ? window.getSelection().removeAllRanges():document.selection.empty();
// that.clearClass()
let str = this.innerText;
// console.log(str)
this.innerHTML = `<input type="text" value="${str}"/>`
// console.log(this.querySelector('input'))
this.querySelector('input').select()
this.querySelector('input').onblur = function(){
// console.log('离开',this.value)
this.parentNode.innerHTML = this.value
}
// 按下回车也可以编辑赋值
this.querySelector('input').onkeyup = function(e){
if(e.keyCode === 13){
this.blur()
}
}
}
}
new Tab('#tab')
</script>
</body>
</html>