【问题标题】:onclick with two function calls takes two clicks to run both functions js带有两个函数调用的 onclick 需要两次单击才能运行两个函数 js
【发布时间】:2019-11-07 16:50:48
【问题描述】:

这可能会被标记为重复,因为已经有很多关于此的 SO 问题,但我无法将这些问题的答案应用到我的代码中。

我在我的 Blob 存储页面代码中使用 Razor、html、css 和 javascript。

在下图中的左侧有三个容器。当点击其中一个时,他们将打开并显示他们所有的孩子(blob)。第一次单击其中一个容器时,只有一个函数调用运行 (listContainerBlobs()),而不是打开容器的那个 (showHide())。

下面是调用onclick函数的html p-tag。

<p class="blob-container" onclick="showHide('@containerId', '@arrowId');listContainerBlobs('@jsonBlob', '@container.Name');"><i class="fa fa-caret-right" id="@arrowId"></i>  @container.Name</p>

带有 C# 和 razor 的完整 div:

 <aside class="aside">
    <div class="aside-header">

        <i class="fa fa-plus add-container-button aside-header-icons" onclick="addContainer()"></i><i class="fa fa-search search-button aside-header-icons"></i>
        <input id="searchBox" type="text" onkeyup="search()" name="search" placeholder="Search blobs..." />
    </div>
    <div class="aside-containers">
        @foreach (var container in containers)
        {
            caretArrowNumber++;
            string arrowId = "arrowId-" + caretArrowNumber;
            containerNumber++;
            string containerId = "containerId-" + containerNumber;
            var blobs = await Model.ListContainerBlobs(container.Name);
            //var jsonBlob = Json.Serialize(blobs);
            List<object> blobObject = new List<object>();
            blobObject.Add(new
            {
                blobCount = blobs.Count,
                blobs = blobs.Select(x => new
                {
                    Name = x.Name,
                    Container = container.Name,
                    Blobtype = x.BlobType,
                    Uri = x.Uri
                })
            });

            var jsonBlob = JsonConvert.SerializeObject(blobObject);

            <div class="arrow-blob-container">
                <p class="blob-container" onclick="showHide('@containerId', '@arrowId');listContainerBlobs('@jsonBlob', '@container.Name');"><i class="fa fa-caret-right" id="@arrowId"></i>  @container.Name</p>
            </div>
            <div class="showBlob" id="@containerId">
                <div class="ml-4">
                    @foreach (var blob in blobs)
                    {
                        blobNumber++;
                        string blobId = "blobId-" + blobNumber;
                        <div>
                            <input class="blobs" id="@blobId" type="button" value="@blob.Name" onclick="downloadBlob('@blobId', '@blob.Name', '@blob.Container.Name')" />
                        </div>
                    }
                </div>
            </div>

        }
    </div>
</aside>

以下代码是 onclick 调用的两个函数:

<script>
function listContainerBlobs(json, container) {
    console.log("beginning");
    console.log(json);

    var arr = JSON.parse(json);

    console.log(arr);
    var blobs = document.getElementById('container-blob-display').innerHTML = "<h4>" + container + "</h4>";
    var otherDiv = document.getElementById('section-1');
    var thisDiv = document.getElementById('section-2');

    otherDiv.style.display = 'none';
    thisDiv.style.display = 'inline';

    var blobNumber = 0;

    for (i = 0; i < arr.length; i++){
        blobNumber++;
        var blobId = "blobId" + blobNumber;
        blobs += "<p class='search-result' id='" + blobId + "' onclick='downloadBlob('" + blobId + "', '" + arr[i].Name + "', '" + container + "')'>" + arr[i].Name + "</p>";
    }
    console.log(blobs);
}

function showHide(containerId, arrowId) {
    var c = document.getElementById(containerId);
    var a = document.getElementById(arrowId);

    if (c.style.display === "none") {
        c.style.display = "inline";
        a.className = "fa fa-caret-down";
    } else {
        c.style.display = "none";
        a.className = "fa fa-caret-right";
    }
}
</script>

我试过了

  • 注释掉ListContainerBlobs()-函数
  • 注释掉所有的 css
  • 从 style.display = "block" 更改为 "inline"(见示例代码)
  • 将整个脚本部分移至 html 顶部
  • 注释掉了 html 中的几乎所有代码,除了最必要的代码

showHide() 仍然不会在第一次点击时运行。

所以目前,第一次点击listContainerBlobs() 运行,第二次点击showHide() 运行,但我希望它们都在第一次点击时运行。

感谢我能得到的所有帮助!提前致谢!

P.S 我很想做一个 jsfiddle,但它似乎不理解 C# 和 List(认为 是一个标签)


从 Mr. Smiths 解决方案编辑

使用 Smith 先生的这个解决方案,我仍然需要单击两次才能运行这两个功能:

HTML:

<div class="arrow-blob-container">
    <p class="blob-container aside-content" id="@newContId" data-containerId="@containerId" data-arrowId="@arrowId" data-jsonBlob="@jsonBlob" data-containerName="@container.Name"><i class="fa fa-caret-right" id="@arrowId"></i>  @container.Name</p>
</div>

Js:

document.querySelectorAll('.aside-content').forEach(element => {
    element.addEventListener('click', function (e) {
        let ds = this.dataset;

        showHide(ds.containerid, ds.arrowid);
        listContainerBlobs(ds.jsonblob, ds.containername);
    })
});

