0

我有以下标记:

<div id="metro-hub">
    <h1 id="hub-title" data-bind="text: hubTitle" class="hub-title">@Model.HubTitle</h1>
    <div id="hubWrapper" data-root-url="/Root" data-bind="html: currentHub"></div>
</div>

我正在使用 KnockoutJS 将viewModelJavaScript 对象绑定到视图。我还创建了一个自定义绑定来将导航连接到服务器上的站点地图。以下是我到目前为止所获得的一些片段:

var MetroPageViewModel = function () {
    var self = this;

    self.currentHub = ko.observable();
    self.viewPortData = ko.observable();
    self.hubTitle = ko.observable();

    self.renderHub = function (rootUrl) {
        console.log(rootUrl);
        $.ajax({
            url: '/Base/NewHub',
            type: 'get',
            data: {
                url: rootUrl
            },
            success: function (data) {
                if (data) {
                    var wrappedData = $(data);
                    var newHubContent = wrappedData.find('ul');
                    var title = wrappedData.find('input.metro-hub-title').val();
                    self.hubTitle(title);
                    self.currentHub(newHubContent); //THIS IS THE LINE THAT DOES NOT WORK
                }
            }
        });
    };

    self.initialize = function () {
        var url = $('#hubWrapper').data('root-url');
        self.renderHub(url);
    };
};

$(function () {
    var viewModel = new MetroPageViewModel();
    ko.applyBindings(viewModel);
    viewModel.initialize();
});

这是使用 Sammy.js 库根据 url 哈希进行路由的自定义绑定:

ko.bindingHandlers.metroHub = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var menuItems = $(element).find('li');
        Sammy(function () {
            var $this = this;
            menuItems.each(function (index, elem) {
                $this.get('#/' + $(elem).data('link-name'), function () {
                    var numChildren = $(elem).data('num-children');
                    if (numChildren > 0) {
                       var rootUrl = (elem).data('source-url');
                       viewModel.renderHub(rootUrl);
                    } else {
                        var dataSource = $(elem).data('source-url');
                        $.ajax({
                            url: dataSource,
                            type: 'get',
                            success: function (data) {
                                if (data) {
                                    viewModel.viewPortData(data);
                                }
                            }
                        });
                    }
                });
            });
            var firstItem = menuItems[0];
            var itemRoute = '#/' + $(firstItem).data('link-name');
            $this.get('', function () { this.app.runRoute('get', itemRoute) });
        }).run();
    }
};

从服务器返回的数据如下:

<div><ul class="metro-menu" data-bind="metroHub: true"><li data-link-name="Home" data-num-children="0" data-source-url="/Navigation/Item1"><a href="#/Home">Home</a></li><li data-link-name="Products" data-num-children="2" data-source-url="/Navigation/Item2"><a href="#/Products">Products</a></li><li data-link-name="Services" data-num-children="0" data-source-url="/Navigation/Item3"><a href="#/Services">Services</a></li></ul>
<input class="metro-hub-title" type="hidden" value="this is a hub title"></input>
<input class="hasParentNode" type="hidden" value="False"></input>
</div>

更新:

现在的问题是,一旦方法中的 AJAX 回调返回,自定义绑定update回调就不会被触发。renderHub()我是否需要调用某种方法来强制绑定或任何东西?

有什么想法吗?

4

1 回答 1

0

也许您应该将更新绑定放在父容器上,因为该控件正在更新。

我认为更新没有触发是因为应该响应更新的旧 div 完全被新的 html 取代。

您可以通过在绑定中使用与更新相同的代码创建一个 init 函数来快速检查我是否正确。

于 2012-08-14T13:21:47.633 回答