【问题标题】:Knockout conditional binding淘汰赛条件绑定
【发布时间】:2013-08-17 19:05:15
【问题描述】:

好的,我一直在构建一个 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 观察页面上发生的情况时,第二组 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>

但是当我观察我看到的调试信息时 [“绑定”,“视图/位置/列表”,ko.bindingContext] [“绑定”,“视图/位置/列表”,ko.bindingContext]

["绑定", "views/shared/memberSummary", ko.bindingContext] ["绑定", "views/shared/memberSummary", ko.bindingContext]

["绑定", "views/shared/summaryGraph", ko.bindingContext] ["绑定", "views/shared/summaryGraph", ko.bindingContext]

我确信这一定是性能上的打击。

我想要做的是只绑定到“phonescape”或“landscape”模式,并删除肯定会影响性能的东西。知道怎么做吗?

【问题讨论】:

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


    【解决方案1】:

    最近,我使用 observable 扩展来执行类似的操作,其中扩展根据媒体查询是否被命中来更新 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);
        };
    })();
    

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

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

    【讨论】:

      猜你喜欢
      • 2013-02-04
      • 1970-01-01
      • 1970-01-01
      • 2018-08-04
      • 2013-10-31
      • 2013-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多