两大编程思想
1.面向过程
分析出解决问题所需要的步骤,用函数一一实现使用的时候在一个个调用
2.面向对象
把事务分解成一个个对象,然后由对象分工和合作
面向对象的特性
- 封装性
- 继承性
- 多态性
两者的区别
面向过程没有面向对象易维护易复用易扩展
面向对象性能比面向过程低
面向对象思维特点
1.抽取对象公用的属性和行为组织(封装成)一个类(模板)
2.对类进行实例化
对象
对象特指某一个通过类实例化一个具体的对象
对象由属性和方法构成
- 属性:事情的特征,在对象中用属性来表示
- 方法:事务的行为
类
- 在es6中增加了类的概念,可以用class关键字来声明一个类,之后用类来实例化对象
类抽象了对象的公共部分,泛指某一个大类
-
创建类 语法
class name{//class body } 创建实例
var xx=new name();
注意类必须使用new实例化对象
- 类constructor构造函数
constructor()方法时类的构造函数,可以接受传递过来的参数,返回实例对象,通过new命令生成对象实例时,自动调用该方法,如果没有显示定义,类的内部会自动创建一个constructor()
class name{
constructor(uname){
this.uname=uname;
}
}
//利用类创建对象new
var aa=new name('11');
var bb=new name('22');
生成实例new不能省略
注意语法规范,创建类,类名后面不要加小括号,生成实例,类名后面加小括号,构造函数不需要加function
-
类添加方法
class name{ constructor(uname){u this.uname=uname; } } say(){ console.lod(this.name+'你好') } }
我们类里面所有的函数不需要加function
多个函数方法之间不需要添加逗号分隔
- 类的继承
子类可以继承父类的一些属性和方法
class father{
}//父类
class son extends father//子类继承父类
例如:
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){
this.x=x;
this.y=y;
}
}
var son =new son(1,2);
son.sum();
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();//调用了父类的构造函数 } } var son =new son(1,2); son.sum();
2.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) {
// constructor里面的this指向的是创建的实例对象
this.x = x;
this.y = y;
}
sum() {
//方法中谁调用this就是指向谁
console.log(this.x + this.y);
}
}
class son extends Father {
constructor(x, y) {
super(x, y) //super必须在子类this之前调用
this.x = x;
this.y = y;
}
subtract() {
console.log(this.x - this.y);
}
}
var son = new son(5, 3);
son.subtract();
- 类的注意点
1.在es6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
2.类里面共有的属性和方法一定要加this使用
3.类中的this指向问题
- constructor里面的this指向的是实例对象,方法里面的this指向的是方法的调用者
面向对象案例
功能需求
1.店家tab栏可以切换效果
2.点击+号可以添加tab栏和内容项
3.点击x号可以删除当前的tab栏和内容项
4.双击tab项文字和内容项目的文字,可以修改里面的文字内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../css/reset.css">
<style>
nav {
width: 500px;
height: 50px;
border: 1px solid #333;
display: flex;
justify-content: space-between;
}
nav ul {
display: flex;
padding: 0;
}
nav li {
list-style-type: none;
border-right: #333 solid 2px;
width: 60px;
padding: 0;
text-align: center;
line-height: 50px;
position: relative;
}
.guanbi {
position: absolute;
right: 0;
top: -20px;
}
.tabscon section:nth-child(2),
.tabscon section:nth-child(3) {
width: 500px;
height: 200px;
border: 1px solid #333;
display: none;
}
.conactive {
width: 500px;
height: 200px;
border: 1px solid rgb(218, 37, 37);
background-color: aqua;
display: block;
}
.liactive {
background-color: pink;
color: white;
}
</style>
</head>
<body>
<h4>js面向对象 动态添加标签页</h4>
<div class="tabsbox" id="tab">
<!-- tab标签 -->
<nav class="fisnav">
<ul>
<li class="liactive"> <span>测试1</span> <span class="guanbi">x</span></li>
<li>
<span>测试2</span>
<span class="guanbi">x</span>
</li>
<li>
<span>测试3</span>
<span class="guanbi">x</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>
</body>
<script>
var that;
class Tab {
constructor(id) {
that = this;
//获取元素
this.main = document.querySelector(id);
this.lis = this.main.querySelectorAll('li')
this.sections = this.main.querySelectorAll('section')
this.add = this.main.querySelector('.tabadd')
this.ul = this.main.querySelector('.fisnav ul:first-child')
this.fsection = this.main.querySelector('.tabscon')
this.remove = this.main.querySelectorAll('.guanbi')
this.init();
}
init() {
this.updateNode()
this.add.onclick = this.addTab;
// init初始化操作让相关的元素绑定事件
// 绑定点击事件
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
this.sections[i].ondblclick = this.editTab
}
}
//切换功能
toggleTab() {
that.clearClass();
this.className = 'liactive';
that.sections[this.index].className = 'conactive';
}
// 获取所有li和section
updateNode() {
this.lis = this.main.querySelectorAll('li')
this.sections = this.main.querySelectorAll('section')
this.remove = this.main.querySelectorAll('.guanbi')
this.spans = this.main.querySelectorAll('.fisnav li span:first-child')
}
clearClass()
// 清除所有li个section的类
{
for (var i = 0; i < this.lis.length; i++) {
this.lis[i].className = '';
this.sections[i].className = '';
}
}
addTab() {
// 清除所有li个section的类
that.clearClass();
// 创建li元素和section元素
var li = '<li class="liactive"> <span>新测试</span> <span class="guanbi">x</span></li>'
var section = ' <section class="conactive">测试3</section>'
// 把创建的两个元素追加到对应的父元素里
that.fsection.insertAdjacentHTML('beforeend', section);
that.ul.insertAdjacentHTML('beforeend', li);
that.init();
//利用insertAdiacentHTML()可以直接把字符串格式元素添加到元素里
}
// 删除事件
removeTab(e) {
// 防止冒泡,防止触发li的切换点击事件
e.stopPropagation();
var index = this.parentNode.index;
console.log(index)
// 根据索引号删除对应的li和section
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();
}
// 编辑功能
//双击事件ondblclick 双击后默认选定文字需要双击禁止选中文字
editTab() {
// 禁止双击选中文字
var str = this.innerHTML
window.getSelection ? window.getSelection().removeAllRanges() : document.section.empty();
this.innerHTML = '<input type="text"/>'
var input = this.children[0]
input.value = str
input.select(); //让文本框里面的文字处于选定状态
// 当我们离开文本框九八文本框的值给span
input.onbur = function() {
this.parentNode.innerHTML = this.value
}
// 按下回车可以把文本框里面的值给span
input.onkeyup = function(e) {
if (e.keyCode === 13) {
//手动调用扁担失去焦点事件,不需要鼠标离开操作
this.blur();
}
}
}
}
new Tab('#tab');
</script>
</html>