当前位置:  首页>> 技术小册>> KnockoutJS入门指南

Control types
这个例子,对view model没有什么特殊的展示,只是展示如何绑定到各种元素上(例如,select, radio button等)。

代码: View

  1. <div class="readout">
  2. <h3>
  3. What's in the model?</h3>
  4. <table>
  5. <tr>
  6. <td class="label">
  7. Text value:
  8. </td>
  9. <td data-bind="text: stringValue">
  10. </td>
  11. </tr>
  12. <tr>
  13. <td class="label">
  14. Password:
  15. </td>
  16. <td data-bind="text: passwordValue">
  17. </td>
  18. </tr>
  19. <tr>
  20. <td class="label">
  21. Bool value:
  22. </td>
  23. <td data-bind='text: booleanValue() ? "True" : "False"'>
  24. </td>
  25. </tr>
  26. <tr>
  27. <td class="label">
  28. Selected option:
  29. </td>
  30. <td data-bind="text: selectedOptionValue">
  31. </td>
  32. </tr>
  33. <tr>
  34. <td class="label">
  35. Multi-selected options:
  36. </td>
  37. <td data-bind="text: multipleSelectedOptionValues">
  38. </td>
  39. </tr>
  40. <tr>
  41. <td class="label">
  42. Radio button selection:
  43. </td>
  44. <td data-bind="text: radioSelectedOptionValue">
  45. </td>
  46. </tr>
  47. </table>
  48. </div>
  49. <h3>
  50. HTML controls</h3>
  51. <table>
  52. <tr>
  53. <td class="label">
  54. Text value (updates on change):
  55. </td>
  56. <td>
  57. <input data-bind="value: stringValue"/>
  58. </td>
  59. </tr>
  60. <tr>
  61. <td class="label">
  62. Text value (updates on keystroke):
  63. </td>
  64. <td>
  65. <input data-bind='value: stringValue, valueUpdate: "afterkeydown"' />
  66. </td>
  67. </tr>
  68. <tr>
  69. <td class="label">
  70. Text value (multi-line):
  71. </td>
  72. <td>
  73. <textarea data-bind="value: stringValue"> </textarea>
  74. </td>
  75. </tr>
  76. <tr>
  77. <td class="label">
  78. Password:
  79. </td>
  80. <td>
  81. <input type="password" data-bind="value: passwordValue"/>
  82. </td>
  83. </tr>
  84. <tr>
  85. <td class="label">
  86. Checkbox:
  87. </td>
  88. <td>
  89. <input type="checkbox" data-bind="checked: booleanValue"/>
  90. </td>
  91. </tr>
  92. <tr>
  93. <td class="label">
  94. Drop-down list:
  95. </td>
  96. <td>
  97. <select data-bind="options: optionValues, value: selectedOptionValue">
  98. </select>
  99. </td>
  100. </tr>
  101. <tr>
  102. <td class="label">
  103. Multi-select drop-down list:
  104. </td>
  105. <td>
  106. <select multiple="multiple" data-bind="options: optionValues, selectedOptions: multipleSelectedOptionValues">
  107. </select>
  108. </td>
  109. </tr>
  110. <tr>
  111. <td class="label">
  112. Radio buttons:
  113. </td>
  114. <td>
  115. <label>
  116. <input type="radio" value="Alpha" data-bind="checked: radioSelectedOptionValue"/>Alpha</label>
  117. <label>
  118. <input type="radio" value="Beta" data-bind="checked: radioSelectedOptionValue"/>Beta</label>
  119. <label>
  120. <input type="radio" value="Gamma" data-bind="checked: radioSelectedOptionValue"/>Gamma</label>
  121. </td>
  122. </tr>
  123. </table>

代码: View model

  1. var viewModel = {
  2. stringValue: ko.observable("Hello"),
  3. passwordValue: ko.observable("mypass"),
  4. booleanValue: ko.observable(true),
  5. optionValues: ["Alpha", "Beta", "Gamma"],
  6. selectedOptionValue: ko.observable("Gamma"),
  7. multipleSelectedOptionValues: ko.observable(["Alpha"]),
  8. radioSelectedOptionValue: ko.observable("Beta")
  9. };
  10. ko.applyBindings(viewModel);

6 Templating
这个例子展示的render模板,以及在模板内部如何使用data binding属性的。

Template很容易嵌套,当任何依赖数据改变的时候,Knockout会自动重新render模板。参考演示(启用‘Show render times’),Knockout知道只需要重新render改变的那些数据所绑定的最近的模板。

