20前端学习之js高级:面向对象、案例:面向对象的tab栏

一、什么是面向对象:

1. 两大编程思想:

  • 面向过程:
  • 面向对象:

2. 面向过程编程(POP)

面向过程就是分析出解决问题所需要的步骤, 然后用函数把这些步骤一步步实现, 使用的时候再一个接一个依次调用就可以了.

3. 面向对象编程(OOP):

面向对象是把事物分解成一个个对象, 然后由对象之间分工合作;
面向对象程序开发思想中,每个对象都是功能中心, 具有明确的分工;
面向对象编程具有灵活,代码复用,容易维护和开发的有点;
面向对象的特性:

  • 封装;
  • 继承;
  • 多态;

二、ES6中的类和对象:

1. 面向对象的思维特点:

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

2. 对象:

  • 具体的特指;
  • 在js中, 对象是一组无序的相关属性和方法的集合, 所有事物都是对象;
  • 对象是由属性和方法组成的:
    • 属性: 事物的特性, 在对象中用属性来表示(常用名词);
    • 方法: 事物的行为, 在对象中用方法来表示(常用动词)

3. 类: class

  • 抽象的泛指;
  • 在ES6中新增了类的概念, 使用class关键字声明一个类, 之后以这个类来实例化对象;

4. 创建类:

4.1 语法:

class name {
	// class body
}

var xx = new name

注意:

  • 类必须使用new来实例化;

4.2 类constructor 构造方法:

  • constructor()方法是类的构造方法(默认方法), 用于传递参数, 返回实例对象, 通过new 关键字生成对象实例, 自动调用该方法.如果没有显式定义, 类内部会自动创建constructor();
class Start {
	constructor(uname, age) {
		// 构造方法
		this.uname = uname;
		this.age = age;
	}
}

var ldh = new Start('刘德华', 18)
console.log(ldh);	// {uname: "刘德华", age: 18}
console.log(ldh.uname);	// 刘德华
console.log(ldh.age);	// 18

4.3 类中添加方法:

class Start {
	constructor(uname) {
		this.uname = uname;
	}
	sing(song) {
		console.log(this.uname + '在唱' + song)
	}
}
var ldh = new Start('刘德华')
ldh.sing('冰雨')	// 刘德华在唱冰雨

注意:
类中的方法不需要使用function定义
多个方法之间不需要添加分号(😉 或 逗号(,)分割;

4.4 类的继承:

// 父类
class Father {
	constructor() {
		this.money = 100;
	}
	have() {
		console.log('这里有' + this.money + '元钱')
	}	
}

// 子类
class Soon extends Father{
	
}

// 实例化
var son = new Son()
son.have(); // 这里有100元钱

4.5 super:

super关键字用于访问和调用父类上的方法.可以d调用父类的构造方法, 也可以调用父类的普通方法;
注意:

  • 子类在构造函数中使用super, 必须放在this前面(必须先调用父类构造方法, 再使用自己的构造方法)
// 父类
class Father {
    constructor(x, y) {
         this.x = x;
         this.y = y;
     }
     sum() {
         return this.x + this.y;
     }
     say() {
		console.log("我是父类")
	}  
}

// 子类
class Son extends Father{
	constructor(x,y) {
		super(x, y);
    }
    say() {
		console.log("我是子类");
	} 
	f_say() {
		super.say();
	}
}

// 实例化
var son = new Son(3, 4);
console.log(son.sum());	// 7
son.say();	// 我是子类
son.f_say()	// 我是父类

5. ES6中类和对象:

三个注意点:

  • 在ES6中类没有类型提升, 所以要先定义类, 再通过类实例化对象;
  • 类里面使用公有的属性和方法一定要加this使用;
  • 类里面this的指向问题;
    • constructor: this指向的新创建的实例;
    • 普通方法: this指向的是调用者;

三、案例: 面向对象的tab栏:

在这里插入图片描述

1. 功能需求:

  • 点击tab栏, 可以实现切换效果;
  • 点击+号, 可以添加tab项和内容项;
  • 点击x号, 可以删除当前tab项和内容;
  • 双击tab项文字或者内容项文字, 可以修改里面的内容

2. 思路:

抽象对象: Tab对象;

  • 切换功能;
  • 添加功能;
  • 删除功能;
  • 修改功能;

3. 知识整理:

3.1 向element添加元素: insertAdjacentHTML:

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

element.insertAdjacentHTML(position, text);
  • position:
位置参数说明
beforebegin元素自身的前面
afterbegin插入元素内部的第一个子节点之前
beforeend插入元素内部的最后一个子节点之后
afterend元素自身的后面
  • text
    是要被解析为HTML或XML元素,并插入到DOM树中的 DOMString;

3.2 禁用双击选中文字:

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

4. 代码实例:

<!DOCTYPE html>
<html lang="zh">
<head>
  <title>面向对象的tab栏切换</title>
  <link rel="stylesheet" href="./style.css">
  <style>
    * {
      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: 80%; }
    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;
      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: 0;
      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; }
