使用onclick传递参数或使用KnockoutJS点击绑定

Bla*_*dow 51 html javascript onclick knockout.js

我有这个功能:

function make(place)
{
  place.innerHTML = "somthing"
}
Run Code Online (Sandbox Code Playgroud)

我曾经用纯JavaScript和HTML做到这一点:

<button onclick="make(this.parent)">click me</button>
Run Code Online (Sandbox Code Playgroud)

我怎么能用idiomatic knockout.js做到这一点?

Jul*_*les 81

使用绑定,如下例所示:

<a href="#new-search" data-bind="click:SearchManager.bind($data,'1')">
  Search Manager
</a>
Run Code Online (Sandbox Code Playgroud)
var ViewModelStructure = function () {
    var self = this;
    this.SearchManager = function (search) {
        console.log(search);
    };
}();
Run Code Online (Sandbox Code Playgroud)

  • 可能值得注意 - 使用[Function.prototype.bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)是一种标准的JavaScript技术,因此值得了解外面的Knockout也是:) (3认同)

Joh*_*les 31

如果在Knockout中设置了单击绑定,则事件将作为第二个参数传递.您可以使用该事件获取发生单击的元素并执行您想要的任何操作.

这是一个小提琴演示:http://jsfiddle.net/jearles/xSKyR/

或者,您可以创建自己的自定义绑定,它将接收作为第一个参数绑定的元素.在初始化时,您可以附加自己的单击事件处理程序来执行您希望的任何操作.

http://knockoutjs.com/documentation/custom-bindings.html

HTML

<div>
    <button data-bind="click: clickMe">Click Me!</button>
</div>
Run Code Online (Sandbox Code Playgroud)

JS

var ViewModel = function() {
    var self = this;
    self.clickMe = function(data,event) {

      var target = event.target || event.srcElement;

      if (target.nodeType == 3) // defeat Safari bug
        target = target.parentNode;

      target.parentNode.innerHTML = "something";
    }
}

ko.applyBindings(new ViewModel());
Run Code Online (Sandbox Code Playgroud)


Sal*_*ali 26

我知道这是一个老问题,但这是我的贡献.你可以简单地将一个函数包装在另一个函数中,而不是所有这些技巧.就像我在这里所做的:

<div data-bind="click: function(){ f('hello parameter'); }">Click me once</div>
<div data-bind="click: function(){ f('no no parameter'); }">Click me twice</div>

var VM = function(){
   this.f = function(param){
     console.log(param);
   }
}
ko.applyBindings(new VM());
Run Code Online (Sandbox Code Playgroud)

这是小提琴

  • 在绑定体内创建函数看起来很奇怪,我会选择bind方法。 (2认同)

Jer*_*oen 12

关于如何click使用KnockoutJS 处理事件的一般答案......

不是问题的直接答案,但可能是大多数Google员工登陆的问题的答案:使用KnockoutJS click绑定而不是onclick.像这样:

function Item(parent, txt) {
  var self = this;
  
  self.doStuff = function(data, event) {
    console.log(data, event);
    parent.log(parent.log() + "\n  data = " + ko.toJSON(data));
  };
  
  self.doOtherStuff = function(customParam, data, event) {
    console.log(data, event);
    parent.log(parent.log() + "\n  data = " + ko.toJSON(data) + ", customParam = " + customParam);
  };
  
  self.txt = ko.observable(txt);
}

function RootVm(items) {
  var self = this;
  
  self.doParentStuff = function(data, event) {
    console.log(data, event);
    self.log(self.log() + "\n  data = " + ko.toJSON(data));
  };
  
  self.items = ko.observableArray([
    new Item(self, "John Doe"),
    new Item(self, "Marcus Aurelius")
  ]);
  self.log = ko.observable("Started logging...");
}

ko.applyBindings(new RootVm());
Run Code Online (Sandbox Code Playgroud)
.parent { background: rgba(150, 150, 200, 0.5); padding: 2px; margin: 5px; }
button { margin: 2px 0; font-family: consolas; font-size: 11px; }
pre { background: #eee; border: 1px solid #ccc; padding: 5px; }
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<div data-bind="foreach: items">
  <div class="parent">
    <span data-bind="text: txt"></span><br>
    <button data-bind="click: doStuff">click: doStuff</button><br>
    <button data-bind="click: $parent.doParentStuff">click: $parent.doParentStuff</button><br>
    <button data-bind="click: $root.doParentStuff">click: $root.doParentStuff</button><br>
    <button data-bind="click: function(data, event) { $parent.log($parent.log() + '\n  data = ' + ko.toJSON(data)); }">click: function(data, event) { $parent.log($parent.log() + '\n  data = ' + ko.toJSON(data)); }</button><br>
    <button data-bind="click: doOtherStuff.bind($data, 'test 123')">click: doOtherStuff.bind($data, 'test 123')</button><br>
    <button data-bind="click: function(data, event) { doOtherStuff('test 123', $data, event); }">click: function(data, event) { doOtherStuff($data, 'test 123', event); }</button><br>
  </div>
</div>

Click log:
<pre data-bind="text: log"></pre>
Run Code Online (Sandbox Code Playgroud)


**关于实际问题的说明......*

实际问题有一点有趣:

// Uh oh! Modifying the DOM....
place.innerHTML = "somthing"
Run Code Online (Sandbox Code Playgroud)

不要那样做!使用像KnockoutJS这样的MVVM框架时,不要像修改那样使用DOM,特别是不要使用自己父级的DOM.如果你这样做,按钮就会消失(如果你替换你的父母,innerHTML你自己将永远消失!).

相反,请改为在处理程序中修改View Model,并让View 响应.例如:

function RootVm() {
  var self = this;
  self.buttonWasClickedOnce = ko.observable(false);
  self.toggle = function(data, event) {
    self.buttonWasClickedOnce(!self.buttonWasClickedOnce());
  };
}

ko.applyBindings(new RootVm());
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<div>
  <div  data-bind="visible: !buttonWasClickedOnce()">
    <button data-bind="click: toggle">Toggle!</button>
  </div>
  <div data-bind="visible: buttonWasClickedOnce">
    Can be made visible with toggle...
    <button data-bind="click: toggle">Untoggle!</button>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)


gaz*_*ubi 5

Knockout的文档还提到了一种更加干净的方法,该方法将额外的参数传递给on-click使用function.bind 进行绑定的函数绑定,如下所示:

<button data-bind="click: myFunction.bind($data, 'param1', 'param2')">
    Click me
</button>
Run Code Online (Sandbox Code Playgroud)