拖拽的原生原理以及继承,原型,深拷贝,原型链等概念

首先在onmousedown中,计算坐标值,就是通过计算当前鼠标的横坐标减去当前元素的与浏览器左边边界的距离。然后再onmousemove中,获得当前鼠标的横纵坐标,然后把当前元素的的left等于,当前横坐标-onmousedown中获得的插值,就是移动的距离,然后即使top的距离,就是当前鼠标纵坐标减去(上一步鼠标的纵坐标减去元素与浏览器上部的距离)然后再onmouseup中,监控鼠标如果放开,则把鼠标的Move事件置空。

也就是

        鼠标点击时候,计算当前鼠标和当前元素的之间的静态距离,然后鼠标移动时,把实时的鼠标位置传给元素,并且改变他的坐标位置,最后再鼠标抬起时,释放掉鼠标Move的监控。注意的是,onmousemove的方法是卸载onmousedown中,且需要给元素css{position:absoulute}的css属性,才能使拖拽生效。

<style>
    .myDiv {
        width: 100px;
        height: 100px;
        background: red;
        position: absolute;
    }
</style>
<body>
    <div class="myDiv"></div>
</body>
<script>
        let myDiv = document.querySelector(".myDiv")
    myDiv.onmousedown = function(e){
        console.log(e.clientX,"鼠标的坐标")
        console.log(this.offsetLeft,"盒子与边框的距离")
        let x = e.clientX - this.offsetLeft
        let y = e.clientY - this.offsetTop
        // console.log(x,y)
        document.onmousemove = function(e){
            console.log(e.clientX- x)
            myDiv.style.left = e.clientX- x + "px"
            myDiv.style.top = e.clientY- y + "px"
        }
        document.onmouseup = function(e){
            document.onmousemove = null
        }
    }
  
</script>

坑:在我们给盒子的left赋值时,需要带上单位px才能够生效。

                需要给盒子一个absolute的位置属性,拖动才能生效

                另外在监听move和up时候,应该监听整个document

2,继承

1,改变this指向

        ES5写法,可以在要继承的方法内,使用call,改变this指向,达到继承的效果

        apply,call, apply第二个参数接受的是一个数组

        Dad.call(this,height)        

        Dad.apply(this,[height])

        Dad.bind(this)(height)

        三者最终效果都是一样的,就是继承了Dad的属性和方法

2,原型继承

        如果父组件的方法是写在原型上的,子组件不能直接拿到

        方案一:Son.prototype = Dad.prototype

        会有问题,如果子类改变原型链的方法,会影响父类

        组合继承: 

let Link = function(){}
Link.prototype = Dad.prototype
Son.prototype = new Link()
Son.prototype.constructor = Son

3,深拷贝和浅拷贝

对象之间的简单赋值,会相互影响

let obj = {
    name:"张三"
    age:20
}
let obj2 = obj;
obj2.age = 30;
console.log(obj)

//发现Obj的age也发生了改变

解决方案1:新开辟地址,先序列化再解析

let obj2 = JSON.parse(JSON.stringfy(obj))

    问题:会丢失funciton和undefined的属性

    解决方案2:深拷贝,思路先判断进来的obj是数组还是对象,根据不同情况先初始化,然后遍历进来的obj不是对象,就直接赋值,如果是对象,则使用递归的方法继续赋值

优化,因为Null也会被认为是对象,所以需要单独处理

for in还会循环原型上的属性,如果不想要原型的属性,可以加上hasOwnProperty

function deepCopy(obj) {
    let newObj = Array.isArray(obj)?[]:{}
    for(let i in obj){
        if(obj.hasOwnProperty(i)){
        if(typeof obj[i] === "object"){
            if(obj[i] ===null){
                newObj[i] = null
            }else{
                 newObj[i] = deepCopy(obj[i])
            }
          
       }else{
            newObj[i] = obj[i]
}}} 
    return newObj
}

4,原型链

调用方法,会先去找本身的方法,然后再去找原型上的方法,如果原型上没有,会去找对象(本质)的方法。顶层是null

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值