Wiesler

导航

knockout.js 框架使用小记

Knockout js 使用心得条目:

1 knockout js是个轻量级的js框架,在knockout官网下载之后,可以引入自己的html中。knockout js的使用并不需要jQuery配合,但我们也可以在jQuery之后自己的js文件之前引入knockoutjs

 

2 knockout js是一个MVVM(Model View Viewmodel)框架, 其他还有MVC(Controller),MVP(Presenter)框架


3 knockout js 是创建一些监控变量和监控数组和事件,并将这些变量,数组,事件通过data-bind属性统统绑定在html上。好处:1省去了在js文档中要写绑定和获取元素的烦恼,因为某个html元素要获取的内容和事件已经绑定好了 2 如果元素的内容或者属性有变化,不需要再查找元素,更改属性,直接修改绑定的变量,数组和事件,html元素就会动态地更新


4 knockout的引入:

<script type="text/javascript" src="./js/jquery-2.2.3.js"></script>
<script src="./js/knockout-3.4.0.js"></script>
<script type="text/javascript" src="./js/demou1.js"></script>

5 knockout的结构:

在js文件中,需要引入的初始数据(一般来说都是不变的数据)都可以在model外定义,可变的数据都要定义在model内部

var variable1 = "...";
var variable2 = "...";
var variableArray = ["..."];
var variableObject = {};
/*...一系列初始量的定义, 这些值是作为外部数据,要传入这个model的...*/
function ViewModel(){
   var self = this;//将this赋值给self,这样方便内部不同域时使用this
   /*
   * 自己定义的监控变量,监控数组,还有事件写在这里
   */
}
ko.applyBindings(new ViewModel());

最后需要应用这个ViewModel,注意每个项目只可以应用一次这个Model

严重注意一点:如果在body的末尾引入script,那么就可以直接向上边这样写代码了;如果在头部引入(推荐),那么就需要将所有代码包裹起来(让DOM树结构完整了再运行代码),两种方法,可以用jQuery包裹,也可以用纯js的window.addEventListener(“load”, function(){}, false)来包裹,个人觉得第二个更好,少用jQuery可以节省运行时间

window.addEventListener("load", function(){
   /*...所有代码...*/
}, false);

$(function(){
   /*...所有代码...*/
});

 

6监控变量:

监控变量的定义

self.variable1 = ko.observable("...");
self.variable2 = ko.observable(100);
self.variable3 = ko.observable(variable1);
self.variable4 = ko.observable({
   name: "alex",
   age: 18
});

这个括号里面就是这个监控变量的值,这个值可以是字符串,可以是数字。这样的话,模型就会实时监控这个变量,任何html元素使用了这个变量,当我们在模型中改变这个变量的时候,html中的值就会改变。

 

监控变量的值获取

var value = self.variable1();

注意,值后边一定要有括号,因为监控的本质是个函数,执行这个函数会返回所监控的内容

这个括号里还可以写外部定义的字符串或数字

 

监控变量的值更新

self.variable1("abc");
self.variable2(self.variable2() + 1);
self.variable1().school = "123"

在括号内赋值,或者改变数值,来更新监控变量。注意第二个,更新的时候是在原有的上边加1

 

7 监控数组

监控数组的定义:使用ko.observableArray()来定义

self.arr = ko.observableArray([]);
self.arr1 = ko.observableArray([{}, {}, {}]);
self.arr2 = ko.observableArray(variableArray);

监控数组里面可以放空数组,可以放对象组成的数组,可以把模型外的数组引入

注意,如果想使用对象,也推荐将对象作为数组的元素来使用,方便用foreach:绑定,如果只是想用对象的话,也可以用ko.observable()来监控

 

监控数组的获取

var array = self.arr();

必须要有括号。获取到的是数组,也就是之前括号里面的监控的值


监控数组的更新

self.arr([{
   "name": "Lee"
}, {
   "name": "alex"
}])

当然监控数组也可以用js的数组方法来更新,

比如self.arr.push(123) 和 self.arr().push(123)效果一样的,不过推荐后者,与监控变量一样的方法,更清晰。

监控数组可以用的方法比如.push()  .pop()  .unshift()  .shift()   .slice()  .reverse()   .sort()  .splice()