这对正确的 id 和其他值一直有效,但就像我说的,我仍然需要单击两次才能调用这两个函数。第一次点击运行listContainerBlobs(),第二次点击showHide()

你知道为什么会这样吗?

【问题讨论】:

  • 当需要附加多个事件时,我建议使用事件监听器而不是onclick,至于您的函数参数,您可以将它们设置为data 属性并在您的函数中访问它们跨度>
  • 您能否举例说明如何将变量设置为数据属性(我不完全了解 javascript -. -)@empiric 最好同时调用标签内的其他两个函数.onclick 函数()?
  • 设置数据属性只是 HTML:data-containerid="@containerId" 等等。到access these attributes 你可以这样做:document.querySelector("@arrowId").dataset.containerid。类似的东西
  • @empiric 如何querySelector 哪个 Id 是正确的,因为 Id 是一个变量,其中最终数字在每个循环中都会增加。那么js真的知道我用@arrowId点击的是哪一个吗? (将在 p-tag 上放置一个新的 Id,但现在让我们使用 arrowId 运行)
  • 您还可以使用类选择器在所有p 标签上绑定事件处理程序,并在函数内使用this 来引用调用事件处理程序的元素

标签: javascript html css onclick


【解决方案1】:

你可以创建一个事件监听器来调用你的函数:

<div class="arrow-blob-container">
    <p class="blob-container" data-container-id="@containerId" data-arrow-id="@arrowId" data-json-blob="@jsonBlob" data-container-name="@container.Name" ><i class="fa fa-caret-right" id="@arrowId"></i>  @container.Name</p>
</div>

脚本:

<script>
    document.querySelectorAll('.blob-container').forEach(element => {
        element.addEventListener('click', function(e) {
            let dataset = e.currentTarget.dataset;

            showHide(dataset.containerId, dataset.arrowId);
            listContainerBlobs(dataset.jsonBlob, dataset.containerName);
        });
    });
</script>

检查这个sn-p:

document.querySelectorAll('.blob-container').forEach(element => {
  element.addEventListener('click', function(e) {
    let dataset = e.currentTarget.dataset;

    console.log("containerId: " + dataset.containerId);
    console.log("arrowId: " + dataset.arrowId);
    console.log("jsonBlob: " + dataset.jsonBlob);
    console.log("containerName: " + dataset.containerName);
  });
});
<div class="arrow-blob-container">
  <button class="blob-container" data-container-id="container1" data-arrow-id="arrow1" data-json-blob="{...}" data-container-name="Button1">Display dataset</button>
  <button class="blob-container" data-container-id="container2" data-arrow-id="arrow2" data-json-blob="{...}" data-container-name="Button2">Display dataset</button>
  <button class="blob-container" data-container-id="container3" data-arrow-id="arrow3" data-json-blob="{...}" data-container-name="Button3">Display dataset</button>
  <button class="blob-container" data-container-id="container4" data-arrow-id="arrow4" data-json-blob="{...}" data-container-name="Button4">Display dataset</button>
</div>

这也可以在没有可能更清晰的 querySelector 的情况下工作:

function onButtonClick(e) {
    let dataset = e.dataset;

    console.log("containerId: " + dataset.containerId);
    console.log("arrowId: " + dataset.arrowId);
    console.log("jsonBlob: " + dataset.jsonBlob);
    console.log("containerName: " + dataset.containerName);
}
<div class="arrow-blob-container">
  <button class="blob-container" onClick="onButtonClick(this)" data-container-id="container1" data-arrow-id="arrow1" data-json-blob="{...}" data-container-name="Button1">Display dataset</button>
  <button class="blob-container" onClick="onButtonClick(this)" data-container-id="container2" data-arrow-id="arrow2" data-json-blob="{...}" data-container-name="Button2">Display dataset</button>
  <button class="blob-container" onClick="onButtonClick(this)" data-container-id="container3" data-arrow-id="arrow3" data-json-blob="{...}" data-container-name="Button3">Display dataset</button>
  <button class="blob-container" onClick="onButtonClick(this)" data-container-id="container4" data-arrow-id="arrow4" data-json-blob="{...}" data-container-name="Button4">Display dataset</button>
</div>

【讨论】:

  • 我在e 上没有收到currentTarget。浏览器吐出:e ==[object MouseEvent] contId = undefined arrId= undefined json = undefined contanerName = undefined。此外,它只是第一个可点击的对象,而不是其余的。
  • e.currentTarget 是被点击的元素。您应该能够使用它找到正确的元素。如果它始终是“.blob-container”,请改用查询选择器。您可以通过该元素上的 dataset 属性访问数据属性(如在您的编辑中)。检查:developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/…
  • p-tag 确实是一个固定元素,但其中会有几个。就像我说的,它只是第一个可点击的。查询选择器 = Returns the first element that is a descendant of node that matches selectors。我不知道这是否是正确的方法(主要是因为我没有让它工作)。 :thinking-face:
  • 好吧,我添加了一个 sn-p 访问多个元素的数据集。希望有帮助
  • 好的,所以我已经尝试过了,现在它没有任何错误,尽管两个示例仍然存在单击 2 次的问题。该死!不过谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-23
  • 1970-01-01
  • 2016-12-01
  • 2020-12-12
  • 2021-02-26
  • 1970-01-01
相关资源
最近更新 更多