Knockout

这是一个js的MVVM(Module-view-ViewModel)框架,这个方便了前端开发者可以不用去写大量的dom交互。它的兼容性也比较好,IE6以上和firfox上应用的都没什么问题。

使用步骤

  1. 引入jQuery.min.js,引入Knockout.js,Knockout.js下载地址
  2. 定义构造函数–实例化–绑定,代码如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //构造函数,定义在标签上要绑定的名字和数据
    var ViewModule=function(){
    var self=this;
    self.gg=ko.observable("测试");
    self.userName=ko.observable();
    self.city=ko.observableArray(['深圳','广州','上海']);
    self.hobby=ko.observableArray([{key:'10001',value:'篮球'},{key:'10002',value:'羽毛球'}])
    self.selectedHobby=ko.observable();
    }
    var currentViewModule=new ViewModule();//实例化
    ko.applyBindings(currentViewModule);//绑定
1
2
3
4
5
6
//html,应用上面js绑定好的数据
<div data-bind="html:gg"></div>//这里面会输出‘测试’
<input type="text" data-bind="value:userName">
<p data-bind="html:userName"></p>//每次在上面的input输完东西后鼠标离开后都会将输入的数据填入到这个p标签里面
<select data-bind="options:hobby,selectedOptions:selectedHobby,optionsCaption:'--请选择--',optionsText:'key',optionsValue:'value'"></select>
<b data-bind="html:selectedHobby"></b>

接下来来点比较好用的

###
点击事件和循环遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>des</th>
</tr>
</thead>
<tbody data-bind="foreach:arr">
<tr>
<td data-bind="html:$index"></td>//$index是konckout自带的参数,自动计算个数进行0,1,2,3...
<td data-bind="html:(name=='月球'?'这是嫦娥的家':name)"></td>//还可以进行条件判断
<td data-bind="html:des"></td>
</tr>
</tbody>
</table>
//循环遍历输出值还可以同过$data循环输出<tbody data-bind="foreach:arr"><tr data-bind="text:$data"></tr></tbody>
<button data-bind="click:addOne">添加一个星球</button>
<script>
$(document).ready(function(){
var arr=[
{id:1,name:"火星",des:"火星探索"},
{id:2,name:"月球",des:"月球探索"},
{id:3,name:"地球",des:"人类居住的地方"}
]

var ViewModule=function(){
var self=this;
self.arr=ko.observableArray(arr);
self.addOne=function(){
self.arr.push({id:"4",name:"接口的",des:"d快递费"});
return false;
}
}
var currentViewModule=new ViewModule();//实例化
ko.applyBindings(currentViewModule);//绑定
})
</script>

自定义输出格式
在看代码的时候先看下computed的概念和pureComputed的概念,我就不说概念了,直接以最简单的方式表达

  1. computed:当用户需要显示自己处理后的数据的时候,那就需要用到它了,它是依赖其他observable,就是通过observable定义好的数据,通过computed来处理这个定义好的数据在其他地方显示,就像下面的date,输入年月日后,在下面的总时间显示特定的格式
  2. pureComputed:当用户既要显示自定义后的数据又要通过修改制定后的数据同时也更新observable的数据,那这时候就可以用到pureComputed了,就像下面的pureComputed
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <input type="text" name="" data-bind="value:year">
    <input type="text" name="" data-bind="value:month">
    <input type="text" name="" data-bind="value:day">
    <input type="text" name="" data-bind="value:date2">
    <script>
    $(document).ready(function(){
    var ViewModule=function(){
    var self=this;
    self.year=ko.observable("");
    self.month=ko.observable("");
    self.day=ko.observable("");
    //注意:computed和pureComputed的区别就是computed不能双向绑定,就是我现在跟在了year或month或day里面的值会改变date的值,但是改变date里面的值不会改变year和month和day的值,但是pureComputed可以做到
    //注意:computed的应用是为了让
    self.date=ko.computed(function(){
    return self.year()+"年"+self.month()+"月"+self.day()+"日"
    })
    //下面这个比较厉害点
    self.date2=ko.pureComputed({
    write:function(value){
    var y=value.indexOf("年");
    var m=value.indexOf("月");
    var d=value.indexOf("日");
    self.year(value.substring(0,y));
    self.month(value.substring(y+1,m));
    self.day(value.substring(m+1,d));
    },
    read:function(){
    return self.year()+"年"+self.month()+"月"+self.day()+"日";
    },
    owner:self
    })
    }
    var currentViewModule=new ViewModule();//实例化
    ko.applyBindings(currentViewModule);//绑定
    })
    </script>

