欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript 拖拽與觀察者模式的實(shí)現(xiàn)及應(yīng)用小結(jié)

 更新時間:2025年01月15日 10:57:24   作者:前端青山  
本文通過代碼片段詳細(xì)介紹了JavaScript中的拖拽功能和觀察者模式(發(fā)布-訂閱模式)的實(shí)現(xiàn)及其應(yīng)用場景,拖拽功能允許用戶通過鼠標(biāo)移動元素,而觀察者模式則定義了一種一對多的依賴關(guān)系,使得對象能夠自動更新,感興趣的朋友跟隨小編一起看看吧

前言

本文將通過幾個具體的代碼片段,深入探討 JavaScript 中的拖拽功能和觀察者模式(發(fā)布-訂閱模式)的實(shí)現(xiàn)及其應(yīng)用場景。

這些代碼片段不僅展示了如何實(shí)現(xiàn)這些功能,還解釋了其背后的原理和實(shí)際用途。通過閱讀本文,讀者可以更好地理解 JavaScript 的高級特性,并將其應(yīng)用到實(shí)際項(xiàng)目中。

1. 拖拽功能的實(shí)現(xiàn)

代碼片段

<!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>
        #father {
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
        }
        #son {
            width: 100px;
            height: 100px;
            background: green;
            position: absolute;
            left: 110px;
        }
    </style>
</head>
<body>
    <div id="father">father</div>
    <div id="son">son</div>
    <script src="js/drag.js"></script>
    <script src="js/subdrag.js"></script>
    <script>
        new Drag('#father');
        new Subdrag('#son');
    </script>
</body>
</html>

代碼解析

拖拽類 Drag

class Drag {
    constructor(selector) {
        // 獲取拖拽的對象
        this.ele = document.querySelector(selector);
        // 添加事件
        this.ele.onmousedown = function (evt) {
            // this: 原來指向了 ele 對象,這里需要一個實(shí)例對象
            this.fnDown(evt);
        }.bind(this);
    }
    fnDown(evt) {
        let e = evt || window.event;
        // 求鼠標(biāo)的相對坐標(biāo)值
        this.dis_x = e.offsetX;
        this.dis_y = e.offsetY;
        // 移動事件
        document.onmousemove = function (evt) {
            // this: document
            this.fnMove(evt);
        }.bind(this);
        // 鼠標(biāo)抬起事件
        document.onmouseup = this.fnUp.bind(this);
        // 取消默認(rèn)行為
        document.ondragstart = function () {
            return false;
        };
    }
    fnMove(evt) {
        let e = evt || window.event;
        this.ele.style.left = e.pageX - this.dis_x + 'px';
        this.ele.style.top = e.pageY - this.dis_y + 'px';
    }
    fnUp() {
        document.onmousemove = null;
    }
}

子類 Subdrag 繼承自 Drag

class Subdrag extends Drag {
    constructor(selector) {
        // 調(diào)用父類的構(gòu)造函數(shù)
        super(selector);
    }
    fnMove(evt) {
        let e = evt || window.event;
        let left = e.pageX - this.dis_x;
        let top = e.pageY - this.dis_y;
        // 設(shè)置邊界
        if (left <= 0) {
            left = 0;
        } else if (left >= document.documentElement.clientWidth - this.ele.offsetWidth) {
            left = document.documentElement.clientWidth - this.ele.offsetWidth;
        }
        if (top <= 0) {
            top = 0;
        } else if (top >= document.documentElement.clientHeight - this.ele.offsetHeight) {
            top = document.documentElement.clientHeight - this.ele.offsetHeight;
        }
        this.ele.style.left = left + 'px';
        this.ele.style.top = top + 'px';
    }
}

功能說明

拖拽功能 是一種常見的用戶交互方式,允許用戶通過鼠標(biāo)移動元素。在上述代碼中,Drag 類實(shí)現(xiàn)了基本的拖拽功能,包括:

  • 獲取拖拽對象:通過選擇器獲取要拖拽的 DOM 元素。
  • 添加鼠標(biāo)按下事件:當(dāng)用戶按下鼠標(biāo)時,記錄鼠標(biāo)相對于元素的位置 (dis_x, dis_y)。
  • 添加鼠標(biāo)移動事件:根據(jù)鼠標(biāo)的當(dāng)前位置更新元素的位置。
  • 添加鼠標(biāo)抬起事件:當(dāng)用戶釋放鼠標(biāo)時,移除鼠標(biāo)移動事件,防止后續(xù)不必要的移動。
  • 取消默認(rèn)行為:阻止瀏覽器的默認(rèn)拖拽行為。

Subdrag 類繼承自 Drag 類,并在其基礎(chǔ)上增加了邊界限制,確保拖拽的元素不會超出視口范圍。這使得拖拽體驗(yàn)更加友好和實(shí)用。

2. 觀察者模式(發(fā)布-訂閱模式)

代碼片段 1:藥店示例