代码: View

  1. <div data-bind='template: "peopleTemplate"'>
  2. </div>
  3. <label>
  4. <input type="checkbox" data-bind="checked: showRenderTimes"/>
  5. Show render times</label>
  6. <script type="text/html" id="peopleTemplate">
  7. <h2>People</h2>
  8. <ul>
  9. {{each people}}
  10. <li>
  11. <div>
  12. ${ name } has <span data-bind="text: children().length">&nbsp;</span> children:
  13. <a href="#" data-bind="click: addChild ">Add child</a>
  14. <span class="renderTime" data-bind="visible: showRenderTimes">
  15. (person rendered at <span data-bind="text: new Date().getSeconds()"></span>)
  16. </span>
  17. </div>
  18. <div data-bind='template: { name: "childrenTemplate", data: children }'></div>
  19. </li>
  20. {{/each}}
  21. </ul>
  22. </script>
  23. <script type="text/html" id="childrenTemplate">
  24. <ul>
  25. {{each $data}}
  26. <li>
  27. ${ this }
  28. <span class="renderTime" data-bind="visible: viewModel.showRenderTimes">
  29. (child rendered at <span data-bind="text: new Date().getSeconds()"></span>)
  30. </span>
  31. </li>
  32. {{/each}}
  33. </ul>
  34. </script>

代码: View model

  1. // Define a "person" class that tracks its own name and children, and has a method to add a new child
  2. var person = function (name, children) {
  3. this.name = name;
  4. this.children = ko.observableArray(children);
  5. this.addChild = function () {
  6. this.children.push("New child");
  7. } .bind(this);
  8. }
  9. // The view model is an abstract description of the state of the UI, but without any knowledge of the UI technology (HTML)
  10. var viewModel = {
  11. people: [
  12. new person("Annabelle", ["Arnie", "Anders", "Apple"]),
  13. new person("Bertie", ["Boutros-Boutros", "Brianna", "Barbie", "Bee-bop"]),
  14. new person("Charles", ["Cayenne", "Cleopatra"])
  15. ],
  16. showRenderTimes: ko.observable(false)
  17. };
  18. ko.applyBindings(viewModel);

7 Paged grid
data-bind=”…”绑定(像text, visible, 和click不是固定死的) - 你可以很容易自定义自己的绑定。如果你的自定义绑定仅仅是添加事件或者更新DOM元素的属性,那几行就可以实现。不过,你依然可以自定义可以重用的绑定(或插件),就行本例的simpleGrid绑定。

如果一个插件需要自己标准的view model(例如本例的ko.simpleGrid.viewModel ),它提供既提供了该如何配置插件实例(分页大小,列声明)工作,也提供了view model上的属性是否是observable 的(例如currentpage索引)。也可以扩展代码让这些属性很容易地改变,并且让UI自动更新。例如,“Jump to first page”按钮的工作原理。

查看HTML源代码可以看到非常容易使用这个simple grid插件。simpleGrid源码地址是:http://knockoutjs.com/examples/resources/knockout.simpleGrid.js

代码: View

  1. <div data-bind="simpleGrid: gridViewModel"> </div>
  2. <button data-bind='click: function() { items.push({ name: "New item", sales: 0, price: 100 }) }'>
  3. Add item
  4. </button>
  5. <button data-bind="click: sortByName">
  6. Sort by name
  7. </button>
  8. <button data-bind="click: function() { gridViewModel.currentPageIndex(0) }">
  9. Jump to first page
  10. </button>

代码: View model

  1. var myModel = {
  2. items: ko.observableArray([
  3. { name: "Well-Travelled Kitten", sales: 352, price: 75.95 },
  4. { name: "Speedy Coyote", sales: 89, price: 190.00 },
  5. { name: "Furious Lizard", sales: 152, price: 25.00 },
  6. { name: "Indifferent Monkey", sales: 1, price: 99.95 },
  7. { name: "Brooding Dragon", sales: 0, price: 6350 },
  8. { name: "Ingenious Tadpole", sales: 39450, price: 0.35 },
  9. { name: "Optimistic Snail", sales: 420, price: 1.50 }
  10. ]),
  11. sortByName: function () {
  12. this.items.sort(function (a, b) {
  13. return a.name < b.name ? -1 : 1;
  14. });
  15. }
  16. };
  17. myModel.gridViewModel = new ko.simpleGrid.viewModel({
  18. data: myModel.items,
  19. columns: [
  20. { headerText: "Item Name", rowText: "name" },
  21. { headerText: "Sales Count", rowText: "sales" },
  22. { headerText: "Price", rowText: function (item) { return "$" + item.price.toFixed(2) } }
  23. ],
  24. pageSize: 4
  25. });
  26. ko.applyBindings(myModel);

