KnockoutJs - 为啥初始化绑定处理程序只被调用一次?

Posted

技术标签:

【中文标题】KnockoutJs - 为啥初始化绑定处理程序只被调用一次?【英文标题】:KnockoutJs - why is init binding handler is only getting called once?KnockoutJs - 为什么初始化绑定处理程序只被调用一次? 【发布时间】:2011-12-15 19:47:39 【问题描述】:

我有一个问题,即第二次从服务器更新数据时没有调用 init: 函数。

有什么原因会发生这种情况吗?

我正在使用映射插件。另一个我不明白的问题是我是否需要根据这是第一次调用还是第二次调用来不同地调用映射插件函数?

JS

 function ViewMemberPopup(memberId) 

        $.get("/People/GetMemberDetails?memberId=" + memberId, function (data)             
            viewMemberModel.model = ko.mapping.fromJS(data);            
            ko.applyBindings(viewMemberModel.model, $("#memberDetailsContainer")[0]);
        );
    


 // binding handler
 ko.bindingHandlers.renderMemberModal = 
        init: function (element, valueAccessor, allBindingsAccessor) 
            $(element).modal("show");            
        
    ;

HTML: 我已经使用 renderMemberModal:true 作为绑定处理程序,不知道为什么我需要附加一个属性。我只需要调用渲染函数...

     <div class="modal fade" id="viewMemberModal" data-bind="renderMemberModal: true" style="display: none;">
        <div class="modal-header">
            <a class="close" href="#">×</a>
            <h3>
                Member Details</h3>
        </div>
        <div class="modal-body">
             <div data-bind="template:  name: 'memberDetailsTemplate' ">
            </div>
        </div>
        <div class="modal-footer">
            <a class="btnx closeModal">Close</a>
        </div>
    </div>

我正在使用引导 css 来显示模式弹出窗口。

【问题讨论】:

【参考方案1】:

您通常不想在每次更新时对同一个元素继续调用 applyBindings。这最终可能会添加多个事件处理程序,具体取决于您使用的绑定。如果您要这样做,那么您至少要在元素上调用ko.cleanNode。比如:http://jsfiddle.net/rniemeyer/F4AzB/

比起在每次更新时调用 applyBindings,我认为让template 绑定(或作为模板绑定包装器的控制流绑定)处理更新内容更容易。

您的 viewModel 可以有一个 observable 来表示您的数据。然后,您可以使用数据的新副本更新该 observable。

在这种情况下,您真正​​想要做的是让您的自定义绑定只有一个更新函数,并确保访问主可观察对象,以便每次调用更新函数时都会触发它。

ko.bindingHandlers.custom = 
    update: function(element, valueAccessor) 
        ko.utils.unwrapObservable(valueAccessor());  //just for subscription
        console.log("hit");
      
;

看起来像这样:http://jsfiddle.net/rniemeyer/dNsW8/

【讨论】:

只是试图通过并理解示例。 ko.mapping.fromJS(dataFromServer, null, viewModel.myData()) - 为什么是 3 个参数,我以为只需要 2 个?有这方面的文档吗? ko.mapping.fromJS 可以带三个参数。第一个是数据,第二个是映射选项,第三个是要更新的对象。如果您正在处理要更新的已映射对象,则可以将其作为第二个参数传递,因为它不再需要映射选项,并且会识别您传递了已映射对象而不是映射选项。 你能在 jsFiddle 中重现你的问题吗?你用的是什么版本的KO?试用 1.3 beta(或来自 github 的当前版本),$data 随处可用,而不仅仅是在 jQuery 模板中。 我已经尽力做到最好,但恐怕这不是我的一天,从引导程序交换后,甚至 jquery ui 都无法正常工作。 jsfiddle.net/dNsW8/3 谢谢,这对我帮助很大。我现在有了一个可行的解决方案!【参考方案2】:

在 Knockoutjs 网站 http://knockoutjs.com/documentation/custom-bindings.html 上讨论自定义绑定。

Knockout 将为您使用绑定的每个 DOM 元素调用一次 init 函数。 init有两个主要用途: - 为 DOM 元素设置任何初始状态 - 注册任何事件处理程序,例如,当用户单击或修改 DOM 元素时,您可以更改关联的 observable 的状态

所以按照设计,Init 只被调用一次来设置绑定。目的是配置 DOM 对象,以便 Update 方法正常工作。

【讨论】:

以上是关于KnockoutJs - 为啥初始化绑定处理程序只被调用一次?的主要内容,如果未能解决你的问题,请参考以下文章

Knockoutjs单页应用程序绑定问题

为啥事件处理程序只能在 IHttpModule 初始化期间绑定到 HttpApplication 事件?

knockoutjs:值绑定独占还是点击事件?

knockoutjs:防止没有处理程序的元素的事件冒泡

“未捕获的 TypeError:无法处理绑定”与 KnockoutJS

KnockoutJS:我应该如何处理繁重的小部件初始化代码?