据说knockoutjs差不多被拍死了,在众多mvvm框架当中,用于复杂的项目干不过angular,简单点的又有vue、react,再简单的话就都不需要用这些东西了,但是公司一个项目用到这个东西,貌似这个东西再配合jQuery还是挺好用的,还有兼容性好,个子小,简洁等优点
中文文档传送门
------------------------------------------------分割线---------------------------------------
首先knockoutjs是基于jQuery的,也就是说引入这玩意之前得先引入jQuery
对于MVVM的理解
model: ko通过ajax向服务器请求的数据模型
viewModel:个人认为就是操作页面的js代码
view:就是可见的页面(是否就是html和css组成的页面?)
(个人对于mvc、mvvm这些还是比较模糊的)
创建数据模型(View Models )和监控属性(Observables)
使用KO创建一个View Model,仅仅只需要声明一个JavaScript对象,也就是在script标签内创建一个对象
var myViewModel = {personName: 'Bob',personAge: 123};
当然了,对象的名字是随你喜欢
<span data-bind="text: personName"></span>//这是绑定到标签上,使用的都是data-bind
最后是激活
ko.applyBindings(myViewModel )
这样整个过程便完成了,当然除了激活意外,对象的内容和绑定标签的属性是需要根据需要而改变的
ko.applyBindings(obj,[node] )
接收两个参数,第一个参数是必须的,是创建的对象,第二个是可省的,你可以使用第二个参数来设置要使用data-bind属性的HTML元素或容器,同一个容器内只能进行一次激活
//容器1
<div class="box">
<input type="text" data-bind="value:text">
<span data-bind="text: value"></span>
</div>
//容器2
<div class="box2">
<input type="text" data-bind="value:text1">
</div>
<script src="knockout.js"></script>
<script>
var viewPoint = {
text: ko.observable("abc"),
value: ko.observable("123"),
}
ko.applyBindings(viewPoint,document.querySelector(".box"))//指定容器1范围
var viewPoint1 = {
text1:ko.observable("321")
}
ko.applyBindings(viewPoint1,document.querySelector(".box2"))//容器2激活
</script>
若是这样,则报错
<div class="box">
<input type="text" data-bind="value:text">
<span data-bind="text: value"></span>
</div>
<script src="knockout.js"></script>
<script>
var viewPoint = {
text: ko.observable("abc")
}
ko.applyBindings(viewPoint)
var viewPoint1 = {
value:ko.observable("321")
}
ko.applyBindings(viewPoint1)
//报错
Observables
这玩意是启动监控,监控data-bind设置的内容,如
<input data-bind="value: personName">
var myViewModel = {personName: ko.observable()};//当input里面的值改变的时候,同时会将值赋给personName,然后就能在myViewModel 对象里面查看,当然也可以通过ko.observable()去设定输入框的值,比如
{personName: ko.observable(123)}
,输入框里面的值就会是123,貌似使用value的话,ko.observable()传入的参数只能是常量,如果是变量,即使在上下文当中该变量有所改变,输入框的值也不会变,如果要动态的双向绑定的话,是否是需要其他的属性??
要注意的是ko.observable监控的对象都是方法。也就是说你想拿输入框的值,你需要这样var data = myViewModel .personName()
,像执行行数一样
饥人是双向绑定,那么就是随时可以通过js随时去改变这个值,比如这样
<div data-bind="text: shouldShowMessage"> </div>
<button class="btn">点我</button>
/*--------------------------------------------*/
var btn = document.querySelector(".btn");
var viewModel = {
shouldShowMessage: ko.observable(123)
};
btn.addEventListener("click",function(){
console.log(1)
viewModel.shouldShowMessage(321); //注意重新给值的格式
})
ko.applyBindings(viewModel)
监控属性数组
var myObservableArray = ko.observableArray([
{name: "Bungle", type: "Bear" },
{name: "George", type: "Hippo" },
{name: "Zippy", type: "Unknown" }]); //括号里面的参数是一个数组
上面是用ko.observable()取监控value字符串,那如果是数组的话,就得用ko.observableArray()去监控
<select width:100px data-bind="options: selectOptions, optionsText: 'name', optionsValue: 'type' "> </select>
var arr = [
{name: "Bungle", type: "Bear" },
{name: "George", type: "Hippo" },
{name: "Zippy", type: "Unknown" }
]
var form = {
selectOptions: ko.observableArray(arr)
}
// function Form(){
// this.selectOptions = ko.observableArray(arr)
// } //也可以是函数
// ko.applyBindings(new Form())
ko.applyBindings(form)
貌似只有下拉列表能这么玩
Knockoutjs数组常用的方法如下:
(1)、myObservableArray.push('Some new value'):增加一个新的元素
(2)、myObservableArray.pop():删除一个元素,并返回其值
(3)、myObservableArray.unshift('Some new value'):在数组的开始处增加一个新的元素
(4)、myObservableArray.shift():删除数组的第一个元素,并返回其值
(5)、myObservableArray.reverse():反转数组的顺序
(6)、myObservableArray.sort():数组排序。排序规则可以由用户自己定义也可以使用默认,默认情况下按照字母顺序或者数字的顺序进行排序。自己定义排序规则时需要接收数组 中的两个元素,并且需要返回一个数值,当此值小于0时表示第一个元素较小,当此值大于0时,表示第二个元素较小,当等于0时表示两个元素相等。这基本和js一样
(7)、myObservableArray.splice():数组截取
observerbale.remove(item),移除所有符合item的对象,并把这些对象作为一个数组返回
myObservableArray.remove(function(item) { return item.age < 18 })
//移除myObservableArray数组内所有年龄属性小于18的对象,并返回这些对象组成的新数组
计算属性
ko.computed()
<span name="" id="" width="100" data-bind="text:fullName"></span>
<button class="btn">点我</button>
var aa = 1,bb = 2;
var form = {
fullName:ko.computed(function(){return aa+bb}) //显示3
}
ko.applyBindings(form)
也可以这样玩,通过页面的输入而改变页面的其他值
function MyViewModel() {
this.firstName = ko.observable('Planet');
this.lastName = ko.observable('Earth');
this.fullName = ko.computed({
read: function () { }, //一般用于显示自己的值
write: function (value) {
var self = this
var btn = document.querySelector(".btn")
btn.addEventListener("click",function(){
var lastSpacePos = value.lastIndexOf(" ");
// Ignore values with no space character
self.firstName(value);
// Update "firstName"
self.lastName(value+"我");
// Update "lastName"
})
}, owner: this //把this指向的环境传进来
});
}
ko.applyBindings(new MyViewModel());
但是,不能这样玩(通过用就是改变变量来改变原以定好的页面的值)
比如这样
btn.addEventListener("click",function(){
value = "hello word" // 和上面的代码的区别就是重新赋值给value
var lastSpacePos = value.lastIndexOf(" ");
// Ignore values with no space character
self.firstName(value);
// Update "firstName"
self.lastName(value+"我");
// Update "lastName"
})
}, owner: this //把this指向的环境传进来
还可以做表单验证,以下是只能输入数字,若不是,则会提示
<p>Enter a numeric value:<input data-bind="value: attemptedValue"/></p>
<div data-bind="visible: !lastInputWasValid()">That's not a number!</div>
function MyViewModel() {
this.acceptedNumericValue = ko.observable(123);
this.lastInputWasValid = ko.observable(true);
this.attemptedValue = ko.computed({
read: this.acceptedNumericValue, //对应this.acceptedNumericValue,write部分会进行验证,只输出数字部分,显示在attemptedValue
write: function (value) {
console.log(this.acceptedNumericValue())//数值部分
if (isNaN(value))
this.lastInputWasValid(false);
else {
this.lastInputWasValid(true);
this.acceptedNumericValue(value);
// Write to underlying storage
}
}, owner: this
});
}
ko.applyBindings(new MyViewModel());
----------------------------------------------我是分割线----------------------------------------------
-
visible绑定
无非就是true可见,false不可见,不仅是通过传入布尔值去改变,还可以通过函数表达式(无非就是执行该表达式返回的结果是true还是false)<div data-bind="visible: shouldShowMessage"> You will see this message only when "shouldShowMessage" holds a true value.
</div>
<div data-bind="visible: myValues().length >0"> You will see this message only when 'myValues' has at least one member.
</div>
可以通过js随时改变这个布尔值
var viewModel = {
shouldShowMessage:ko.observable(true)
}
$(node).on("click",function(){
viewModel.shouldShowMessage(false)
})
ko.applyBindings(viewModel)
-
Text绑定
<span data-bind="text:userName"></span> var form = { user: ko.observable("123") } form.userName = ko.computed(function(){ return this.user.length>3?"123":"321" },form) //需要传进this
-
html绑定
当代码中有html标签的时候,会进行编译,而如果用text则不编译,标签以文本的方式显示
<div data-bind="html: details"></div>
var viewModel = {
details: ko.observable() // Initially blank
};
viewModel.details("<em>For further details</em>")//斜体For further details
ko.applyBindings(viewModel) -
CSS类名绑定
用true和false决定是否使用该class,可以用表达式,也可以直接是true和false<div data-bind="css: { profitWarning: currentProfit() < 0,majorHighlight: isSevere }"> <div data-bind="css: { 'my-class': someValue }">...</div> //注意变量名的格式,像这般,要加引号,一般加上引号就没有错
-
Style属性绑定
这和class绑定类似<div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }"> Profit Information
</div>
注意有横杠的一些样式的定义
错误:{ font-weight: someValue }; 正确:{ fontWeight: someValue }
-
attr属性绑定
类似于href、title等属性的绑定(可以动态)<a data-bind="attr: { href: url, title: details }"> Report </a> <button class="btn">点我</button> var viewModel = { url: ko.observable("#"), details: ko.observable("Report including final year-end statistics") } ko.applyBindings(viewModel) var btn = document.querySelector(".btn") btn.addEventListener("click",function(){ viewModel.url("https://baidu.com") })
-
foreach绑定
就是遍历数组,通常用于列表,详细参考点我,$parent、$index、$data、as(命名)<table> <thead> <tr><th>First name</th><th>Last name</th></tr> </thead> <tbody data-bind="foreach: people"> <tr> <td data-bind="text: firstName"></td> <td data-bind="text: lastName"></td> </tr> </tbody> </table> ko.applyBindings({ people: [ { firstName: 'Bert', lastName: 'Bertington' }, { firstName: 'Charles', lastName: 'Charlesforth' }, { firstName: 'Denise', lastName: 'Dentiste' } ] });
-
if绑定
决定显示与否,下过和visible类似,与visible不同的是,if binding是真正的控制Html标签是否出现在DOM中,如果绑定的值为false,则Html标签不会出现在页面中,回频繁地操作dom -
with绑定
可以使用with binding来重新定义一个上下文绑定,按照我的理解是这样的<p data-bind="with: coords"> //coords是一个对象 Latitude: <span data-bind="text: latitude"> //latitude和longitude是对象里面的属性或者方法, //一般访问的话需要是coords.latitude,而现在只需要用latitude就行, //这就是父元素上用了width指定了上下文的功劳 </span> , Longitude: <span data-bind="text: longitude"> </span> </p> ko.applyBindings({ coords: { latitude: 51.5001524, longitude: -0.1262362 } });
-
click绑定
点击事件,默认情况下,Knockout会阻止冒泡,防止默认的事件继续执行
也可以这样去阻止冒泡
<button data-bind="click: myButtonHandler, clickBubble: false">
Click me
</button> -
event绑定
keypress,mouseover和mouseout,change<div data-bind="event: { mouseover: myFunction }"> Mouse over me </div> var viewModel = { myFunction: function(event) { if (event.shiftKey){doSomething} }
防止事件冒泡
<button data-bind="event: { mouseover: myButtonHandler },mouseoverBubble: false">
Click me
</button>
网友评论