针对jQuery的淘汰自定义绑定fadeIn fadeOut具有可观察对象

时间:2018-02-26 15:50:37

标签: jquery knockout.js

使用Knockout和jQuery,我希望编辑面板淡入淡出。 Knockout通过bindingHandlers工具调用jQuery方法。 fadeIn工作正常,但fadeOut没有。这是自定义绑定处理程序:

ko.bindingHandlers.fadeVisible = {
  init: function(element, valueAccessor) {
    // Initially set the element to be instantly visible/hidden depending on the value
    var value = valueAccessor();
    $(element).toggle(ko.unwrap(value)); // Use "unwrapObservable" so we can handle values that may or may not be observable
  },
  update: function(element, valueAccessor) {
    // Whenever the value subsequently changes, slowly fade the element in or out
    var value = valueAccessor();
    ko.unwrap(value) ? $(element).fadeIn("slow") : $(element).fadeOut("slow");
  }
};

我的HTML代码显示城市列表,并允许您编辑每个城市(显示一个编辑框)。我的HTML代码如下所示:

<div data-bind="foreach: cities">
  <span data-bind="text: name"></span>
  <button data-bind="click: $root.editCity">edit</button>
  <br />
</div>
<br />

<div data-bind="fadeVisible: cityToEdit">
  <div data-bind="if: cityToEdit">
    <div style="border: 1px solid #000; padding: 10px;">
      <h4>Edit Form</h4>
      <input data-bind="value: cityToEdit().name" />
      <br />
      <input data-bind="value: cityToEdit().population" />
      <br />
      <button data-bind="click: $root.cancelEdit">Cancel</button>
    </div>
  </div>
</div>

如果你进入小提琴,然后点击任何城市的编辑,你会看到编辑面板淡入。到现在为止还挺好。问题是当我淡出时。我需要fadeOut在清除可观察变量“cityToEdit”之前发生并完成,并且UI会更新以反映这一点。

https://jsfiddle.net/4qhkkeLh/50/

有什么方法可以实现fadeIn和fadeOut同时保持数据结构的方式?希望我可以调整自定义绑定。

我有办法实现吗?

1 个答案:

答案 0 :(得分:3)

if绑定会删除您尝试淡出的元素的内容。您可以通过多种方式解决此问题,具体取决于您希望实现的交互类型。

仅限查看修复

删除取消时的if绑定和清除输入:

<input data-bind="value: (cityToEdit() || {}).name" />
<br />
<input data-bind="value: (cityToEdit() || {}).population" />

var myVm = function() {
  var self = this;
  self.cities = ko.observableArray(
    [{
        'name': 'London',
        'population': 1000000
      },
      {
        'name': 'Cardiff',
        'population': 250000
      }
    ]
  );
  self.cityToEdit = ko.observable(null);

  self.editCity = function() {
    self.cityToEdit(this);
  }

  self.cancelEdit = function() {
    self.cityToEdit(null);
  }
}


ko.bindingHandlers.fadeVisible = {
  init: function(element, valueAccessor) {
    // Initially set the element to be instantly visible/hidden depending on the value
    var value = valueAccessor();
    $(element).toggle(ko.unwrap(value)); // Use "unwrapObservable" so we can handle values that may or may not be observable
  },
  update: function(element, valueAccessor) {
    // Whenever the value subsequently changes, slowly fade the element in or out
    var value = valueAccessor();
    ko.unwrap(value) ? $(element).fadeIn("slow") : $(element).fadeOut("slow");
  }
};


var vm = new myVm();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-bind="foreach: cities">
  <span data-bind="text: name"></span>
  <button data-bind="click: $root.editCity">edit</button>
  <br />
</div>
<br />

<div data-bind="fadeVisible: cityToEdit">
  <div data-bind="">
    <div style="border: 1px solid #000; padding: 10px;">
      <h4>Edit Form</h4>
      <input data-bind="value: (cityToEdit() || {}).name" />
      <br />
      <input data-bind="value: (cityToEdit() || {}).population" />
      <br />
      <button data-bind="click: $root.cancelEdit">Cancel</button>
    </div>
  </div>
</div>

下行:

  • 丑陋的数据绑定
  • 在淡入淡出之前清除值有点跳跃

更好的修复

创建一个控制可见性的新属性:

self.cityToEdit = ko.observable(null);
self.canEdit = ko.observable(false);
self.cityToEdit.subscribe(city => self.canEdit(true));

self.cancelEdit = function() {
  self.canEdit(false);
}

绑定到canEdit而不是cityToEdit

 <div data-bind="fadeVisible: canEdit"> ... </div>

var myVm = function() {
  var self = this;
  self.cities = ko.observableArray(
    [{
        'name': 'London',
        'population': 1000000
      },
      {
        'name': 'Cardiff',
        'population': 250000
      }
    ]
  );
  self.cityToEdit = ko.observable(null);
  self.canEdit = ko.observable(false);
  self.cityToEdit.subscribe(city => self.canEdit(true));
  
  
  self.editCity = function() {
    self.cityToEdit(this);
  }

  self.cancelEdit = function() {
    self.canEdit(false);
  }
}


ko.bindingHandlers.fadeVisible = {
  init: function(element, valueAccessor) {
    // Initially set the element to be instantly visible/hidden depending on the value
    var value = valueAccessor();
    $(element).toggle(ko.unwrap(value)); // Use "unwrapObservable" so we can handle values that may or may not be observable
  },
  update: function(element, valueAccessor) {
    // Whenever the value subsequently changes, slowly fade the element in or out
    var value = valueAccessor();
    ko.unwrap(value) ? $(element).fadeIn("slow") : $(element).fadeOut("slow");
  }
};


var vm = new myVm();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-bind="foreach: cities">
  <span data-bind="text: name"></span>
  <button data-bind="click: $root.editCity">edit</button>
  <br />
</div>
<br />

<div data-bind="fadeVisible: canEdit">
  <div style="border: 1px solid #000; padding: 10px;">
    <h4>Edit Form</h4>
    <input data-bind="value: (cityToEdit() || {}).name" />
    <br />
    <input data-bind="value: (cityToEdit() || {}).population" />
    <br />
    <button data-bind="click: $root.cancelEdit">Cancel</button>
  </div>
</div>

下行:

  • 在淡出过程中,您仍然可以编辑框
  • 您需要额外的财产