<!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>
</head>
<body>
    <script>
        // 發(fā)布者 - 藥店
        let drugstore = {
            // 花名冊
            obj: {},
            // 訂閱方法
            listen: function (eventName, fn) {
                if (!(this.obj[eventName])) {
                    this.obj[eventName] = [];
                }
                this.obj[eventName].push(fn);
            },
            // 發(fā)布方法
            publish: function (eventName, data) {
                this.obj[eventName]?.map(fn => {
                    fn(data);
                });
            }
        };
        let data = {
            type: "N95",
            price: 30,
            num: 500
        };
        let liaohuadata = {
            type: '連花',
            price: 200,
            num: 50
        };
        // 小周
        function xiaozhou(data) {
            if (data.price > 20) {
                console.log('黑店,太貴了,我就算不出門,我也不去買!');
            }
        }
        drugstore.listen('mask', xiaozhou);
        // 小易
        function xiaoyi(data) {
            if (data.type === 'N95') {
                console.log('先少買一點(diǎn),等有普通醫(yī)用口罩時,再多屯點(diǎn)');
            }
        }
        drugstore.listen('mask', xiaoyi);
        // 小王
        function xiaowang(data) {
            if (data.num > 100) {
                console.log('多屯點(diǎn),再高價賣給別人');
            }
        }
        drugstore.listen('mask', xiaowang);
        // 老王
        function laowang(data) {
            console.log('有佛祖保佑,不需要口罩');
        }
        drugstore.listen('mask', laowang);
        drugstore.publish('mask', data);
    </script>
</body>
</html>

代碼解析

觀察者模式(發(fā)布-訂閱模式)是一種設(shè)計(jì)模式,用于定義對象間的一種一對多依賴關(guān)系。當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都會收到通知并自動更新。在上述代碼中,drugstore 作為發(fā)布者,維護(hù)了一個名為 obj 的花名冊,記錄了不同事件的訂閱者列表。

具體實(shí)現(xiàn)如下:

  • 訂閱方法 listen:接收事件名稱 eventName 和回調(diào)函數(shù) fn,將回調(diào)函數(shù)添加到對應(yīng)事件的訂閱者列表中。
  • 發(fā)布方法 publish:接收事件名稱 eventName 和數(shù)據(jù) data,遍歷對應(yīng)的訂閱者列表,依次調(diào)用每個回調(diào)函數(shù)并傳遞數(shù)據(jù)。

通過這種方式,多個訂閱者可以根據(jù)不同的條件對同一事件做出響應(yīng)。例如,在上述代碼中,四個不同的訂閱者(小周、小易、小王、老王)根據(jù)藥店發(fā)布的口罩信息做出了不同的反應(yīng)。

代碼片段 2:售樓處示例

<!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>
</head>
<body>
    <script>
        // 發(fā)布者--售樓處
        let salesOffice = {
            // 花名冊
            arr: [],
            // 訂閱方法
            listen: function (fn) {
                this.arr.push(fn);
            },
            // 發(fā)布消息
            publish: function (data) {
                // 遍歷花名冊
                this.arr.forEach(fn => {
                    fn(data);
                });
            }
        };
        // 發(fā)布的消息
        let data = {
            size: 80,
            money: '10000元/平',
            num: '50套'
        };
        // 小明
        salesOffice.listen(function (data) {
            if (data.size < 100) {
                console.log('房子太小,不在考慮');
            }
        });
        // 小龍
        salesOffice.listen(function (data) {
            if (parseInt(data.money) < 150000) {
                console.log('預(yù)算充足,價格還可以,馬上去訂購一套');
            }
        });
        // 小強(qiáng)
        salesOffice.listen(function (data) {
            if (parseInt(data.num) > 30) {
                console.log('趕緊去,先屯20套再說');
            }
        });
        // 發(fā)布消息
        salesOffice.publish(data);
    </script>
</body>
</html>

代碼解析

在售樓處示例中,salesOffice 作為發(fā)布者,同樣使用了花名冊 arr 來記錄訂閱者的回調(diào)函數(shù)。不同的是,這里的訂閱者只關(guān)心新樓盤推出的消息,而不需要區(qū)分不同的事件類型。

具體實(shí)現(xiàn)如下:

  • 訂閱方法 listen:接收回調(diào)函數(shù) fn 并將其添加到花名冊中。
  • 發(fā)布方法 publish:接收數(shù)據(jù) data,遍歷花名冊中的所有回調(diào)函數(shù)并依次調(diào)用。

通過這種方式,多個訂閱者可以根據(jù)新樓盤的信息做出不同的反應(yīng)。例如,在上述代碼中,三個不同的訂閱者(小明、小龍、小強(qiáng))根據(jù)售樓處發(fā)布的房屋信息做出了不同的決策。

結(jié)尾

通過以上兩個主要部分的詳細(xì)探討,我們深入分析了 JavaScript 中的拖拽功能和觀察者模式的實(shí)現(xiàn)及其應(yīng)用場景。拖拽功能使得用戶能夠直觀地操作頁面元素,而觀察者模式則提供了一種優(yōu)雅的方式來處理對象間的依賴關(guān)系,避免了緊耦合的問題。

在實(shí)際項(xiàng)目中,合理運(yùn)用這些技術(shù)和模式可以顯著提高用戶體驗(yàn)和代碼的可維護(hù)性。希望本文的內(nèi)容對讀者有所幫助,歡迎繼續(xù)探索 JavaScript 的更多可能性。無論是構(gòu)建復(fù)雜的用戶界面還是實(shí)現(xiàn)高效的數(shù)據(jù)通信,掌握這些高級編程技巧都將為開發(fā)者帶來更多的便利和靈活性。

到此這篇關(guān)于JavaScript 拖拽與觀察者模式的實(shí)現(xiàn)及應(yīng)用的文章就介紹到這了,更多相關(guān)js 拖拽與觀察者模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論