注意.sort()方法,我们知道排序时必须要传一个比大小的函数,不然会按照字符串来比较

self.arr().sort(function(a, b){
   if(a < b){
       return -1;
   }else{
       return 1;
   }
});

从小到大还是从大到小就是调整-1和1的位置

因为数组的上述方法都是可以直接改变数组的,所以我们可以用self.arr().方法()直接使用,但是无论字符串还是数字都没有可以改变自身的方法,所以就不能这样更新了。

 

其实监控变量还是监控数组本质都可以用self.content(self.content()变化)来更新, 获取都是用self.content()来获取


8 事件:

通过self.事件名 = function(){...};来定义事件,事件可以用于被触发时,更新监控数据或者做其他操作

self.divClick = function(){
   self.arr1().push("click"); // 更新数据
   console.log("Click");
};
<div data-bind="html: variable1, event: {click: divClick}"></div>

9 绑定:通过在html标签内引入data-bind = “” 来绑定标签和监控数据(变量,数组,事件)

详细绑定可以参考knockout的文档http://knockoutjs.com/documentation/introduction.html

这里说几个比较常用的:

多个事件绑定用,号隔开,同一种绑定的不同类型,用: {,}来区别, style里用backgroungColor这种写法,而不用background-color这种写法

 

html绑定和text绑定:

我们在jQuery中知道$(..).html() 和 $(..).text()的作用,可以设置和获取某元素的内容,区别在于html()方法一旦遇到可以转换成标签的内容就会变成html标签,可以动态生成内部元素,而text()方法不管遇到什么都会作为这个元素的文本内容体现


那么这里的绑定也是这个意思:

使用方法:

<div data-bind="html: variable2"></div>

这个html:后的variable2 一定是在js中已经定义好了的监控变量 self.variabl2 = ko.observable(..)


visible绑定:

self.flag1 = ko.observable(true);
self.flag2 = ko.observable(false);

定义两个保存true和false的状态值

<div data-bind="html: variable1, visible: flag2"></div>

如果visible: false状态,就会自动隐藏,如果visible: true状态就会显现。而这里的隐藏很有用,隐藏之后并不占位,可以用来实现动态的列表等

 

attr绑定:用来绑定并动态修改元素的行内属性

self.src = ko.observable("...");
self.alt = ko.observable("...");

定义了行内属性值

<img src="" alt="" data-bind="attr: {src: src, alt: alt}"/>

与jQuery相似的是,对于表单元素input等,或者标签行内有value的属性,可以用value来绑定

data-bind=”value: ...”

style绑定:用来绑定并动态修改元素的样式

self.displayBlock = ko.observable("block");
self.backgroundColor = ko.observable("red");
<div data-bind="style: {display: displayBlock, backgroundColor: backgroundColor}"></div>

 

也可以用事件绑定了,

self.backgroundColor = function(){
   return "rgb(23, 45, 67)";
};

只不过backgroungColor: backgroundColor()来调用

<div data-bind="html: variable2, style: {display: displayBlock, backgroundColor: backgroundColor()}"></div>

 

css绑定:这个是添加css类的,也就是给元素添加或动态修改class的

比如我在css中定义了

.red {
   background-color: red;
}

我在js中,监控了这个类名

self.addRedClass = ko.observable("red");

那么我可以绑定到标签上

<div data-bind="html: variable2, css: addRedClass"></div>

该标签就可以自动获取并添加一个类 red,相当于class = red

也可以用方法来获取,动态修改类,来切换一些复杂的预先定义好的样式:

self.addRedClass = function(){
   return "red";
};

只不过这个时候也是要用addRedClass()来获取,

<div data-bind="html: variable2, css: addRedClass()"></div>

事件绑定类:

click绑定:

self.divClick = function(){
   self.arr1().push("click"); // 更新数据
   console.log("Click");
};

定义点击要触发的方法

<div data-bind="html: variable2, click: divClick"></div>

submit绑定:

self.formSubmit = function(){
   self.divClick();
   return false;//阻止默认事件,也是默认值,可以不写return false
   //return true;//允许默认事件
};

