原生JS案例(面向对象)——按住鼠标实现左右拖动列表

需求

鼠标在有色部分按下后, 可以对有颜色的部分进行左右拖拽

基本结构效果图

在这里插入图片描述

HTML页面

  • id为box的一个对象
    <div class="box" id="box">
        <ul class="ul-list">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
    </div>
  • id为box1的一个对象
    <div class="box" id="box1">
        <ul class="ul-list">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
        </ul>
    </div>

CSS样式

        * {
            margin: 0;
            padding: 0;
            list-style: none;
        }

        .box {
            width: 400px;
            height: 200px;
            margin: 100px auto;
            position: relative;
            overflow: hidden;
        }

        .ul-list {
            width: 2000px;
            height: 200px;
            line-height: 200px;
            position: absolute;
            display: flex;
            background-color: red;
            box-sizing: border-box;
        }

        .ul-list li {
            text-align: center;
            width: 200px;
        }

        .ul-list li:nth-child(odd) {
            background-color: aqua;
        }

        .ul-list li:nth-child(even) {
            background-color: #008c07;
        }

实现思路

  1. 鼠标按下时, 记录鼠标相对于ul的坐标disX。注意:这里不能用e.offsetX, 因为e.offsetX获取到的是鼠标相对于li的坐标。而我们要获取的是离鼠标最近的有绝对定位的父元素ul, 也就是用e.layerX。
  2. 当鼠标移动时, 是在整个浏览器窗口移动, 所以给document绑定鼠标移动事件。
  3. 移动时,先求出移动后盒子离浏览器左边的距离(e.clientX - disX),再用移动前盒子离浏览器左边的距离(box.offsetLeft)减去移动后盒子离浏览器左边的距离(e.clientX - disX),并赋值给盒子的滚动距离(box.scrollLeft)
  4. 鼠标弹起时, 解除document的鼠标移动事件
    在这里插入图片描述

原生JS

class dragMove {
    constructor(selector) {
        // 获取dom元素
        this.box = document.querySelector(`#${selector}`);
        this.ulList = this.box.querySelector('ul');

        // 设置ul的宽度, ul的宽度跟随li的数量动态变化
        this.ulList.style.width = this.ulList.querySelector('li').offsetWidth * this.ulList.querySelectorAll('li').length + 'px';
    }
    init() {
        this.bindEvents()
    }
    bindEvents() {
        // 鼠标按下时
        this.ulList.onmousedown = e => {
            e = e || window.event;
            // e.offsetX获取到的是鼠标相对于li的坐标
            // e.layerX获取到的是鼠标相对于ul(最近的有绝对定位的元素)的坐标
            let disX = e.layerX;

            // 鼠标移动时
            document.onmousemove = e => {
                e = e || window.event;
                this.box.scrollLeft = this.box.offsetLeft - (e.clientX - disX);
            }

            // 鼠标弹起时
            document.onmouseup = () => {
                document.onmousemove = null;
            }

            // 取消默认行为
            if (e.preventDefault) {
                e.preventDefault();
            } else {
                return false;
            }
        }
    }
}
// 创建新的对象并传参
(new dragMove('box')).init();
(new dragMove('box1')).init();

最终效果

在这里插入图片描述

实际应用

在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
原生 JavaScript 中,可以通过构造函数和原型链来实现面向对象继承。具体实现方式如下: 1. 构造函数继承 构造函数继承是通过在子类构造函数中调用父类构造函数来实现的。这种方式的缺点是无法继承父类原型上的方法和属性。 ```javascript function Parent(name) { this.name = name; } function Child(name, age) { Parent.call(this, name); this.age = age; } var child = new Child('Tom', 18); console.log(child.name); // Tom console.log(child.age); // 18 ``` 2. 原型链继承 原型链继承是通过将子类的原型指向父类的实例来实现的。这种方式的缺点是所有子类实例共享父类实例上的属性和方法。 ```javascript function Parent() { this.name = 'parent'; } Parent.prototype.sayHello = function() { console.log('Hello'); }; function Child() {} Child.prototype = new Parent(); var child1 = new Child(); var child2 = new Child(); console.log(child1.name); // parent console.log(child2.name); // parent child1.sayHello(); // Hello child2.sayHello(); // Hello ``` 3. 组合继承 组合继承是将构造函数继承和原型链继承结合起来使用的一种方式。这种方式既可以继承父类实例上的属性和方法,也可以继承父类原型上的属性和方法。 ```javascript function Parent(name) { this.name = name; } Parent.prototype.sayHello = function() { console.log('Hello'); }; function Child(name, age) { Parent.call(this, name); this.age = age; } Child.prototype = new Parent(); Child.prototype.constructor = Child; var child = new Child('Tom', 18); console.log(child.name); // Tom console.log(child.age); // 18 child.sayHello(); // Hello ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

前端技术迷

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

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

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

打赏作者

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

抵扣说明:

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

余额充值