【问题标题】:Lazy <option> loading延迟 <option> 加载
【发布时间】:2017-07-08 16:33:03
【问题描述】:

假设我有这样的选择:

<select size="4">
  <option id="1">Please wait ...</option>
  <option id="2">Please wait ...</option>
  <option id="3">Please wait ...</option>
  <option id="4">Please wait ...</option>
  <option id="5">Please wait ...</option>
</select>

我应该看到一个包含 4 个元素的列表,右侧有一个滚动条。

如果选项以某种方式可见(滚动和/或初始),我现在想做的是通过 ajax 加载文本。

编辑:

最后,由于元数据传输量很大,我不会懒惰地加载它们。这是我必须上传的请求(发送到服务器):

这对于单个元素的延迟加载是不可接受的。

【问题讨论】:

  • 您可以通过 JSON 和/或 Ajax 轻松地将数据拉入

标签: jquery lazy-loading visibility


【解决方案1】:

我很抱歉我的英语不好,但是当我理解这个问题时,我可以提出这个解决方案:

$(document).ready(function(){
  $('select').on('scroll', function(){
    var sel = $(this);
    var lasto = sel.find('option:last');
    var s = sel.position().top + sel.height();
    var o = lasto.height() + lasto.position().top - 4;
    setTimeout(function(){
      if(o < s){console.log('We need AJAX!');}
    }, 2200);
  });
});

Link

