在knockoutjs中,已有的绑定功能已经十分强大,基本上可以不需要再去考虑扩展了,但是,也有例外的场景,面对这种场景,还是得去完成,knockoutJS提供了自定义绑定来扩展绑定功能。

一、新建绑定

  新建一个js文件来尝试绑定功能,按照给定的格式ko.bindingHandlers.xxx来扩展一个绑定。

ko.bindingHandlers.yourBindingName = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// This will be called when the binding is first applied to an element
// Set up any initial state, event handlers, etc. here
}, update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// This will be called once when the binding is first applied to an element,
// and again whenever the associated observable changes value.
// Update the DOM element based on the supplied values here.
}
};

  其次,在html中完成绑定即可,用法同自带的绑定。

<div data-bind="yourBindingName: someValue"> </div>

  此处需要注意的是,在自定义绑定中,initupdate方法不是一定要全部定义,也可以只定义其中一个。

  最后将js文件引入,放置在knockoutjs下

<script src="~/lib/knockout/knockout-3.5.0.js"></script>
<script src="~/js/custombindings.js" asp-append-version="true"></script>

二、解析update函数

  当绑定的监听元素的发生改变时或是关联的监听元素改变时,knockout会回调update函数,只要存在关联的监听元素改变,update函数都会被立马回调,回调时会传递几个参数到update函数中。

  • element:本次绑定的DOM元素

  • valueAccessor:一个JavaScript函数,通过valueAccessor()可以得到应用到这个绑定的model上的当前属性值,使用valueAccessor()无需传入参数,再通过调用ko.unwrap()并传入valueAccessor()得到的属性值可以拿到实际值。

  • allBindings:一个JavaScript对象,通过这个对象可以访问绑定的DOM元素上的所有属性值,通过allBindings.get('属性名')得到这个元素上指定属性名的值,如果这个属性不存在,则返回undefined,或者通过allBindings.has(‘属性名’)来判别该属性是否存在于这个DOM元素上。

  • bindingContext: 当前元素的绑定上下文,通过该绑定上下文可以访问当前的绑定上下文内的属性及该绑定上下文的父级上下文内、同级上下文内的属性(功能十分强大)。

  例如,你可能想通过 visible绑定来控制一个元素的可见性,但是你想让该元素在隐藏或者显示的时候加入动画效果。那你可以自定义自己的绑定来调用jQuery的slideUp/slideDown 函数:

ko.bindingHandlers.slideVisible = {
update: function(element, valueAccessor, allBindings) {
// 获取属性值
var value = valueAccessor(); // 获取当前属性值
var valueUnwrapped = ko.unwrap(value); // 从当前绑定上下文的其它上下文获取属性值
var duration = allBindings.get('slideDuration') || 400; // 400ms is default duration unless otherwise specified // 操控DOM元素
if (valueUnwrapped == true)
$(element).slideDown(duration); // Make the element visible
else
$(element).slideUp(duration); // Make the element invisible
}
};

  页面上,直接按照格式完成绑定,此处,我将自定义文件已经引入到模板页的js块中。

<div data-bind="slideVisible: giftWrap, slideDuration: 600">You have selected the option</div>
<label><input type="checkbox" data-bind="checked: giftWrap" /> Gift wrap</label> @section Scripts{
<script type="text/javascript">
var viewModel = {
giftWrap: ko.observable(true)
}; $(function () {
ko.applyBindings(viewModel);//完成绑定
});
</script>
}

  可以看到自定义绑定的效果,可以在多处地方完成绑定以实现代码重用。  

  

三、解析init函数

  knockout在DOM元素使用自定义绑定的时候会调用你的init函数,init函数主要有两个用途:

  • 为DOM元素设置初始值

  • 注册事件句柄,例如当用户点击或者编辑DOM元素的时候,你可以改变相关的observable值的状态。

  init函数接收和update函数一样的参数,按照上面的例子,改造一下,让slideVisible在页面第一次显示的时候设置该元素的状态(但是不使用任何动画效果),以便于让动画在以后用户改变的时候再执行。

