随笔 - 233  文章 - 0  评论 - 246  阅读 - 84万

Knockout与Require框架同时使用时的visible绑定的问题,造成的影响,以及解决的方法。

Knockout 可以将 visible 绑定到DOM 元素上,使得该元素的hidden 或visible 状态取决于绑定的值。

查看以下knockout的描述,http://knockoutjs.com/documentation/visible-binding.html

When the parameter resolves to a false-like value (e.g., the boolean value false, or the numeric value 0, or null, or undefined),  <br>the binding sets yourElement.style.display to none, causing it to be hidden. This takes priority over any display style you’ve defined using CSS。
当这个参数是一个假值时(举例来说,布尔值的false , 数值0,或者null,或者undefined),绑定时候设置你的元素的style.display是none,从而使之隐藏起来。这个优先级要高于CSS中定义的.
 
When the parameter resolves to a true-like value (e.g., the boolean value true, or a non-null object or array),  the binding removes the yourElement.style.display value, <br>causing it to become visible。
当这个参数是一个真值时(举例来说,布尔值是true,或者非空对象与数组),绑定时候移除你display的值,从来显示出来

当单独使用knockout框架时,这个visible绑定运行起来相当好,但是,当Knockout和Require两个框架同时使用时,就出问题了。

先看一个例子,这个例子里有有两个div,第一次加载页面时显示div1,隐藏div2,当按下一步按钮时,隐藏div1,显示div2,最后点返回按钮时,显示div1,隐藏div2。

ko_visible.htm代码,

<html>
<head>
   <script src="../lib/require/require.js" data-main="ko_visible"></script>
</head>
<body  >
  <div id="div1" data-bind="visible: showVisibleDiv1">
  <p>First name: <span ></span></p>
  <p>Last name: <span ></span></p>
  <p>Full name: <span ></span></p>
  <input type="text" id="inputAddress"  /> *
  <input type="text" id="inputMoney"  /> *
  <input type="button" id="btnSave" value="下一步" data-bind="click: SaveClick" />
  </div>
 
  <div id="div2" data-bind="visible: showVisibleDiv2">
      <table>
          <tr>
              <td>标题</td><td>内容</td>
          </tr>
          <tr>
              <td></td><td></td>
          </tr>
      </table>
      <input type="button" id="btnNext" value="返回" data-bind="click: NextClick" />
  </div>
 
</body>
</html>

  

ko_visible.js

require.config({
    paths: {
        "knockout": "../lib/knockout/knockout-2.3.0",
        "jquery": "../lib/jquery/jquery-1.9.1.min"
    }
 
});
 
require(['jquery', 'knockout'], function ($, ko) {
 
    //数据绑定
    $(document).ready(function () {
        var viewModel = {
            showVisibleDiv1: ko.observable(true),
            showVisibleDiv2: ko.observable(false),
            SaveClick: function () {
                viewModel.showVisibleDiv1(false);
                viewModel.showVisibleDiv2(true);
            },
            NextClick: function () {
              viewModel.showVisibleDiv1(true);
              viewModel.showVisibleDiv2(false);               
            }
        };
        ko.applyBindings(viewModel); 
    });
});

当运行此页面时,效果如下图,div1,div2同时显示,然后, div2因为visible=false的缘故,又迅速消失。

当页面中存在多个步骤的div,想一步步执行并控制某些div显示时, 这个效果是让人不能接受的.

当页面初始加载时,因为Require的延迟加载特性(也就是不先加载js,而是先加载元素,异步加载js),当knockout代码还没有执行时,元素是没有被隐藏的,这一点是致命的。

所以,修改的方法有两个:

1.不使用Require框架。

例子如下: 

ko_visible1.htm

<html>
<head>
  <script type="text/javascript" src="../lib/knockout/knockout-2.3.0.js"></script>
  <script type="text/javascript" src="../lib/jquery/jquery-1.9.1.min.js"></script>
  <script type="text/javascript" src="ko_visible1.js"></script>
</head>
<body  >
  <div id="div1" data-bind="visible: showVisibleDiv1">
  <p>First name: <span ></span></p>
  <p>Last name: <span ></span></p>
  <p>Full name: <span ></span></p>
  <input type="text" id="inputAddress"  /> *
  <input type="text" id="inputMoney"  /> *
  <input type="button" id="btnSave" value="下一步" data-bind="click: SaveClick" />
  </div>
 
  <div id="div2" data-bind="visible: showVisibleDiv2">
      <table>
          <tr>
              <td>标题</td><td>内容</td>
          </tr>
          <tr>
              <td></td><td></td>
          </tr>
      </table>
      <input type="button" id="btnNext" value="返回" data-bind="click: NextClick" />
  </div>
 
</body>
</html>

ko_visible1.js

//数据绑定
$(document).ready(function () {
 
    var viewModel = {
        showVisibleDiv1: ko.observable(true),
        showVisibleDiv2: ko.observable(false),
        SaveClick: function () {
            viewModel.showVisibleDiv1(false);
            viewModel.showVisibleDiv2(true);
        },
        NextClick: function () {
          viewModel.showVisibleDiv1(true);
          viewModel.showVisibleDiv2(false);               
        }
    };
    ko.applyBindings(viewModel); 
});

  

2.如果必须使用Require框架,那在这种场合,建议不要使用visible,还是使用css的样式控制。

例子如下:

ko_display.htm

<html>
<head>
   <script src="../lib/require/require.js" data-main="ko_display"></script>
</head>
<body  >
  <div id="div1" data-bind="visible: showVisibleDiv1">
  <p>First name: <span ></span></p>
  <p>Last name: <span ></span></p>
  <p>Full name: <span ></span></p>
  <input type="text" id="inputAddress"  /> *
  <input type="text" id="inputMoney"  /> *
  <input type="button" id="btnSave" value="下一步" data-bind="click: SaveClick" />
  </div>
 
  <div id="div2" style="display:none">
      <table>
          <tr>
              <td>标题</td><td>内容</td>
          </tr>
          <tr>
              <td></td><td></td>
          </tr>
      </table>
      <input type="button" id="btnNext" value="返回" data-bind="click: NextClick" />
  </div>
 
</body>
</html>

ko_display.js

require.config({
    paths: {
        "knockout": "../lib/knockout/knockout-2.3.0",
        "jquery": "../lib/jquery/jquery-1.9.1.min"
    }
 
});
 
require(['jquery', 'knockout'], function ($, ko) {
 
    //数据绑定
    $(document).ready(function () {
 
        var viewModel = {
            showVisibleDiv1: ko.observable(true),
 
            SaveClick: function () {
                viewModel.showVisibleDiv1(false);
                $("#div2").show();
            },
            NextClick: function () {
                viewModel.showVisibleDiv1(true);
                $("#div2").hide();                          
            }
        };
        ko.applyBindings(viewModel); 
    });
});

以上是本人在项目中遇到的问题总结,如有谬误之处,还请大家指正!

 

posted on   BobLiu  阅读(2061)  评论(3编辑  收藏  举报

点击右上角即可分享
微信分享提示