多个事件的绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<b data-bind="html:count,style:{color:styleColor},visible:count()>3"></b>//千万要记住count()要加上括号
<button data-bind="event:{click:addCount,mouseover:mouseOverEvent,mouseout:mouseOutEvent}">点击我把</button>
//传递参数bind,第一个参数是默认值就是viewModel对象,另一个缺省值是event指的是当前点击的对象,所以要传递参数是从第二个参数开始
<button data-bind="event:{click:sure.bind($data,'参数1','参数2')}">确定</button>
<script>
$(document).ready(function(){
var moduleView=function(){
self.count=ko.observable(0);
self.styleColor=ko.observable("black");
self.addCount=function(){
var currentCount=self.count();
var currentCount=currentCount+1;
self.count(currentCount);
};
self.mouseOverEvent=function(){
self.styleColor("red");
};
self.mouseOutEvent=function(){
self.styleColor("black");
};
self.sure=function(params){

}
}
var currentModuleView=new modulwView();
ko.applyBindings(currentModuleView);
})
</script>

定义组件
关键词:components\register\viewModel\template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//两种方式引入组件
<div data-bind="component:'messageList'"></div>//组件名字必须以字符串的方式引入,就是要用引号引入
<div data-bind="component:{name:'messageList',params:'chenjiaobin'}"></div>//可以传递一个params的参数
<script>
$(document).ready(function(){
ko.components.register(
'messageList',{
viewModel:function(params){//这个viewModule的名字不能改,必须是这个
var self=this;
self.account=ko.observable(params!=null?params:"tom");
self.message=ko.observable("");
self.send=function(){
self.messages.push({mes:self.message(),num:self.account()});
self.message("");
};
self.messages=ko.observableArray([]);
},
template:'<input type="text" name="" data-bind="value:message"><button data-bind="click:send">发送</button><ul data-bind="foreach:messages"><li><span data-bind="html:num"></span><span data-bind="html:mes"></span></li></ul>'
}
);
ko.applyBindings();
})
</script>

级联
这个demo主要涉及到的是select选择器,属性options/optionsCaption/optionsText/optionsValue/value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<select data-bind="options:cityWrap,optionsCaption:'--请选择城市--',optionsText:'name',optionsValue:'code',value:cs"></select>
<select data-bind="options:currentCity,optionsCaption:'--请选择地区--',optionsText:'name',optionsValue:'areaCode',value:dq"></select>
<script>
var viewModel=function(){
self.cs=ko.observable("");
self.dq=ko.observable("");
self.cityWrap=ko.observableArray([
{name:'北京',code:1001},
{name:"上海",code:1002}
]);
self.area=ko.observableArray([
{name:'天安门',areaCode:100010,cityCode:1001},
{name:'天坛',areaCode:100011,cityCode:1001},
{name:'圆明园',areaCode:100012,cityCode:1001},
{name:'上海门',areaCode:100013,cityCode:1002},
{name:'上海侨',areaCode:100014,cityCode:1002}
]);
self.currentCity=ko.computed(function(){
//这个是knock的数组过滤的方法
return ko.utils.arrayFilter(self.area(),function(item){
return item.cityCode==self.cs();
})
})
}
var currentViewModel=new viewModel();
ko.applyBindings(currentViewModel);
</script>

applyBindings参数
applyBindings有两个参数,applyBindings(currentViewModel,document.getElementById(“box”))
第一参数指视图对象,如上面的代码,第二参数是可选的,如果设置了第二个参数,比如box那么在元素设置里的id=box的元素下的后代元素可以使用视图模型里面定义的变量,在其他元素里面就不可以了。eg

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="chenjiaobin">
  <div data-bind="html:name"></div>
</div>
<div class="kevin">
  <div data-bind="html:name"></div>
</div>
<script>
var viewModel={
  username:ko.observable("陈焦滨")
}
ko.applyBindings(viewModel,document.getElementById("chenjiaobin"));
</script>
最后在id=chenjiaobin元素下显示出来的是“陈焦滨”,在id=kevin下的元素先显示的则是""

