【问题标题】:Passing parameter using onclick or a click binding with KnockoutJS使用 onclick 传递参数或使用 KnockoutJS 进行点击绑定
【发布时间】:2012-04-19 19:47:03
【问题描述】:

我有这个功能:

function make(place)
{
  place.innerHTML = "somthing"
}

我以前用纯 JavaScript 和 html 来做这个:

<button onclick="make(this.parent)">click me</button>

如何使用惯用的 knockout.js 做到这一点?

【问题讨论】:

    标签: javascript html knockout.js onclick


    【解决方案1】:

    使用绑定,如下例所示:

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

    【讨论】:

    • 谢谢。但是,如果我想传递多个参数怎么办?我该怎么做?
    • @sudip 简单:点击:PesquisaGerente.bind($data,'1', '2', '3')
    • 可能值得注意 - 使用 Function.prototype.bind 是一种标准的 JavaScript 技术,因此在 Knockout 之外也值得学习 :)
    • 这应该是一个问题,bind 是为这种情况而设计的众所周知的标准 js 函数。该示例中的自定义绑定对我来说太过分了。
    【解决方案2】:

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

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

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

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

    HTML

    <div>
        <button data-bind="click: clickMe">Click Me!</button>
    </div>
    

    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());
    

    【讨论】:

      【解决方案3】:

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

      <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());
      

      这里是fiddle

      【讨论】:

      • 我最喜欢这个。简单易懂。最终根本不需要传递参数,但仍计划使用此方法(并用于测试)。
      • 这没关系,但是被调用函数的 this 将引用窗口而不是通常在 KO 绑定函数中预期的 ViewModel。 function.bind($data) 解决了这个问题。
      • 在绑定体内创建函数看起来很奇怪,我会使用绑定方法。
      【解决方案4】:

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

      对于所提出的问题不是一个直接的答案,但可能是大多数 Google 员工登陆这里的问题的答案:使用 the click binding from KnockoutJS 而不是 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());
      .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; }
      <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>

      **关于实际问题的注释...*

      实际的问题有一个有趣的地方:

      // Uh oh! Modifying the DOM....
      place.innerHTML = "somthing"
      

      不要那样做!当使用像 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());
      <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>

      【讨论】:

        【解决方案5】:

        Knockout 的文档还提到了一种更简洁的方法,可以将额外的参数传递给使用on-click 绑定的函数,使用 function.bind,如下所示:

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

        【讨论】:

          猜你喜欢
          • 2012-04-29
          • 2013-05-01
          • 1970-01-01
          • 2016-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-25
          相关资源
          最近更新 更多