Knockout Custom Binding有时不会初始化

时间:2016-09-19 17:05:15

标签: knockout.js requirejs bootstrap-modal

我创建了一个敲除自定义绑定,有助于启用bootstrap的模态功能。但是,有时在标记使用绑定时不会调用init方法。

// data-bind="bootstrapModal: {viewModel: {isOpen: ko.observable(false)}, backdrop: 'static'}"
ko.bindingHandlers.bootstrapModal = {
    init: function (elem, value) {
        debugger; // added for debugging

        var options = ko.utils.unwrapObservable(value()),
            viewModel = options.viewModel,
            backdrop = options.backdrop;

        /* added for debugging */
        console.log('Attaching boostrapModal binding to view model.');
        console.log(viewModel);

        debugger;
        /* end added for debugging */

        // do not allow backdrop = true for now; it doesn't sync with the view model
        if (backdrop === undefined || backdrop === true) {
            backdrop = 'static';
        }

        if (viewModel.isOpen()) {
            $(elem).modal({ show: true, backdrop: backdrop });
        }

        viewModel.isOpen.subscribe(function (newVal) {
            console.log('View model open toggle.');
            if (newVal) {
                $(elem).modal({ show: newVal, backdrop: backdrop });
            } else {
                $(elem).modal('hide');
            }
        });
    }
};

这与以下标记一起使用:

<div class="modal fade" tabindex="-1" role="dialog" data-bind="bootstrapModal: { viewModel: $data, backdrop: 'static' }, with: $data">
    <div class="modal-dialog" role="document">
    ... rest of modal markup

$ data是一个带有isOpen observable boolean属性的视图模型(以及其他内容)。

在同一页面中,我们使用require来引入如下脚本:

<script>
    requirejs(['knockout', 'NavViewModel'],
        function (ko, nav) {

            // investigating the binding handlers, bootstrapModal is available
            console.log(ko.bindingHandlers);
            debugger;

            ko.applyBindings(nav.NavViewModel.getInstance(), document.getElementById('navContainer'));
        });
</script>

我们正在使用ASP.NET MVC的bundler创建一个包含knockout和所有自定义绑定的bundle,以便它们一起下载。

BundleTable.Bundles.Add(new ScriptBundle("~/scripts/knockout.js")
            .Include("~/scripts/jquery-1.12.3.min.js")
            .Include("~/scripts/bootstrap.min.js")
            .Include("~/scripts/knockout-3.4.0.js")
            .Include("~/scripts/knockout.customBindings.js"));

这并不是它真正的设置方式,但实际上是相同的。需要'淘汰'将下载包含jquery,bootstrap,knockout和自定义绑定的bundle knockout.js。

因此,在绑定发生之前,绑定处理程序在ko.bindingHandlers中可用。但是,并不总是命中自定义绑定(init函数的第一行)中的断点。在FF中,我很少观察到错误。在Chrome中,它几乎每次都有。一遍又一遍地刷新页面最终会注意到两个浏览器中的工作状态和损坏状态。

1 个答案:

答案 0 :(得分:0)

即使脚本低于它影响的标记,它也只会实际应用绑定。将applyBindings调用移动到DOM就绪回调中可以解决问题。

<script>
    requirejs(['jquery', 'knockout', 'NavViewModel'],
        function ($, ko, nav) {

            $(function() {
                ko.applyBindings(nav.NavViewModel.getInstance(), document.getElementById('navContainer'));
            });
        });
</script>