定义submit的方法,提交方法要绑定在form元素上,按回车的时候触发

<form action="" data-bind="submit: formSubmit"></form>

对于任何事件,click或者submit,或者之后的event包含的所有事件,使用data-bind都是阻止默认行为的,如果想要开启默认行为就要return true;

 

event绑定:

应该算是所有事件都适用,可为一个元素绑定多个事件

self.rightClick = function(){
   console.log("rightClick");
   return false;
};
<div data-bind="html: variable2, event: {click: divClick, contextmenu: rightClick}"></div>

同时绑定了左击和右击事件

 

value绑定和textInput绑定:

他们两个都可以用来绑定input,select,textarea元素,

value: 监控元素或者函数(), valueUpdate: ‘keyup’

后边还可以有一个参数来指明,什么时候更新这个value,使用valueUpdate: 可以是’keyup’弹起触发 ‘keypress’按下触发(不松手会持续触发) ‘afterkeydown’按下后触发

<input type="search" data-bind="value: inputValue, valueUpdate: 'afterkeydown', event: {click: inputClick, keyup: inputKeyUp}" />

实际上,如果你要浏览器边输入边检测输入的内容的话,textInput绑定最合适,因为他可以不加附加参数,并且检测所有输入的值

<input type="search" data-bind="textInput: inputValue" />

foreach绑定:

如果你想要根据已有的数据动态生成一些元素,并添加到父元素内,或者动态管理元素的内容,那么对父元素采用foreach绑定最合适了。

之前我们知道用html绑定也可以给元素添加子元素,并且这个子元素也可以应用绑定,问题是,这样生成的子元素,虽然我写了绑定,但是无法触发。

self.variable2 = ko.observable("<span data-bind='click: divClick'>123</span>");
<div data-bind="html: variable2"></div>

因为模型应用的时候,他刚刚生成这个元素,并没有解析他的绑定事件,所以绑定不了。

解决办法:

单独对这个元素绑定一下模型,

模型结尾,

var viewmodel = new ViewModel();
ko.applyBindings(viewmodel);
ko.applyBindings(viewmodel, $("span")[0]);

这样我们绑定的还是同一个模型,第一次把DOM里已经有的元素和事件绑定了,第二次绑定那些动态生成的元素,不是jQuery元素,一定是DOM元素, document.getElementsByTagName("span")[0]

或者$("span")[0] 或者$("span").get(0)

 

另一种解决办法就是foreach绑定:

这个绑定经常用于比如要给ul - li或者ol - li动态添加li的时候使用,也可以用于动态添加几组元素比如,动态添加三组 h3-p-span的组合到父元素中。

并且foreach绑定可以绑定并解析事件,无需在模型末尾再绑定元素。这时就要用observableArray([])了,数组里面包含几个对象元素,那么就会产生几个子元素。

父元素用foreach: 监控数组,写一个子元素, 子元素内用$data.来获取每个对象中的值,作为相应的绑定内容

self.arr3 = ko.observableArray([{
   "name": 'lee',
   "liEvent": function(){
       console.log("click");
   }
}, {
   "name": 'george',
   "liEvent": function(){
       console.log("click");
   }
}, {
   "name": 'alex',
   "liEvent": function(){
       console.log("click");
   }
}]);

 

<ul data-bind="foreach: arr3">
   <li data-bind="html: $data.name, click: $data.liEvent"></li>
</ul>

这个时候就可以发挥数组的方法的灵活性了,就可以操作数组,数组里面可以添加对象等。也可以自己写函数让每个对象内容不同,这样绑定的结果也会不同了。

 

使用knockout时,经常用的数组.forEach()方法和indexOf()取某元素索引的方法

self.arr3().forEach(function(item){
   if(item.name == "george"){
       console.log(self.arr3()[self.arr3().indexOf(item)]);
   }
});

 

对于,html刚加载时的事件window.onload, 或者屏幕缩放时的动态捕捉事件window.onresize, 可以绑定在body上

<body data-bind="event: {load: windowLoad(), resize: windowResize()}">

 

 

 

 

...........未完待续...........

 

posted on 2016-07-07 01:39  Wiesler  阅读(1034)  评论(0编辑  收藏  举报