ko.bindingHandlers.slideVisible = {
init: function (element, valueAccessor) {
var value = ko.unwrap(valueAccessor());
$(element).toggle(value);
},
update: function (element, valueAccessor, allBindings) {
// 获取属性值
var value = valueAccessor(); // 获取当前属性值
var valueUnwrapped = ko.unwrap(value); // 从当前绑定上下文的其它上下文获取属性值
var duration = allBindings.get('slideDuration') || 400; // 400ms is default duration unless otherwise specified // 操控DOM元素
if (valueUnwrapped == true)
$(element).slideDown(duration); // Make the element visible
else
$(element).slideUp(duration); // Make the element invisible
}
};

  将viewModel中的giftWrap设置默认值为false,当页面启动后将会看见相应的Div直接是隐藏状态,并在点击选中后才会显示出来。

var viewModel = {
giftWrap: ko.observable(true)
};

  

四、DOM事件后修改监听值

  已经掌握了使用update回调当observable值改变的时更新DOM元素。但是反过来的场景呢,例如当用户对某个DOM元素做一些操作时,想更新相关的observable值。这可以通过使用init回调来注册一个事件句柄,来改变相关的observable值。

ko.bindingHandlers.hasFocus = {
init: function (element, valueAccessor) {
$(element).focus(function () {
var value = valueAccessor();
value(true);
});
$(element).blur(function () {
var value = valueAccessor();
value(false);
});
},
update: function (element, valueAccessor) {
var value = valueAccessor();
if (ko.unwrap(value))
element.focus();
else
element.blur();
}
};

  比如,当用户点击输入框时展示,离开时隐藏,同时修改监听值,控制按钮的启用禁用。

<p>Name: <input data-bind="hasFocus: editingName" /></p>

<div data-bind="visible: editingName">You're editing the name</div>
<button data-bind="enable: !editingName(), click:function() { editingName(true) }">Edit name</button> @section Scripts{
<script type="text/javascript">
var viewModel = {
giftWrap: ko.observable(false),
editingName: ko.observable()
}; $(function () {
ko.applyBindings(viewModel);//完成绑定
});
</script>
}

  可以得到如下效果

  

  在虚拟元素上也可以使用自定义绑定

<!-- ko mybinding: somedata --> ... <!-- /ko -->

 至此,完成了自定义绑定的方式,虽然实际使用的少,诸如二八原则,但是只要存在场景便可以发挥用武之地。

  代码地址:https://gitee.com/530521314/Partner.TreasureChest.git

2019-08-29,望技术有成后能回来看见自己的脚步