【讨论】:

    【解决方案2】:

    你是这样做的:

    只有在元素可见时才会加载。

    function loadSelect() {
      elementsDisplayed = Math.ceil(($(this).scrollTop() + Number($(this).css("padding-top").slice(0,-2))) / $(this).find("option:first").height() + parseFloat($(this).attr("size")));
    
      $(this).find("option").slice(0,elementsDisplayed).not(".loaded").each(function () {
        $(this).addClass("loaded"); //prevents spam reloading certain elements
    
        /*$.post("fetch.php", {
                  dataId : $(this).attr("id")
              }, function (data) {
                  //Yay, we are now loaded
              });*/
    
        console.log("Loading : " + $(this).attr("id"));
      });
    }
    
    $("select").on("scroll", loadSelect);
    
    loadSelect.bind($("select"))();
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <select size="4" style="padding:14px">
      <option id="1">Please wait ...</option>
      <option id="2">Please wait ...</option>
      <option id="3">Please wait ...</option>
      <option id="4">Please wait ...</option>
      <option id="5">Please wait ...</option>
      <option id="6">Please wait ...</option>
      <option id="7">Please wait ...</option>
      <option id="8">Please wait ...</option>
      <option id="9">Please wait ...</option>
      <option id="10">Please wait ...</option>
    </select>

    【讨论】:

    • 1.那些在开始时可见的人不会在不滚动的情况下加载。 2. 他们提前加载一个元素。
    • 1.我在新版本中修复了这个问题。 2. 我认为先加载一个而不是潜在地加载一个更有意义...从技术上讲,代码会加载任何可见和部分可见的元素。
    • 如果您不希望它加载“提前一个”,我可以更新代码以使用 Math.floor 而不是 Math.ceil
    • 你的意思是 size="4" 显示第五部分?这将是一个错误。
    • 好的,但是如果我将选择的填充设置为 14px,我可以看到第五个尚未加载的人
    【解决方案3】:

    您可以将元素/选项传递给下面的函数以检查元素是否可见并执行您的 AJAX 函数调用。

    function isVisible(element) {
      var bx = element.getBoundingClientRect();
      var viewh = Math.max(document.documentElement.clientHeight, window.innerHeight);
      return !(bx.bottom < 0 || bx.top - viewHeight >= 0);
    }
    

    执行会像

    if(isVisible(document.getElementById("select_id")))
    {
    /* Execute your ajax call here */
    }
    

    【讨论】:

    • Thies 必须被调用,但我喜欢注册一个处理程序。
    【解决方案4】:

    你可以试试this。它并没有真正使用选择。它使用 JS 重新创建其行为。您应该尝试使用 jsfiddle,因为它与 http 请求有问题。

    ajax 加载元素的处理还没有工作,很容易修复。

    function loadMoreItems() {
      var requestStr = "http://randomword.setgetgo.com/get.php";
      alert("load triggered")
      $.ajax({
        type: "GET",
        url: requestStr,
        dataType: "jsonp",
        jsonpCallback: 'RandomWordComplete'
      });
    };
    
    function RandomWordComplete(data) {
      var op = $("li.option.last")
      op.removeClass("last")
      var li = $("<li>"+data.Word+"</li>")
      li.addClass("option")
      li.addClass("last")
      li.data("value", op.data("value") + 1)
      $("#select").append(li)
      li.slideDown()
    }
    
    $("document").ready(function() {
      $(".option").click(function() {
        $(".option").slideDown();
      });
    
      $(".option:not(.selected)").click(function() {
        $(".option:not(.selected)").slideUp();
    
        $(".option.selected").text($(this).text())
        $("#selectVal").val($(this).data("value"))
      });
    
      $("#select").scroll(function() {
        var div = $(this);
        if (div[0].scrollHeight - div.scrollTop() == div.height()) {
          loadMoreItems();
        }
    
      });
    });
    li {
      list-style: none
    }
    
    .option {
      display: none;
      margin: 10px 0
    }
    
    .option:first-child {
      display: block
    }
    
    .option:not(.selected):hover {
      background: red
    }
    
    #select {
      border: 1px solid black;
      width: 180px;
      cursor: pointer;
      max-height: 60px;
      overflow: auto
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <ul id="select">
      <li class="option selected">--</li>
      <li class="option" data-value="0">Spain</li>
      <li class="option last" data-value="1">Portugal</li>
    
    </ul>
    <input id="selectVal" type="hidden" value="" />

    【讨论】:

    • 好的,但它不是选项标签。
    • 我知道。但行为是相似的,并且比典型的选择更可定制
    • 另一种选择是使用插件。您在此处解释了解决方案:stackoverflow.com/a/32094259/2127296
    【解决方案5】:

    这样的东西可能对你有用,它基本上只是检查选项的偏移量,但也确保你没有发送多个 ajax 请求

    $(function () {
    
      var api = 'https://jsonplaceholder.typicode.com'
      var url = api + '/posts/1'
    
      var select = $('select')
      var option = select.find('option')
      var selectTop = select.offset().top
      var selectHeight = select.height()
      var inview, optionTop
    
      select.on('scroll', function () {
        option.each(function () {
    
          var _this = $(this)
    
          optionTop = _this.offset().top
          inview = optionTop >= selectTop && optionTop < selectTop + selectHeight
    
          // check that the option element is in range
          if (inview) {
    
            // don't send multiple requests if already triggered
            if (
              _this.attr('data-status') !== 'success'
              && _this.attr('data-status') !== 'loading'
              && _this.attr('data-status') !== 'error'
            ) {
              _this.attr('data-status', 'loading')
              _this.text('Loading ...')
              $.ajax({
                url: url,
                method: 'GET',
                success: function ajaxSuccess(resp) {
                  _this.attr('data-status', 'success')
                  _this.text(resp.title)
                },
                error: function ajaxError(xhr) {
                  _this.attr('data-status', 'error')
                  _this.text('Error ...')
                  console.log(xhr.responseText)
                }
              })
            }
          }
        })
      })
    
      // bootstrap
      select.triggerHandler('scroll')
    })
    

    查看JSFiddle here,它加载速度很快,您可以注释掉triggerHandler 以防止它在页面加载时发送请求

    编辑:我还更新了选项元素的 ID,因为 ID 不应该以数字开头

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 2021-07-13
      • 2010-11-26
      • 2011-08-26
      • 2018-08-08
      • 2018-04-28
      相关资源
      最近更新 更多