1

在 Knockout 文档中,据说如果我们不使用 ko.observable(...),单向数据绑定是可能的:http: //knockoutjs.com/documentation/value-binding.html

但是,以下代码无法按我的预期工作:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>

<body>
    <form data-bind="with: selectedMerchant">
        <input data-bind="value: name"></input>
        <button data-bind="click: change"> CHANGE </button>
        <button data-bind="click: show"> SHOW </button>
    </form>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js" type="text/javascript"></script>
    <script>
        function PartnersViewModel() {
            self.selectedMerchant = {'name': 'John'};
            self.show = function() {
                alert(JSON.stringify(self.selectedMerchant));
            }
            self.change = function() {
                self.selectedMerchant = {'name': 'David'};
            }
        }
        ko.applyBindings(new PartnersViewModel());
    </script>
</body>
</html>

'selectedMerchant' 是在没有 ko.observable(...) 的情况下声明的,所以它应该是单向绑定的。我希望一旦单击“更改”按钮,输入框中的文本将更改为“大卫”。我还尝试了不同的方向 - 我更改了输入中的文本并单击了“显示”按钮。消息框给出了它在开始时的初始值。

4

3 回答 3

2

为了扩展 M. Ihsan 的正确答案,Knockout 将在不使用可观察对象并使用普通 JavaScript 变量/对象时绑定一种方式。这是一个例子。

function ExampleObject(one, two) {
  var self = this;

  self.one = one;
  self.two = ko.observable(two);

  self.ChangeVariables = function() {
    self.one = "1";
    self.two("2");
    console.log(self.one, ko.toJS(self.two));
  }
}


function ViewModel() {
  var self = this;

  self.bindingExample = ko.observableArray();

  self.Load = function() {
    self.bindingExample.push(new ExampleObject("one way", "two ways"));
    self.bindingExample.push(new ExampleObject("one way", "two ways"));
    self.bindingExample.push(new ExampleObject("one way", "two ways"));
    self.bindingExample.push(new ExampleObject("one way", "two ways"));
  }

  self.Load();

}

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<table border=1>
  <thead>
    <tr>
      <th>1 way</th>
      <th>2 way</th>
      <th></th>
    </tr>
  </thead>
  <tbody data-bind="foreach: bindingExample">
    <tr>
      <td data-bind="text: one"></td>
      <td data-bind="text: two"></td>
      <td> <a data-bind="click: ChangeVariables"> Change Variables</a></td>
    </tr>
  </tbody>
</table>

于 2017-07-03T13:10:46.463 回答
2

如果您想要一个真正的单向绑定,它将继续更新 UI,您可以使用计算的 observable。除非您为计算指定“写入”属性,否则它只会在模型-> UI 方向上更新。话虽如此,您只需将输入框替换为跨度或标签以防止用户更新值即可获得相同的结果,因此我不确定我是否看到单向绑定的实用性。

function PartnersViewModel() {
    var self = this;
    self.selectedMerchant = ko.observable({'name': 'John'});
    self.show = function() {
        alert(JSON.stringify(self.selectedMerchant()));
    }
    self.change = function() {
        self.selectedMerchant({'name': 'David'});
    }
    self.selectedName = ko.computed(function(){
      return self.selectedMerchant().name;
    });
}
ko.applyBindings(new PartnersViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js" type="text/javascript"></script>
    
<div data-bind="with: selectedMerchant">
  <input data-bind="value: $parent.selectedName"></input>
  <button data-bind="click: $parent.change"> CHANGE </button>
  <button data-bind="click: $parent.show"> SHOW </button>
</div>

如果你想要一些更可重用的东西,你可以制作一个只实现一个方向的自定义绑定:

ko.bindingHandlers.oneWayValue = {
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var value = ko.unwrap(valueAccessor());
        element.value = value;
    }
}
于 2017-07-03T16:37:11.947 回答
0

with大多数绑定一样,绑定已经是单向绑定。它们从模型到视图是单向的,但这需要模型值是可观察的。

value通常是双向绑定。文档中描述的单向性质是从视图到模型,无论如何这不是您想要的方向。

换句话说,你需要selectedMerchant是可观察的。

于 2017-07-03T17:24:40.240 回答