KnockoutJS-自定义属性绑定的更多相关文章

  1. WPF自定义控件的自定义属性绑定后不更新问题

    原文:WPF自定义控件的自定义属性绑定后不更新问题 需要在绑定时设置属性变更触发 UpdateSourceTrigger=PropertyChanged 例如: <Border CornerRa ...

  2. knockoutjs with绑定导致unobtrusive validation失效的问题

    如果最初的时候with绑定的对象是空的,那么with绑定内部的unobtrusive validation规则在提交的时候无法生效,无法进行验证. 解决办法: 在提交的时候(或者with绑定的对象非空 ...

  3. KnockoutJS(3)-绑定语法

    绑定语法大致分为2种: 1. 数据绑定(data-bind syntax) 2. 绑定上下文(Binding Context) 下面针对这2中绑定语法分别介绍一下 1. 绑定上下文(Binding C ...

  4. knockoutjs -- if 绑定

    参考:http://knockoutjs.com/documentation/if-binding.html If 绑定用来控制一部分html标签是否生成在DOM树中(html标签有data-bind ...

  5. avalon2简单数据绑定(自定义属性绑定)

    <!DOCTYPE html> <html> <head> <title>项目</title> <meta charset=" ...

  6. KnockoutJS学习笔记10:KonckoutJS foreach绑定

      KnockoutJS foreach绑定用来处理数组,通常用来将一个数组绑定到一个列表或者table中.在foreach绑定中,我们可以使用if.with等嵌套绑定. 示例代码: <tabl ...

  7. [后端人员耍前端系列]KnockoutJs篇:使用WebApi+Bootstrap+KnockoutJs打造单页面程序

    一.前言 在前一个专题快速介绍了KnockoutJs相关知识点,也写了一些简单例子,希望通过这些例子大家可以快速入门KnockoutJs.为了让大家可以清楚地看到KnockoutJs在实际项目中的应用 ...

  8. KnockoutJS-模板绑定

    对于knockoutJS来讲,模板绑定和Mapping插件绑定是十分重要的功能,虽然模板绑定在我工作中用的及其少,但模板绑定的重要性不可忽视,在其他前端框架中,如Angular.Vue等等,模板存在的 ...

  9. KnockJs 绑定语法

    按照汤姆大叔的教程,学习了KnockJs相关知识,练习一下KnockoutJs的绑定语法. 相关的教程大家可以去看 汤姆大叔的博客. 练习代码下载 由于没有环境,代码直接用记事本写的,可能比较乱,仅作 ...

  10. Vue之指令和绑定

    一.v-once指令 <!DOCTYPE html> <html lang="zh"> <head> <meta charset=&quo ...

随机推荐

  1. Linux常用基本命令 (逐步添加)

    Linux jobs命令 fg , bg , jobs , & , ctrl + z都是跟系统任务有关 一.&命令 用在一个命令的最后,可以把这个命令放到后台执行 二.Ctrl + z ...

  2. 免费试用 | 多模 NoSQL 服务GeminiDB for Cassandra 全球首发

    PS:多模NoSQL服务GeminiDB重磅公测,免费体验,参与公测还有华为AI音响好礼相送~ 7月5日,华为云多模 NoSQL 服务GeminiDB for Cassandra正式对外定向邀测.华为 ...

  3. PHY6202 蓝牙4.0NRF51802

    PHY6202可以替代NRF51802/NRF51822的虽然PHY6202是蓝牙4.0,但它同时可是使用5.0的软件进行组网PHY6202 M0内核,封装:QFN48/32基本参数:ARM CORT ...

  4. Apple Developer swift教程学习笔记

    https://developer.apple.com/library/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson6. ...

  5. 基于leaflet的标绘功能(一)--可调整的圆

    标绘功能是指在电子地图上可以标注点.线.面.复杂多边形等图形.主要操作包括上图.调整(大小.方向.位置).网络存储等.根据具体的业务场景,也可以做到协同标绘等特色功能.其中,要求每个图形有若干关键点控 ...

  6. TypeScript - 类型声明、枚举、函数、接口

    目录  可定义的类型  类型声明  枚举  函数  接口 可定义的类型 以下所写的并不代表typescript的数据类型,而是在使用过程中可以用作定义的类型 number : 数值类型: string ...

  7. 几个非常适合练手的python爬虫项目,总有一个能搞定!

    前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:Python玩家 注意:如果你平时学Python有问题找不到人解答,可以 ...

  8. ARTS-S idea常用快捷键

    1.生成main方法 先输入p,再输入Ctrl+j,选psvm,回车. 2.生成System.out.println() 先输入s,再输入Ctrl+j,选sout,回车. 输入A.B.C.D形式的快捷 ...

  9. Appium之实操(了解配置项)

    使用Appium,测试对象APP的运行环境有两种:① 真实设备 如手机  ②模拟器 如夜神 连接真实设备: - 进入开发者模式,启动usb调试 - 在电脑上 执行adb命令  adb devices ...

  10. 【数据结构06】二叉平衡树(AVL树)

    目录 一.平衡二叉树定义 二.这货还是不是平衡二叉树? 三.平衡因子 四.如何保持平衡二叉树平衡? 五.平衡二叉树插入节点的四种情况 六.平衡二叉树操作的代码实现 七.AVL树总结 @ 一.平衡二叉树 ...