【问题标题】:Knockout ObservableArray in custom binding自定义绑定中的淘汰 ObservableArray
【发布时间】:2018-06-02 09:59:19
【问题描述】:

我可以在自定义绑定的 init 块内创建一个 observableArray 吗? 另外,我想在 update 方法中使用这个 observableArray 来推送一些新元素。

循环 例如:

    ko.bindingHandlers.yourBindingName = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var animateImageArray = ko.observableArray(["img1", "img2"]);
        ko.applyBindings(animateImageArray);
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        //Also can I get a reference to animateImageArray here
    }
};

HTML

    <div class="customized-slider-wrapper" data-bind="yourBindingName: someData">
    <div class="customized-slider" data-bind="foreach: animateImageArray">
    <div class="individual-tile">
        <img data-bind= "attr: {src: $data}" />
    </div>
    </div>
</div>

编辑:

在评论中尝试了以下代码

      StopAnimation = setInterval(function () {

        _index++;
        if (_index >= imgArray.length) {
          _index = 0;
        }


         $(temp[_index]).attr('src', imgArray[_index]);


        toBeScrolledBy = slideWidth * _index;
        $(scroller).css({
          'transform': 'translateX(-' + toBeScrolledBy + 'px)'
        });

      }, 1500);

现在图像动画的顺序出错了。 第一个图像滑动和第二个加载,动画回到第一个而不是第三个,并且每次在图像 src 数组中传递一个新索引时都会发生这种情况。

【问题讨论】:

  • 你在哪里使用someData?通常绑定使用绑定到它的值(例如,通过使用ko.unwrap(valueAccessor()) 的结果)。另外,由于您的数组是静态的,因此不需要它是可观察的,也不需要提供init 函数。如果数组不是静态的,它应该是你没有使用的someData
  • 是的,我正在使用 var data = ko.unwrap(valueAccessor());获取 someData 的值以向 dom 添加一些信息。我正在寻找一种在我的自定义绑定中拥有一个新的 Obeserable 数组的方法
  • 您需要提供更多详细信息,我们才能为您提供有用的帮助。就目前而言,在init 中创建自己的可观察数组是没有意义的。
  • 我创建了自定义绑定以在电子商务产品列表页面上显示产品磁贴。产品的每张图片有 3-8 张图片。当用户将鼠标悬停在一个图像上时,我想制作动画并开始图像的侧面展示。我教过一个可观察的数组是否可以一张一张地推送图像并将它们显示在视图中。这是否清除了场景?
  • 一点(你应该编辑你的问题,而不是评论更多细节)——它告诉我可观察数组应该是你绑定到处理程序的数据的一部分(例如,部分someData),而不是处理程序突然创建的东西。毕竟,它需要图片,而且这些图片因产品而异。

标签: javascript knockout.js


【解决方案1】:

根据您的描述,init 不应该创建数组,并且数组可能不必是可观察的。相反,您的可观察产品数组将包含对象,并且每个产品对象将具有其图像的数组(可能不必是可观察的)。粗略的草图:

var vm = {
  products: ko.observableArray([
      {
          name: "Widget",
          images: [
              "https://via.placeholder.com/100/5d5/fff.png?text=Widget+1",
              "https://via.placeholder.com/100/d55/fff.png?text=Widget+2",
              "https://via.placeholder.com/100/55d/fff.png?text=Widget+3"
          ]
      },
      {
          name: "Gadget",
          images: [
              "https://via.placeholder.com/100/55d/fff.png?text=Gadget+1",
              "https://via.placeholder.com/100/5d5/fff.png?text=Gadget+2",
              "https://via.placeholder.com/100/d55/fff.png?text=Gadget+3",
              "https://via.placeholder.com/100/55d/fff.png?text=Gadget+4",
              "https://via.placeholder.com/100/5d5/fff.png?text=Gadget+5"
          ]
      },
  ])
};

ko.bindingHandlers.productSlides = {
    init: function(element, valueAccessor) {
      // Current timer handle
      var timer = 0;
      // Current slide index
      var index = 0;

      // Show first slide
      element.src = ko.unwrap(valueAccessor())[index];

      // Set up handlers
      element.addEventListener("mouseenter", startTimer);
      element.addEventListener("mouseleave", clearTimer);
  
      // Show next slide
      function nextSlide() {
          // Re-read the observable in case it's changed
          var slides = ko.unwrap(valueAccessor());
          index = (index + 1) % slides.length;
          element.src = slides[index];
      }
  
      // Start showing slides
      function startTimer() {
        if (!timer) {
            nextSlide();
            timer = setInterval(nextSlide, 1000);
        }
      }
      
      // Stop showing slides
      function clearTimer() {
          if (timer) {
              clearInterval(timer);
              timer = 0;
          }
      }
      
      // Clean up on disposal
      ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
          element.removeEventListener("mouseenter", startTimer);
          element.removeEventListener("mouseleave", clearTimer);
          clearTimer();
      });
    }
};

console.log("Showing products");
ko.applyBindings(vm, document.body);

// Example of adding another product to the array later
setTimeout(function() {
    console.log("Adding third product");
    vm.products.push({
        name: "Doogle",
        images: [
            "https://via.placeholder.com/100/d55/fff.png?text=Doogle+1",
            "https://via.placeholder.com/100/5d5/fff.png?text=Doogle+2",
            "https://via.placeholder.com/100/55d/fff.png?text=Doogle+3",
            "https://via.placeholder.com/100/d55/fff.png?text=Doogle+4"
        ]
    });
}, 2000);
<div data-bind="foreach: products">
  <img data-bind="productSlides: images">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

【讨论】:

  • 已尝试您的代码并面临问题,已编辑我的问题并添加了我的代码。你能检查一下吗?
  • 不确定为什么鼠标悬停事件在幻灯片更改后被取消注册
  • @HarpreetSinghSaini - 恕我直言,关于 SO 的问题并不意味着成为移动目标。我通过运行演示回答了您提出的问题。如果您在应用它时遇到问题,则需要更多的上下文。几天后将其添加到问题中并不理想。相反,请继续努力,如果您无法解决,请发布一个新问题,并附上问题的 minimal reproducible example
  • 道歉!。已创建一个新问题并将上述内容标记为正确。新链接在下面stackoverflow.com/questions/50703902/…
猜你喜欢
  • 1970-01-01
  • 2014-02-05
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多