day18 面对对象
概述:
面向对象是一种编程思想(oop) , 它是相当于面向过程的一个抽取和简化. 主要是以类来构建对象,以对象来存储对应的行为和属性 , 抽取对应的行为作为方法 , 抽取对应的属性作为属性 .
核心 : 万物皆对象(所有的内容都可以抽取为一个对象)
关键点 : 找有这个行为的对象去完成这个行为
面向对象和面向过程 :
面向过程以过程为核心
示例 ( 去饭店吃饭 )
-
先找饭店
-
找服务员点餐
-
等待上菜
-
吃饭
-
结账
面对对象以对象为核心
示例
-
我找饭店 ( 我这个对象 , 找饭店这个对象 )
-
结账 , 吃饭 , 点餐属于我的行为
-
饭店提供的服务属于饭店的行为
对象的构建
需要调用new关键词 去执行构造函数来创建对象
通过类来构建对象(构造器) (es6)
//通过类来构造对象 (区分对应的类型) class Person{ constructor(username){ //构造器,他是一个函数,new的时候会调用对应的构造函数 this.name = username //this指向当前构造的实例对象 } } var person = new Person('jack')
//通过构造函数创建 , 首字母要大写 function Person(name){ this.name = name //函数里的this指向它的调用者,在new的时候会指向对应的对象实例 } var person=new Person('Alex')
上述的两种构建方式 其实核心上都是一种 , 都是通过构造函数 ( 构建对象的函数 ) 来构建
通过构造函数构建 做了什么操作
-
自动构建对象
-
手动设置属性
-
自动返回对象
通过工厂模式来构建 , 返回对应的对象 ( 不能区分类型 )
-
手动创建对象
-
手动创建属性
-
手动返回对象
//工厂里面传入的属性 返回的是对象(不能区分类型) function factory(name){ //object是最大的对象,手动构建对象 var obj = new Object() //手动给对象添加属性 obj.name = name //手动返回对象 return obj } //调用 var obj = factory('发财') var obj1 = factory('发大财') console.log(obj,obj1)
工厂模式的特性
-
可以构建所有的对象
-
在构建对象的时候会忽略细节
-
console.log(obj instanceof Object) //true console.log(obj1 instanceof Object) //true
面对对象的三大特性
-
封装 ( 将对应的行为抽取为方法 )
-
继承 ( 子类继承父类的属性和方法 )
-
多态 ( 继承关系的体现 , 重写 : 子类重写父类的方法 ) , 重载 ( 在一个类中同名不同参数 , js没有会覆盖 ))
封装示例
示例 : 有一只猫会喵喵叫 , 它很胖800斤 , 吃得很多 , 名字叫咪咪
属性 : 体重800斤 , 名字咪咪
方法 : 喵喵叫 , 吃很多
继承及对应的重写
class Person{ constructor(){ this.name='jack' this.say=()=>{ console.log('hhhh') } } } class Son extends Person{ constructor(){ super() this.age=25 this.say=()=>{ console.log('oooo') } } } var son =new Son() console.log(son) //name,age,say son.say()
面对对象tab栏切换
行为 : tab栏的点击事件 , 显示栏的切换方法
//构建一个类 class Tab{ constructor(nav,content){ this.nav=nav //上边的点击栏 this.content=content //下边的切换栏 } //切换的方法 toggele(selectedElement){ //遍历上边的点击栏,选中的设置样式,其他的清空样式 Array.from(this.nav).forEach((item)=>{ item.className='' }) selectedElement.className='selected' //遍历下边的切换栏 Array.from(this.content).forEach((item)=>{ item.className='' }) //找到上边点击栏被选中的下标 let i = Array.from(this.nav).findIndex((v)=>{ return v==selectedElement }) //改这个下标对应的样式 this.content[i].className='show' } //点击的方法 handlerClick(){ let self=this //遍历上边点击栏,给每个成员添加点击事件并切换 Array.from(this.nav).forEach((item,i)=>{ item.onclick=()=>{ self.toggle(item) } }) } }
<!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>
<style>
.box {
width: 500px;
height: 500px;
border: 1px solid #000;
position: relative;
}
.move {
width: 100px;
height: 100px;
background-color: aqua;
position: absolute;
}
</style>
</head>
<body>
<div class="box">
<div class="move"></div>
</div>
<script>
// 面对对象实现盒子拖拽
class Touch {
constructor(box, move) {
this.box = box //大盒子
this.move = move //移动的盒子
this.point = { //坐标位置,初始位置是0,0
x: parseInt(this.getStyle(this.move).left || 0),
y: parseInt(this.getStyle(this.move).top || 0)
}
this.handlerDown()
}
// 获取样式的方法
getStyle(element) {
if(window.getComputedStyle){
return window.getComputedStyle(element,'')
}else{
return element.currentStyle
}
}
// 按下事件
handlerDown() {
this.move.onmousedown = (e) => {
e = e || window.event
// 获取移动盒子按下的位置
let currentX = e.offsetX
let currentY = e.offsetY
// 调用移动的方法
this.handlerMove(currentX, currentY)
// 调用弹起的方法
this.handlerUp()
console.log(currentX, currentY)
}
}
// 移动事件
handlerMove(currentX,currentY) {
// 给大盒子添加移动事件
this.box.onmousemove = (e) => {
e = e || window.event
// 获取大盒子在页面上的位置
let { x, y } = this.getPagePoint(this.box)
// 获取可移动位置 = 页面上的位置-大盒子在页面上的位置-当前按下的位置
let { targetX, targetY } = {
targetX: e.pageX - currentX - x,
targetY: e.pageY - currentY - y
}
// 获取最大拖拽值
let maxX = this.box.offsetWidth - this.move.offsetWidth
let maxY = this.box.offsetHeight - this.move.offsetHeight
// 区间判断,为了让盒子不超出移动范围
if (targetX < 0) {
targetX = 0
}
if (targetX > maxX) {
targetX = maxX
}
if (targetY < 0) {
targetY = 0
}
if (targetY > maxY) {
targetY = maxY
}
// 设置位置(调用方法)
this.point = { x: targetX, y: targetY }
this.setStyle()
}
}
// 鼠标弹起事件
handlerUp() {
document.onmouseup = () => {
this.box.onmousemove = null
}
}
// 设置位置的方法
setStyle() {
this.move.style.left = this.point.x + 'px'
this.move.style.top = this.point.y + 'px'
}
// 获取到父元素的距离,一直到body循环就结束
getPagePoint(element) {
let x = 0
let y = 0
while (element.offsetParent) {
x += element.offsetLeft
y += element.offsetTop
element = element.offsetParent
}
return { x, y }
}
}
var box = document.querySelector('.box')
var move = document.querySelector('.move')
// 调用实现拖拽
new Touch(box,move)
</script>
</body>
</html>
// 放大镜功能和盒子区间拖拽的实现有类似 class Magnifier extends Touch{ constructor(box,move,bigBox,bigImg){ // 传给父类 super(box,move) this.bigBox=bigBox this.bigImg=bigImg this.handlerEnter() this.handlerLeave() } handlerEnter(){ this.bos.onmouseenter = ()=>{ this.move.style.display = 'block' this.bigBox.style.display = 'block' this.init() //调用移动的方法 this.handlerMove(this.move.offsetWidth/2,this.move.offsetHeight/2) } } handlerLeave(){ this.box.onmouseleave = ()=>{ this.move.style.display='none' this.bigBox.style.display='none' } } init(){ // 将移动的move的大小初始化 this.move.style.width = this.box.offsetWidth / (this.bigImg.offsetWidth / this.bigBox.offsetWidth)+'px' this.move.style.height = this.box.offsetHeight/(this.bigImg.offsetHeight/this.bigBox.offsetHeight)+'px' } setStyle(){ //根据对应的坐标来设置位置 this.move.style.left = this.point.x+'px' this.move.style.top = this.point.y+'px' //获取大图片的定位 //公式为 : 大盒子/移动的盒子 = 大图片/图片盒子 //故图片定位应是 = 大盒子/移动的盒子*图片盒子 let x = this.point.x/this.box.offsetWidth*this.bigImg.offsetWidth*-1 let y = this.point.y/this.box.offsetHeight*this.bigImg.offsetWidth*-1 //根据定位设置大图片的位置 this.bigImg.style.left = x+'px' this.bigImg.style.top = y+'px' } }

浙公网安备 33010602011771号