8 Animated transitions
该例子展示了2种方式实现动画过渡效果:

当使用template/foreach绑定的时候,你可以使用afterAdd和beforeRemove回调函数,他们可以让你写代码真实操作添加和删除元素,这样你就可以使用像jQuery的 slideUp/slideDown()这样的动画效果。在planet types之间切换或添加新的planet可以看到效果。

通过observable 类型的值,我们不难定义自己的Knockout绑定,查看HTML源代码可以看到一个自定义绑定fadeVisible,不管什么时候它改变了, jQuery就会在相关的元素上执行fadeIn/fadeOut动画效果。点击“advanced options” checkbox 可以看到效果。

代码: View

  1. <h2>Planets</h2>
  2. <p>
  3. <label>
  4. <input type="checkbox" data-bind="checked: displayAdvancedOptions"/>
  5. Display advanced options
  6. </label>
  7. </p>
  8. <p data-bind="fadeVisible: displayAdvancedOptions">
  9. Show:
  10. <label><input type="radio" value="all" data-bind="checked: typeToShow"/>All</label>
  11. <label><input type="radio" value="rock" data-bind="checked: typeToShow"/>Rocky planets</label>
  12. <label><input type="radio" value="gasgiant" data-bind="checked: typeToShow"/>Gas giants</label>
  13. </p>
  14. <div data-bind='template: { name: "planetsTemplate",
  15. foreach: planetsToShow,
  16. beforeRemove: function(elem) { $(elem).slideUp(function() { $(elem).remove(); }) },
  17. afterAdd: function(elem) { $(elem).hide().slideDown() } }'>
  18. </div>
  19. <script type="text/html" id="planetsTemplate">
  20. <div class="planet ${ type }">${ name }</div>
  21. </script>
  22. <p data-bind="fadeVisible: displayAdvancedOptions">
  23. <button data-bind='click: function() { addPlanet("rock") }'>
  24. Add rocky planet</button>
  25. <button data-bind='click: function() { addPlanet("gasgiant") }'>
  26. Add gas giant</button>
  27. </p>

代码: View model

  1. var viewModel = {
  2. planets: ko.observableArray([
  3. { name: "Mercury", type: "rock" },
  4. { name: "Venus", type: "rock" },
  5. { name: "Earth", type: "rock" },
  6. { name: "Mars", type: "rock" },
  7. { name: "Jupiter", type: "gasgiant" },
  8. { name: "Saturn", type: "gasgiant" },
  9. { name: "Uranus", type: "gasgiant" },
  10. { name: "Neptune", type: "gasgiant" },
  11. { name: "Pluto", type: "rock" }
  12. ]),
  13. typeToShow: ko.observable("all"),
  14. displayAdvancedOptions: ko.observable(false),
  15. addPlanet: function (type) { this.planets.push({ name: "New planet", type: type }); }
  16. };
  17. viewModel.planetsToShow = ko.dependentObservable(function () {
  18. // Represents a filtered list of planets
  19. // i.e., only those matching the "typeToShow" condition
  20. var desiredType = this.typeToShow();
  21. if (desiredType == "all")
  22. return this.planets();
  23. return ko.utils.arrayFilter(this.planets(), function (planet) {
  24. return planet.type == desiredType;
  25. });
  26. } .bind(viewModel));
  27. // Here's a custom Knockout binding that makes elements shown/hidden via jQuery's fadeIn()/fadeOut() methods
  28. // Could be stored in a separate utility library
  29. ko.bindingHandlers.fadeVisible = {
  30. init: function (element, valueAccessor) {
  31. // Initially set the element to be instantly visible/hidden depending on the value
  32. var value = valueAccessor();
  33. $(element).toggle(ko.utils.unwrapObservable(value));
  34. // Use "unwrapObservable" so we can handle values that may or may not be observable
  35. },
  36. update: function (element, valueAccessor) {
  37. // Whenever the value subsequently changes, slowly fade the element in or out
  38. var value = valueAccessor();
  39. ko.utils.unwrapObservable(value) ? $(element).fadeIn() : $(element).fadeOut();
  40. }
  41. };
  42. ko.applyBindings(viewModel);

该分类下的相关小册推荐: