html或原生js是单一对应绑定的,原生js数据绑定

双向数据绑定是非常重要的特性 —— 将JS模型与HTML视图对应,能减少模板编译时间同时提高用户体验。我们将学习在不使用框架的情况下,使用原生JS实现双向绑定 —— 一种为Object.observe_(译注:现已废弃,作者写博客时为14年11月),另一种为覆盖get / set。PS: 第二种更好,详情请参阅底部的TL;DR(译注:too long;don't read. 直译为“太长,不想看”,意译为“简单粗暴来吧”)_。

1: Object.observe 和 DOM.onChange

Object.observe()是一种新特性,其在ES7中实现,但在最新的Chrome中已可用 —— 允许对JS对象进行响应式更新。简单说就是 —— 只要对象(的属性)发生变化就调用回调函数。

一般用法为:

log = console.log

user = {}

Object.observe(user, function(changes){

changes.forEach(function(change) {

user.fullName = user.firstName + " " + user.lastName;

});

});

user.firstName = 'Bill';

user.lastName = 'Clinton';

user.fullName // 'Bill Clinton'

复制代码

这很方便,且能实现响应式编程 —— 保证所有内容都是最新的。

如下:

//

user = {};

div = $("#foo");

Object.observe(user, function(changes){

changes.forEach(function(change) {

var fullName = (user.firstName || "") + " " + (user.lastName || "");

div.text(fullName);

});

});

user.firstName = 'Bill';

user.lastName = 'Clinton';

div.text() //Bill Clinton

复制代码

如上,我们自己实现了模型到数据的绑定!封装一下(译注:此处原文为Let’s DRY ourselves with a helper function. DRY即 don't repeat yourself):

//

function bindObjPropToDomElem(obj, property, domElem) {

Object.observe(obj, function(changes){

changes.forEach(function(change) {

$(domElem).text(obj[property]);

});

});

}

user = {};

bindObjPropToDomElem(user,'name',$("#foo"));

user.name = 'William'

$("#foo").text() //'William'

复制代码

换一种方式 —— 将DOM元素与JS值绑定起来。简单的方法是使用jQuery.change

//

$("#foo").val("");

function bindDomElemToObjProp(domElem, obj, propertyName) {

$(domElem).change(function() {

obj[propertyName] = $(domElem).val();

alert("user.name is now "+user.name);

});

}

user = {}

bindDomElemToObjProp($("#foo"), user, 'name');

//enter 'obama' into input

user.name //Obama.

复制代码

简直不要太方便,在实际开发时,可以将两者结合,通过函数来创建一个双向数据绑定:

function bindObjPropToDomElem(obj, property, domElem) {

Object.observe(obj, function(changes){

changes.forEach(function(change) {

$(domElem).text(obj[property]);

});

});

}

function bindDomElemToObjProp(obj, propertyName, domElem) {

$(domElem).change(function() {

obj[propertyName] = $(domElem).val();

console.log("obj is", obj);

});

}

function bindModelView(obj, property, domElem) {

bindObjPropToDomElem(obj, property, domElem)

bindDomElemToObjProp(obj, propertyName, domElem)

}

复制代码

注意:在双向绑定时,需正确进行DOM操作,因为不同的DOM元素(input,div,textarea,select)有不同的取值方式(text,val)。同时注意:双向数据绑定并不是必须的 —— “输出型”元素一般不需要视图到模型的绑定,而“输入型”元素一般不需要模型到视图的绑定。

下面为第二种方式:

2: 深入'get'和'set'属性

上面的解决方法并不完美。比如直接的修改并不会自动触发jQuery的“change”事件 —— 例如,直接通过代码对DOM进行修改,比如以下代码不起作用:

$("#foo").val('Putin')

user.name //still Obama. Oops.

复制代码

现在,我们来用一种更激进的方式实现 —— 重写getter和setter。因为我们不仅要监测变化,我们将重写JS最底层的功能,即get/setting变量的能力,所以不那么“安全”。后面我们将会看到,这种元编程的方式有多强大。

那么,如果我们可以重写get和set对象值的方法会怎么样呢?这也是数据绑定的实质。用 Object.defineProperty() 即可实现.

其实,以前就有已废弃且非标准实现方式,但通过Object.defineProperty的实现方式更好(最重要的是标准),如下所示:

user = {}

nameValue = 'Joe';

Object.defineProperty(user, 'name', {

get: function() { return nameValue },

set: function(newValue) { nameValue = newValue; },

configurable: true //to enable redefining the property later

});

user.name //Joe

user.name = 'Bob'

user.name //Bob

nameValue //Bob

复制代码

现在user.name是nameValue的别名。但可做的不仅仅是创建新的变量名 - 我们可以通过它来保证模型和视图的一致。如下:

//

Object.defineProperty(user, 'name', {

get: function() { return document.getElementById("foo").value },

set: function(newValue) { document.getElementById("foo").value = newValue; },

configurable: true //to enable redefining the property later

});

复制代码

user.name现在绑定到#foo元素。这种底层的方式非常简洁 —— 通过定义(或扩展)变量属性的get / set实现。由于实现非常简洁,因此可以根据情况轻松扩展/修改代码 —— 仅绑定或扩展get / set中的一个,比如绑定其他数据类型。

可封装如下:

function bindModelInput(obj, property, domElem) {

Object.defineProperty(obj, property, {

get: function() { return domElem.value; },

set: function(newValue) { domElem.value = newValue; },

configurable: true

});

}

复制代码

使用:

user = {};

inputElem = document.getElementById("foo");

bindModelInput(user,'name',inputElem);

user.name = "Joe";

alert("input value is now "+inputElem.value) //input is now 'Joe';

inputElem.value = 'Bob';

alert("user.name is now "+user.name) //model is now 'Bob';

复制代码

注意:上面的domElem.value只对input元素有效。(可在bindModelInput中扩展,对不同的DOM类型使用对应的方法来设置它的值)。

思考:

注意:上面的实现中,在某些场景下,视图可认为是符合SPOT (single point of truth )原则的,但该原则常常被忽视(因为双向数据绑定也就意味着等价)。然而,深究下去可能就会发现问题了,在实际开发中也会遇到。 —— 比如,当删除DOM元素时,关联的模型会自动注销么?答案是不会。bindModelInput函数在domElem元素上创建了一个闭包,使DOM元素常驻在内存中

—— 并保持模型与模型的绑定关系 —— 即使DOM元素被移除。即使视图被移除了,但模型依旧存在。反之一样 —— 若模型被移除了,视图依然能够正常显示。在某些刷新视图和模型无效的情况下,理解这些内部原理就能找到原因了。

(译注:SPOT简单翻译为“单点原则”,即引起变化最好的是由单一入口引起的,而不是由多个入口引起的,比如一个函数,其返回结果最好仅由参数决定,这样输入和输出才能一致,而不会由于其他变化导致用一个输入会出现不同的输出)

这种自己实现的数据绑定方法与Knockout或Angular等框架的数据绑定相比,有一些优点,例如:

理解:一旦掌握数据绑定的源码,不仅理解更深入,而且也能对其进行扩展和修改。

性能:不要将所有东西都绑定在一起,只绑定所需的,避免监测过多对象

避免锁定:若所用的框架不支持数据绑定,则自行实现的数据绑定更强大

缺点是由于不是真正的绑定(没有脏检查),有些情况会失败 —— 视图更新时不会触发模型中的数据,所以当试着同步视图中的两个DOM元素时将会失败。也就是说,将两个元素绑定到同一个模型上时,只有更新模型,则两个元素才会被正确更新。可以通过自定义一个更新函数来实现:

//

//

input1 = document.getElementById('input1')

input2 = document.getElementById('input2')

user = {}

Object.defineProperty(user, 'name', {

get: function() { return input1.value; },

set: function(newValue) { input1.value = newValue; input2.value = newValue; },

configurable: true

});

input1.onchange = function() { user.name = user.name } //sync both inputs.

复制代码

TL;DR:

当需要使用原生JS创建模型和视图的双向数据绑定时,如下:

function bindModelInput(obj, property, domElem) {

Object.defineProperty(obj, property, {

get: function() { return domElem.value; },

set: function(newValue) { domElem.value = newValue; },

configurable: true

});

}

//

user = {}

bindModelInput(user,'name',document.getElementById('foo')); //hey presto, we now have two-way data binding.

复制代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526933.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

et200sp模块接线手册_西门子PN/PN耦合器学习应用系列(1)-外观及接线

早在2017年我曾写过两篇文章介绍西门子PN/PN耦合器,文章链接如下:初识西门子PNPN耦合器(PN/PN Coupler);如何在博途(TIA Portal)环境下组态PNPN耦合器?当时PN/PN耦合器的固件版本还是V3.x。随着产品的升级,新版本的PN/…

textview加载html glide,TextView加载HTML,文字和图片

原文出处链接:《TextView加载HTML,文字和图片》工具类:public class ImageGetterUtils {public static MyImageGetter getImageGetter(Context context, TextView textView) {MyImageGetter myImageGetter new MyImageGetter(context, textV…

js 条码枪扫描_年会展台 精彩不断 | 沧田:从打印到扫描录入 国产品牌从未停止...

11月23日-25日,中国现代办公行业年会(以下简称COAA年会)在南昌召开。今年对于OA行业而言,国产品牌的崛起成为主要特征之一。以针式打印机起家的沧田,在本次展会中展示了多款重量级产品,涵盖了针式打印机、激光一体机、条码打印机、…

投后管理岗面试_2020天津水务招79人,管理岗+操作岗,专科起报

Hello大家好,我们今天的国企招聘主要说的是天津水务。天津水务的公告和去年相比晚了几个月,而且要求也变了一些——变成了校招(要求2020年应届生),虽然条件还是不高——大专起报。2点要求基本的条件就是要求&#xff1…

html的课设作业6,第七节课html标签元素属性作业-2019-9-6 作业

实例html>2019最新课程表table {/* border: 1px solid #000; *//* border-collapse: collapse; */width: 800px;margin: 2px auto;border-spacing: 0;/* box-shadow: 2px 2px 2px #888888; */}th,td {/* border: 1px solid #000; */text-align: center;padding: 10px;border…

微信没有回车键怎么换行_在东平相亲网加了心仪对方的微信,但是没有话题怎么办?...

最近很多东平单身小伙伴问红娘:加了对方微信不知道聊什么,觉得两个人没有共同话题,而且感觉该聊的都聊了,每天早晚安也发了,够热情了。还有的说不知道怎么回信息或者不知道跟ta说什么话题该怎么办?1其实这些…

中国重汽微服务管理_springcloud微服务架构实战:商家管理微服务设计

商家管理微服务设计商家管理微服务是一个独立的RESTAPI应用,这个应用通过接口服务对外提供商家信息管理、商家权限管理和菜单资源管理等方面的功能。商家管理微服务开发在merchant-restapi模块中实现,有关这一类型模块的依赖引用、配置、启动程序的设计等…

计算机自带游戏在哪里打开,电脑自带游戏选项在哪里打开

如果只是这个游戏有这个问题,就是软件有问题了,重装这游戏,如果有好几个软件都有这个问题,无疑是中毒了,用360彻底查杀。不行重装系统,装完后马上装360,再升级查杀。重装游戏。不行就-------那是…

html文字竖直书写,css 文字竖直居中的写法和图片垂直居中代码(图文)

界面上文章左右居中使用text-aligin:center,上下竖直居中的写法如下,图片垂直居中的代码文字、图片居中显示的方法.content{height: 40px;line-height: 40px;border:1px double #abc;}.myimg{/*非IE的主流浏览器识别的垂直居中的方法*/display: table-ce…

怎么判断到了月初_双春年与无春年怎么区分?2021年是寡妇年吗?

导读:双春年与无春年怎么区分?2021年是什么春年?就在昨天,我写了一篇关于寡妇年的文章,没想到大家热情高涨,关注度挺高的,还有的朋友私信问我这个双春年、有春年和无春年该怎么分,今…

微型计算机中的奔四指的是,2015云南省计算机等级考试二级理论考试试题及答案...

1、在微型计算机中,微处理器的主要功能是进行( D )A、算术运算 B、逻辑运算C、算术逻辑运算 D、算术逻辑运算及全机的控制2、下列各进制数中最小的数是( A )A、101001B B、520 C、2BH D、44D3、通常,在微机中标明的P4或奔腾4是指( D )A、产品型号 B、主频…

乐橙本地录像回放不了_乐橙智能锁来告诉你:你家门真的安全吗?

你家门锁真的安全吗?你以为家门反锁就没事了?最近,看到一则新闻:女主人反锁门后出门喝喜酒,回家后发现家中遭窃,现金、珠宝首饰等全部遗失。还有那些专门行窃的小偷,他们会先按下房间门铃&#…

swift html编辑器,SwiftUI 的可视化编辑工具

原标题:SwiftUI 的可视化编辑工具作者:希德,iOS 开发者,前“有经验的前端开发工程师”,就职于网易严选。正在写书《Thinkable SwiftUI》(严重拖稿中)Session 10185: https://developer.apple.com/videos/play/wwdc2020…

在百模大战中AI行业发展有何新趋势?

前言 在百模大战中,AI行业的发展正在经历前所未有的变革。这场竞争不仅推动了AI技术的快速发展,也揭示了AI行业的新趋势。这些趋势不仅影响着我们如何看待和使用AI,也预示着AI未来的发展方向。在这个快速发展的领域,了解这些新趋…

如何备份数据_如何通过归档、备份和灾难恢复实现多云数据保护

点击上方“蓝色字体”,选择 “设为星标”关键讯息,D1时间送达!为了提高业务连续性并更好地控制成本,企业将在2020年向IT专业人员施加压力,要求他们打破内部和外部基础设施之间以及公共云提供商离散环境之间的孤岛。为此…

清华大学计算机专业高中选课系统,【清华大学计算机实验教学中心】_清华大学计算机实验教学中心...

计算机实验教学中心面向全校所有专业本科生开课,每年开出计算机实验教学课超过7000人门,完成实验学时数逾750000.计算机学科是一门理论与实践结合得非常紧密的学科,因此实验教学中心的教学指导小组在教学实践中归纳出一套计算机学科特有的实验教学模式:除了独立设置的部分专题实…

机器人测钢卷直径_酒钢碳钢冷轧钢卷自动焊接机器人上线

10月18日消息,在酒钢集团宏兴股份公司碳钢薄板厂冷轧生产现场,一款白色自动焊接机器人上线作业。“这款机器人可进一步降低职工劳动强度,保证职工作业安全,最重要的是能够代替人工完成有害环境下的作业。”该厂电气责工刘世忠介绍…

html ace编辑器,Tiny-editor

Tiny-editor是和jsFiddle一样具有在线运行js功能的在线代码编辑器,基于Ace。Usage1.下载slidePagegit clone https://github.com/lipten/Tiny-editor.git2.引用相关文件3.引用js文件4.html结构//--html结构比较复杂,看下载后的editor.html比较完整5.初始…

树展示 移动端_百度移动端开始用网站品牌名代替网址显示

最近,有站长发现,百度移动端最近做了部分改版:移动端部分网站域名开始逐渐被网站相关名称代替,PC端还是用域名展示,卢松松博客网站域名也被替换成网站品牌名显示!点击添加图片描述(最多60个字)编…

html视频标签略缩图,JS可以截取video的标签视频缩略图吗?

这次给大家带来JS可以截取video的标签视频缩略图吗?,JS截取video的标签视频缩略图的注意事项有哪些,下面就是实战案例,一起来看一下。JavaScript截取video标签视频缩略图,前几天做个小项目以瀑布流加载MP4视频,一个页面差不多会加…