if和ifnot判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div>
<label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label>
<div data-bind="if: displayMessage">Here is a message. Astonishing.</div>//if应用
</div>
<div>
<label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label>
<div data-bind="ifnot: displayMessage">Here is a message. Astonishing.</div>//ifnot应用
</div>
<ul data-bind="foreach: planets">
<li>
Planet: <b data-bind="text: name"> </b>
<div data-bind="if: capital">
Capital: <b data-bind="text: capital.cityName"> </b>
</div>
</li>
</ul>
<script>
var viewModel={
  displayMessage:ko.observable(true),
planets: [
{ name: 'Mercury', capital: null },
{ name: 'Earth', capital: { cityName: 'Barnsley' } }
]
}
ko.applyBindings(viewModel);
</script>

textInput的使用
textInput与value的最大区别就是textInput它是实时更新的,而value需要离开焦点后才会生效
uniqueName主要是用来自动生成name值

1
2
3
4
5
6
7
8
9
10
<div>
<input type="text" data-bind="textInput:kk,uniqueName:true">//textInput的应用
<p data-bind="html:kk"></p>
</div>
<script>
var viewModel={
  kk:ko.observable("打电话")
}
ko.applyBindings(viewModel);
</script>

hasFocus的使用
当值为true时说明获得焦点,反之.
下面这个demo的效果是刚开始显示一串文字,点击文字后会显示输入框,离开焦点的时候输入框会消失

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div>
<p data-bind="visible:!edit(),text:something,click:changeFocus"></p>
<input type="text" name="" data-bind="visible:edit,value:something,hasfocus:edit">//hasfocus的使用
</div>
<script>
var viewModel={
  something=ko.observable("来啊,互相伤害啊"),
edit=ko.observable(false),
changeFocus=function(){
this.edit(true);
}
}
ko.applyBindings(viewModel);
</script>

循环遍历的另一种做法
下面这个遍历是knockout默认的语法

1
2
3
<!-- ko foreach:city -->
<p data-bind="html:$data"></p>
<!-- /ko -->

复选框的checkedValue和checked

1
2
3
4
5
6
7
8
9
10
11
12
<!--ko foreach:city-->
<input id="chk" type="checkbox" data-bind="checkedValue:$data,checked:$root.chkArr">
<label for="chk" data-bind="text:$data"></label>
<!--/ko-->
<div data-bind="html:chkArr"></div>//点击选择复选框后选择的会在这个标签里面显示
<script>
var viewModel={
  chkArr:ko.observableArray(),
city:['北京','上海','广州']
}
ko.applyBindings(viewModel);
</script>

template属性的使用
这个可以通过定义模板然后在指定的dom里面插进去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div data-bind="template:{name:'mytemplate1',foreach:nobody}"></div>//foreach的使用,循环
<div data-bind="template:{name:'mytemplate2',data:something}"></div>//data的使用,一个对象数据,不用循环
<script type="text/html" id="mytemplate1">
<h1 data-bind="html:name"></h1>
<h2 data-bind="html:age"></h2>
</script>
<script type="text/html" id="mytemplate2">
<p data-bind="text:name"></p>
</script>
<script type="text/javascript">
var viewModel=function(){
var self=this;
self.nobody=ko.observableArray([{name:"啥子呦",age:12},{name:"tony",age:24}]);
self.something={name:"啥子呦",age:12}
}
var currentViewModel=new viewModel();
ko.applyBindings(currentViewModel);//激活视图模型
</script>

在这里还可以通过别名(as:’’)来设置获取值,这个主要是用在多重嵌套循环里面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div data-bind="template:{name:'mytemplate1',foreach:nobody,as:'chen'}"></div>//通过as设置别名
<script type="text/html" id="mytemplate1">
<h1 data-bind="html:name"></h1>
<h2 data-bind="html:age"></h2>
<h3 data-bind="template:{name:'moreTemp',foreach:mm,as:'jiaobin'}"></h3>//嵌套循环里面使用as命名第二个模板
</script>
<script type="text/html" id="mytemplate2">
<p data-bind="text:jiaobin"></p>
</script>
<script type="text/javascript">
var viewModel=function(){
var self=this;
self.nobody=ko.observableArray([{name:"啥子呦",age:12,mm:['打篮球','游泳','打啥']},{name:"tony",age:24,mm:['乒乓球','羽毛球','弹吉他']}]);
}
var currentViewModel=new viewModel();
ko.applyBindings(currentViewModel);//激活视图模型
</script>
//这两个模板别名的作用是为了获取数据数据的时候出现混乱,比如,当第二个模板的数据里面也有name这个属性的时候,那么如果我们直接用`data-bind='text:name'`的时候就可能输出的是第二个模板里面的name值,那如果我们设置了别名,我们就可以获取到parent的name值

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器