以编程方式创建元素后未处理 Ondragstart 事件

问题描述 投票:0回答:1

我正在创建一个 Web 构建器,我使用 svelte 来促进 UI 的某些功能,但 Web 构建器本身几乎是纯 JavaScript。我创建了一个工具面板,其中包含按比例创建的不同可拖动元素,以便可以将它们拖放到画布上(它是一个 div,但出于结构目的,我将其称为画布)。然而,为了在画布中创建 html 元素,我正在考虑将标签名称作为文本传递,并让它在画布内创建该类型的新元素。

拖放正在工作,并且元素确实是可拖动的,但问题出在 ondragstart 属性上。我还尝试向元素添加事件侦听器,但这仍然不起作用。此操作包含三个主要组成部分。第一个工具面板如下。用户将在这里看到他的工具并能够将它们拖到画布中

<script lang="ts">
    import { onMount } from "svelte";
    import {define_default_styles, define_default_content} from "$lib/helpers/default_element_configurations";

    let hidden:boolean = true
    let element_declaration:string[] = ["div", "h1", "h2", "p", "form", "input", "button"]
    let elements: (string | undefined)[] = [];
    let element_panel:HTMLElement

    onMount(()=>{
        for(let element of element_declaration){ 
            let newElement = document.createElement(element)
            newElement.className="rounded p-2 border"
            newElement.draggable=true
            newElement.ondragstart=(event)=>{
                console.log("dragstart event fired");
                event.dataTransfer?.setData("text/plain", "div");
                console.log("Data set: ", event.dataTransfer?.getData("text/plain"));
            }
            define_default_styles(newElement,element)
            define_default_content(newElement,element)
            elements.push(newElement.outerHTML)
        }
    })

</script>


<div class="flex items-center space-x-2 p-2 bg-gray-200">
    <h1 class="text-blue-500 font-bold text-xl">Scripter Web-Builder</h1>
    <button on:click={()=>{hidden=false}} class="bg-blue-500 text-white rounded text-center px-2 text-xl font-bold py-1 hover:bg-blue-700 active:bg-blue-900">+</button>
    
</div>
{#if !hidden}
    <div bind:this={element_panel} class="absolute border-2 w-1/4 min-h-52 bg-gray-50 rounded shadow-md">
        {#each elements as element}
            <div class="p-2">{@html element}</div>
        {/each}
    </div>
{/if}

这是一个添加附加功能的辅助函数,这是我尝试添加事件侦听器的地方。我已经删除了代码中的事件侦听器,但为了说明性目的,我将再次添加它 `

export function define_default_content(node:HTMLElement, node_type:string){
    switch(node_type){
        case "div":
            node.innerText="div"
            node.addEventListener("dragstart" ,(event)=>{
                console.log("dragstart event fired");
                event.dataTransfer?.setData("text/plain", "div");
                console.log("Data set: ", event.dataTransfer?.getData("text/plain"));
            })
            node.addEventListener("drop", (event)=>{event.stopPropagation()})
        break;

最后,这就是画布,它确实像宣传的那样工作

<script lang="ts">
    import {onMount} from "svelte"

    let canvas:HTMLElement
    onMount(()=>{
        canvas.addEventListener("dragenter",(e)=>e.preventDefault())
        canvas.addEventListener("dragover",(e)=>e.preventDefault())
        canvas.addEventListener("drop",(e)=>console.log(e.dataTransfer?.getData("text/plain")))
    })    
</script>


<div bind:this={canvas}>
    
</div>
javascript drag-and-drop svelte addeventlistener sveltekit
1个回答
0
投票

最好避免手动 DOM 操作,这可能会导致组件安装/卸载的干扰。

对于这样的事情,可以通过

{#each}
<svelte:element>
添加任意元素。

© www.soinside.com 2019 - 2024. All rights reserved.