【问题标题】:jQuery appendTo() without reloading embedded contentjQuery appendTo() 无需重新加载嵌入内容
【发布时间】:2016-03-04 02:34:55
【问题描述】:

我用 jQuery 编写了一个堆叠函数,它采用容器元素 .search-results,收集容器中每个 .col 元素中的所有 .card 元素,然后将它们重新堆叠到多个列中,这些列是根据计算得出的离开容器的宽度。

页面加载时,第一列中的所有卡片都被初始化,随后的列被隐藏。然后,脚本会取消隐藏它确定应该存在的许多列,并遍历列和卡片,使用 appendTo 在列之间均匀分布卡片。

我创建了一个 jsFiddle 来演示该过程。

在页面加载时调用该脚本时效果很好。如果我想在页面加载后调用脚本,我会遇到一个严重的问题。如果我移除其中一张卡片并想重新堆叠它们以保持分布均匀,我必须再次调用堆叠函数。当我这样做时,它会导致重新加载卡片中的嵌入内容(例如嵌入的推文),这是不可取的。请注意,当页面加载时,Tweets 直到调用 stacking 函数后才会初始化。

在我的示例中,我有意迭代推文 ID 以使用 twttr.widgets.createTweet() 重新初始化它们,但是如果我省略该步骤,则推文会在卡片重新堆叠后消失。如果我检查卡片,我可以看到 Tweet 小部件 iframe 仍然存在,但 iframe 的 body 是空的。

现在显然我可以在重新堆叠卡片后简单地重新初始化我的推文,但这会提供糟糕的用户体验,因为在(重新)初始化嵌入式推文时会有延迟。我之前曾提出过与此相关的question。我发现我可以使用.clone()appendTo() 从控制台手动移动卡片而无需重新加载嵌入式推文,但是我没有运气重构我的堆叠功能来利用这一点行为,这就是我问这个问题的原因。

这是我的堆叠功能:

function resizeColumns(layoutElem, ignoreRank, width) {
    if (width === undefined) {
        var colMin = 300;
    } else {
        var colMin = width;
    }

    var w = layoutElem.width();
    var numCols = Math.floor(w / colMin);
    if (numCols === 0) numCols = 1;

    layoutElem.removeClass('cols-1 cols-2 cols-3 cols-4 cols-5 cols-6 cols-7 cols-8 cols-9 cols-10 cols-11 cols-12');
    layoutElem.addClass('cols-' + numCols);
    var cols = layoutElem.find('.col');
    var cards = cols.find('.card');
    var sortedCards = [];
    cards.each(function(i) {
        var rank;
        if (!ignoreRank) {
            rank = parseInt($(this).attr('rank'));
            if (isNaN(rank)) rank = 1000000;
        } else {
            var o = parseInt($(this).attr('order'));
            if (isNaN(o)) {
                rank = i;
                $(this).attr('order', i);
            } else {
                rank = o;
            }
        }
        sortedCards.push({
            rank: rank,
            element: $(this)
        });
    });
    sortedCards.sort(rankCompare);
    var curCol = 0;
    for (var i in sortedCards) {
        var cardElem = sortedCards[i].element;
        cardElem.appendTo($(cols[curCol]));
        curCol++;
        if (curCol >= numCols) curCol = 0;
    }
    // hide any additional columns
    cols.each(function(i) {
        if (i >= numCols) {
            $(this).hide();
        } else {
            $(this).show();
        }
    });

    function rankCompare(a, b) {
        if (a.rank < b.rank)
        return -1;
        if (a.rank > b.rank)
        return 1;
        return 0;
    }
}

我在 jsFiddle 中堆叠卡片和​​初始化推文的步骤

第一次调用该函数时,我引入了一个延迟,以便定义 $scope.cards。这是第一个电话:

$timeout(function() {
    // Only the first argument is required.
    resizeColumns($('.cards'), true, 250);
}, 250)

在我调用resizeColumns 函数后,我在第一次初始化推文之前设置了一个延迟。这是必不可少的,以便 Twitter 小部件脚本可以在 DOM 中定位推文。

推文初始化后,我将延迟设置为 4 秒,然后再取出卡片并重新堆叠卡片。最后,一旦重新堆叠卡片,我就会重新初始化推文。最后一步是我想要避免的。我不想重新初始化推文,因为这是一个缓慢的过程。我希望卡片移动后立即重新出现推文。

$timeout(function() {
    // Iterate over the Tweet IDs and initialize them.
    ids.forEach(function(id) {
        twttr.widgets.createTweet(id, document.getElementById(id));
    });

    $timeout(function() {
        // Wait a few seconds and then remove a card from the DOM.
        $('#' + $scope.cards[1].id).detach();
        // Restack cards
        resizeColumns($('.cards'), true, 250);
        $timeout(function() {
            // Reinitialize Tweets after cards have been restacked. This is the step I want to avoid.
            ids.forEach(function(id) {
                twttr.widgets.createTweet(id, document.getElementById(id));
            });
        }, 500)
    }, 4000);
}, 1000);

【问题讨论】:

    标签: javascript jquery twitter


    【解决方案1】:

    根据其他问题的答案,尝试更改:

        sortedCards.push({
            rank: rank,
            element: $(this)
        });
    

    到:

        sortedCards.push({
            rank: rank,
            element: $(this).clone();
        });
        $(this).detach();
    

    或者您可以在appendTo 循环中进行克隆和分离:

    for (var i in sortedCards) {
        var cardElem = sortedCards[i].element.clone();
        cardElem.appendTo($(cols[curCol]));
        sortedCards[i].element.detach()
        curCol = (curCol + 1) % numCols;
    }
    

    【讨论】:

    • 我对如何将.clone() 应用于该函数有相同的想法,但我无法让它工作。在小提琴上进行了测试,第二次调用该函数后,推文仍然消失。也就是说我必须重新初始化它们,这是我想要避免的。
    • 我已将代码添加到您的小提琴中,如何让它再次调用该函数?
    • 我刚刚更新了我的问题,更清楚地解释了我堆叠/重新堆叠卡片所采取的步骤。让我知道这是否有意义。
    • 我认为超时函数中的detach() 是问题所在。为什么在致电resizeColumns 之前需要这样做?
    • 我用它来模拟用户隐藏其中一张卡片。在我的实际应用中,卡片有一个隐藏它们的按钮。这样做会切换一个布尔属性,触发卡片通过附加到卡片的ng-if 块从 DOM 中删除。我不想尝试复制小提琴中的所有附加功能,所以我只使用了.detach()。可以肯定的是,我确实在实际应用程序上测试了您的代码,但行为与小提琴中的相同。
    猜你喜欢
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多