敲除条件绑定

时间:2013-08-15 14:49:29

标签: twitter-bootstrap knockout.js single-page-application

好的,我一直在构建一个SPA应用程序,并希望根据是在手机还是笔记本电脑上查看该网站来设置不同的布局。

如果使用Bootstrap,它提供了css类的条件隐藏/显示,虽然它很好地适用于它的功能,但当布局更改超过某个点时,它不能正常工作。使用这种替代布局,我最终需要在一个页面上放置两组div,然后使用一些条件Javascript代码来消除目标div的内部html。这可以防止图表被填充到永远不会被看到的页面部分。

    var setViewscape = function () {
    var l = $(".positionDetails").length;
    if (l == 0) {
        setTimeout(function() {
            setViewscape();
        }, 10);
    } else {
        if (window.innerWidth <= 899) {
            $(".landscape").html("");
            $(".phonescape").css("visibility", "visible");
        } else {
            $(".phonescape").html("");
            $(".landscape").css("visibility", "visible");
        }
    }
};

到目前为止一切顺利,除非我观察Knockout页面上发生的事情,第二组淘汰赛标签仍然受到约束。我尝试添加一个ko条件只绑定到我打算显示的那些控件:

<div id="content" class="main">
    <div class="row landscape">
        <!--ko if: $(window.innerWidth > 899) -->
        <div class="col-8 col-lg-8">
            <!--ko compose: {view: 'positions/list'} --><!--/ko-->
        </div>
        <div class="col-lg-4 col-4 " > 
            <!--ko compose: {view: 'shared/summaryGraph'} --><!--/ko-->
            <!--ko compose: {view: 'shared/memberSummary'} --><!--/ko-->
            <!--ko compose: {view: 'shared/memberCalendar'} --><!--/ko-->
            <!--ko compose: {view: 'shared/memberTwitter'} --><!--/ko-->
            <div data-bind="visible: advert() != null && advert().length > 0" id="advert"  class="img-rounded container-fluid" style="min-width: 120px; min-height: 680px; height: inherit; margin-bottom: 30px; background-color:whitesmoke ">
                <h4>Advert</h4>
            </div>
        </div>
    <!--/ko-->
    </div>
    <div  class="row phonescape" style="padding-left: 15px; padding-top: 15px;">
    <!--ko if: $(window.innerWidth <= 899) -->
        <div class="col-sm-12">
            <!--ko compose: {view: 'shared/memberSummary'} --><!--/ko-->
            <!--ko compose: {view: 'shared/sagaSummaryGraph'} --><!--/ko-->
            <!--ko compose: {view: 'positions/list'} --><!--/ko--> 
        </div>
    <!--/ko-->
    </div>
</div>

但是当我观察调试信息时,我看到了 [“Binding”,“views / positions / list”,ko.bindingContext] [“Binding”,“views / positions / list”,ko.bindingContext]

[“Binding”,“views / shared / memberSummary”,ko.bindingContext] [“Binding”,“views / shared / memberSummary”,ko.bindingContext]

[“Binding”,“views / shared / summaryGraph”,ko.bindingContext] [“Binding”,“views / shared / summaryGraph”,ko.bindingContext]

我确信这必须受到性能的影响。

我要做的是只绑定到'phonescape'或'landscape'模式,并删除肯定会受到性能影响的内容。知道怎么做吗?

1 个答案:

答案 0 :(得分:0)

最近,我使用了一个可观察的扩展来做类似这样的事情,其中​​扩展根据媒体查询是否被命中更新了一个observable。你可以定义一个observable:

this.large = ko.observable().matchMedia("(min-width: 800px)");

然后,您可以将页面区域与“大”(例如if: large)绑定,以防止区域被绑定到您不想要的区域。

代码有点天真,因为它只支持旧版浏览器中基于px的测量的最小/最大宽度查询。

以下是我使用的内容:

//small extension to update an observable based on a media query
(function() {
    var self = ko.observable.fn.matchMedia = function(query) {
        self["matchMedia" in window ? "syncWithMatchMedia" : "syncWithResize"](this, query);
        return this;
    };

    self.syncWithMatchMedia = function(observable, mediaQuery) {
        var query = window.matchMedia(mediaQuery);

        observable(query.matches);

        query.addListener(function(query) {
            observable(query.matches);
        });
    };

    self.syncWithResize = function(observable, mediaQuery) {
        var pieces = mediaQuery.split(":"),
            isMax = pieces[0].indexOf("max") > -1,
            value = pieces[1].replace(")", "").replace("px",""), //just works with px for now
            currentWidth;

        var matcher = function() {
            var width = document.outerWidth || document.body.clientWidth;

            //see if something changed
            if (width !== currentWidth) {
                currentWidth = width;
                observable(isMax ? value > width : value < width);
            }
        }

        matcher();

        ko.utils.registerEventHandler(window, "resize", matcher);
    };
})();

如果浏览器不支持resize API,则会回退使用matchMedia事件。

以下是一个示例:http://jsfiddle.net/rniemeyer/7s2hZ/