</style>
</head>
<body>
  <main>
    <h4>Js面向对象 动态添加标签页</h4>
    <div class="tabsbox" id="tab">
      <nav class="firstnav">
        <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>
    var that = null;
    class Tab {
      constructor(id) {
        that = this;
        // 获取元素
        this.main = document.querySelector(id);
        this.add = document.querySelector('.tabadd');
        this.initTab();
      }
      initTab() {
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
        this.removes = this.main.querySelectorAll('.icon-guanbi');
        this.spans = this.main.querySelectorAll('.firstnav li span:first-child');
        // 初始化操作
        for(let i = 0; i < this.lis.length; i++) {
          this.lis[i].index = i;
          this.lis[i].onclick = this.toggleTab;
          this.removes[i].onclick = this.removeTab;
          this.spans[i].ondblclick = this.editTab;
          this.sections[i].ondblclick = this.editTab;
        }
        this.add.onclick = this.addTab;
      }
      toggleTab() {
        // 切换
        that.clearClass(); // 注意指向问题
        this.className = 'liactive';
        that.sections[this.index].className = 'conactive';
      }
      addTab() {
        that.clearClass();
        // 添加
        let _ul = document.querySelector('.firstnav ul:first-child');
        let title = '新添加';
        _ul.insertAdjacentHTML('beforeEnd', `<li class="liactive"><span>${title}</span><span class="iconfont icon-guanbi"></span></li>`);

        let tabscon = document.querySelector('.tabscon ');
        let content = '新添加的内容' + Math.random();
        tabscon.insertAdjacentHTML('beforeEnd', `<section class="conactive">${content}</section>`);

        // 重新加载l和section
        that.initTab();
      }
      removeTab(e) {
        // 删除
        e.stopPropagation();  // 阻止冒泡
        // 获取父级的索引号
        let index = this.parentNode.index;
        that.lis[index].remove();
        that.sections[index].remove();
        // 重新加载l和section
        that.initTab();

        if(document.querySelector('.liactive')) return;
        // 当删除了选中状态的li
        index--;
        // 手动触发点击事件
        that.lis[index] && that.lis[index].click();
      }
      editTab() {
        // 修改功能
        // 双击禁止选定文字
        window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
        // 获取原内容
        let str = this.innerHTML
        this.innerHTML = `<input type='text'>`;
        let input = this.children[0];
        input.value = str;
        input.select();
        // 离开时赋值
        input.onblur = function() {
          this.parentNode.innerHTML = this.value;
        }
        // 按下回车提交修改
        input.onkeyup = function(e) {
          if(e.keyCode !== 13) return
          this.blur();
        }
      }
      clearClass() {
        for(let i = 0; i < this.lis.length; i++) {
          this.lis[i].className = '';
          this.sections[i].className = '';
        }
      }
    }
    var tab = new Tab('#tab')
  </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

浅弋、璃鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值