iT邦幫忙

0

Js_removeEventListener

  • 分享至 

  • xImage

我的目標是當我點選newbutton時,在自定義的areaDiv新增一次按鈕;
寫死的狀態下是可以做到只新增一次;
但後續想新增text、label...所以改成用參數傳遞。
發現無法取消Listener,請各大大幫我看一下出了甚麼問題?

原本程式碼:

newButton.addEventListener('click', function () {
		if (!isDrawing) {
			startX = 0;
			startY = 0;
			isDrawing = true;
			areaDiv.addEventListener('mousedown', startSelection);
		}
	});
	function startSelection(event) {
		startX = event.clientX - areaDiv.offsetLeft;
		startY = event.clientY - areaDiv.offsetTop;
		isDrawing = true;
		areaDiv.addEventListener('mousemove', updateSelection);
		areaDiv.addEventListener('mouseup', createComponent);
	}
function createComponent(event) {
		if (isDrawing) {
			var currentX = event.clientX - areaDiv.offsetLeft;
			var currentY = event.clientY - areaDiv.offsetTop;
			var width = Math.abs(currentX - startX);
			var height = Math.abs(currentY - startY);
			var left = Math.min(startX, currentX);
			var top = Math.min(startY, currentY);

			var newButton = document.createElement('button');
			newButton.innerText = 'New Button';
			newButton.style.position = 'absolute';
			newButton.style.left = left + 'px';
			newButton.style.top= top + 'px';
			newButton.style.width = width + 'px';
			newButton.style.height = height + 'px';
			areaDiv.appendChild(newButton);

			isDrawing = false;
			areaDiv.removeEventListener('mousemove', updateSelection);
			areaDiv.removeEventListener('mouseup', createComponent);
			areaDiv.removeEventListener('mousedown', startSelection);
		}
	}

下面這是AI推薦寫法。
傳遞參數寫法:

	newButton.addEventListener('click', function () {
		if (!isDrawing) {
			startX = 0;
			startY = 0;
			isDrawing = true;
			areaDiv.addEventListener('mousedown', function(event) {
				startSelection(event, 'button');
			});
		}
	});

	function startSelection(event, newcomponentType) {
		startX = event.clientX - areaDiv.offsetLeft;
		startY = event.clientY - areaDiv.offsetTop;
		isDrawing = true;
		areaDiv.addEventListener('mousemove', updateSelection);
		areaDiv.addEventListener('mouseup', function(event) {
			createComponent(event, newcomponentType);
		});
	}
function createComponent(event, newcomponentType) {
		if (isDrawing) {
			var currentX = event.clientX - areaDiv.offsetLeft;
			var currentY = event.clientY - areaDiv.offsetTop;
			var width = Math.abs(currentX - startX);
			var height = Math.abs(currentY - startY);
			var left = Math.min(startX, currentX);
			var top = Math.min(startY, currentY);

			if (newcomponentType === 'button') {
				var newButton = document.createElement('button');
				newButton.innerText = 'New Button';
				newButton.style.position = 'absolute';
				newButton.style.left = left + 'px';
				newButton.style.top = top + 'px';
				newButton.style.width = width + 'px';
				newButton.style.height = height + 'px';
				areaDiv.appendChild(newButton);
			}
			isDrawing = false;
			areaDiv.removeEventListener('mouseup', createComponent);
			areaDiv.removeEventListener('mousemove', updateSelection);
			areaDiv.removeEventListener('mousedown', startSelection);
		}
	}

最後面有嘗試過下列寫法,一樣是無法取消

			isDrawing = false;
			areaDiv.removeEventListener('mousemove', updateSelection);
			areaDiv.removeEventListener('mouseup', function(event) {
				createComponent(event, newcomponentType);
			});
			areaDiv.removeEventListener('mousedown', function(event) {
				startSelection(event, newcomponentType);
			});
看更多先前的討論...收起先前的討論...
froce iT邦大師 1 級 ‧ 2024-01-16 13:40:45 檢舉
你也不是新人了,問問題的code簡化一下,然後把你要的什麼的情境描述一下。
搞不好根本不用這樣設計。
rain_yu iT邦新手 1 級 ‧ 2024-01-16 17:20:12 檢舉
我是搞不懂,因為我工作上都是寫別的居多。
這邊是我想要額外學習的地方,所以底子挺差的
froce iT邦大師 1 級 ‧ 2024-01-16 21:01:37 檢舉
問問題的技巧和你語言功力沒關係吧?
然後你這把所有無關緊要的code都丟上來,還沒說你到底哪邊要傳參數,哪有辦法回你…
想幫你試還不太能試,太多沒必要的code了

像我還以為你要在綁定(event handler)的時候就傳參數,結果只是handler裡面的函數想重複利用,跟你題目不太相同,我也看不懂你要removeEventListener是要用來幹嘛
rain_yu iT邦新手 1 級 ‧ 2024-01-17 08:38:16 檢舉
沒關係,我也看不懂你在講甚麼;
你可能看到我問題的主因是由其他狀況發生的。

但我當下只覺得問題是無法removeEventListener,
因為我是寫死的情況下改用參數傳遞去使用function。
會列出那些程式是方便大老看到可以做前後對比,
而且也只有這些程式有不一樣

後來我改變寫法,解決了問題。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
wenyen84
iT邦新手 5 級 ‧ 2024-01-16 12:30:36
最佳解答

areaDiv.addEventListener('mousedown', function(event){})
因為你的新做法是用匿名函數處理事件,這種做法沒辦法removeEventListener。
如果要達成你要的功能,可以 button、text、label各寫一組function處理,或是用全域變數來傳遞參數。

看更多先前的回應...收起先前的回應...
rain_yu iT邦新手 1 級 ‧ 2024-01-16 17:19:31 檢舉

感謝回答,但是我問題中的的寫法就是AI解決匿名函數寫法,
他當時也是說我是用匿名函數;但是AI的寫法無法處理這問題。
實際上我也不太懂那是啥意思。
我後來將程式重新改寫成

newButton.addEventListener('click', function() {
        startSelection('button');
    });
    

再來微調就OK了

wenyen84 iT邦新手 5 級 ‧ 2024-01-17 08:53:32 檢舉

這樣mousedown的部分就解決了,不過我很好奇你怎麼處理mouseup,可以的話能分享一下嗎?

rain_yu iT邦新手 1 級 ‧ 2024-01-17 13:36:10 檢舉

老實說原理我也不太懂,程式上整體來說沒甚麼變,
主要是在startSelection中move & up寫到dowm內。
其實只要remove down listener就好,但是我有寫其他程式,
所以都要做移除動作。


newButton.addEventListener('click', function() {
        startSelection('button');
    });
function startSelection(type) {
		componentType = type;
        isDrawing = true;
        areaDiv.addEventListener('mousedown', function(event) {
            startX = event.clientX - areaDiv.offsetLeft;
            startY = event.clientY - areaDiv.offsetTop;
            areaDiv.addEventListener('mousemove', updateSelection);
            areaDiv.addEventListener('mouseup', function(event) {
                createComponent(event, componentType);
            });
        });
    }
function createComponent(event, componentType) {
        if (isDrawing) {
            var currentX = event.clientX - areaDiv.offsetLeft;
            var currentY = event.clientY - areaDiv.offsetTop;
            var width = Math.abs(currentX - startX);
            var height = Math.abs(currentY - startY);
            var left = Math.min(startX, currentX);
            var top = Math.min(startY, currentY);
            if (componentType === 'button' || componentType === 'label') {
            //省略
            }
            isDrawing = false;
			componentType = null;
            areaDiv.removeEventListener('mousemove', updateSelection);
            areaDiv.removeEventListener('mouseup', createComponent);
            areaDiv.removeEventListener('mousedown', startSelection);
			if (areaDiv.contains(selectionDiv)) {
				areaDiv.removeChild(selectionDiv);
			}
		}
    }
rain_yu iT邦新手 1 級 ‧ 2024-01-17 13:49:20 檢舉

現在解決後GPT的事後諸葛表示。

程式二可以使用removeEventListener方法,而程式一不行的原因是因為事件監聽器在每次點擊事件觸發後都會重新創建。

在程式一中,每次點擊newButton後,都會創建一個新的mousedown事件監聽器,並將其添加到areaDiv上。這導致areaDiv上存在多個相同的mousedown事件監聽器。當你嘗試使用areaDiv.removeEventListener來移除事件監聽器時,它只會移除最後一次添加的事件監聽器,而不是你期望的那個。

相反,在程式二中,只有一個mousedown事件監聽器被添加到areaDiv上,並在每次點擊newButton時都保持不變。因此,當你使用areaDiv.removeEventListener來移除事件監聽器時,它能正確地移除該事件監聽器。

要解決程式一中無法正確移除事件監聽器的問題,你可以將事件監聽器定義為具名函式,然後在需要移除它時使用相同的函式名稱來移除。這樣就可以避免重複添加事件監聽器的問題。

我要發表回答

立即登入回答