js项目中双向数据绑定的简单实现方法

目录
  • 前言
  • 发布订阅者模式
    • 结果
    • 调用
  • 总结

前言

双向数据绑定 指的是当对象的属性发生变化时能够同时改变对应的UI,反之亦然。换句话说,如果我们有一个user对象,这个对象有一个name属性,无论何时你对user.name设置了一个新值,UI也会展示这个新的值。同样的,如果UI包含一个用于数据用户名字的输入框,输入一个新值也会导致user对象的name属性发生相应的改变。

许多流行的javascript框架,像Ember.js,Angular.js或者KnockoutJS都会把双向数据绑定作为其中的主要特性来宣传。这并不意味着从头开始实现它很难,也不意味着当我们需要这种功能的时候,使用这些框架是我们唯一的选择。内部的潜在思想事实上是相当基础的,实现它可以归纳为以下三点:

  • 我们需要一种方式确定哪个UI元素绑定在哪个属性上。
  • 我们需要监控属性和UI的变化
  • 我们需要把所有绑定的对象和UI元素的变化传播出去。

发布订阅者模式

发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。

订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。

结果

调用

html  调用 端 绑定 data-bind-phone="name"

  <ul>  

     <li class="block-phone fix bd-bottom">  

          <label for="J_verificationPhone" data-bind-phone="tishi"><span>手机号</span></label>  

          <input  class="fix1" id="J_verificationPhone" data-bind-phone="name" name="phone"  type="text" />  

          <button class="right J_clickTime"  type="button">

            <span class="award-messages-btn2 J_messagesBtn1">获取验证码</span>

            <span class="award-messages-btn2 J_messagesBtn2 none"><i>60</i>s后重发</span>

          </button>

     </li>  

     <li class="block-verification fix">  

          <label for="J_verificationCode"><span>验证码</span></label>  

          <input class="fix1" data-bind-code="tishi" id="J_verificationCode" data-bind-phone="name" name="verification-code" class="" type="" />  

     </li> 

  </ul>  

js 调用 看下面代码注释

/**
 * function verficationCallback 回调方法
 * [$btn1 description]
 * data-bind-phone="name"
 * @ message {[type]}   发生变化的字段phone
 * @ prop_name {[type]}  字段的value  name
 * @ target {[type]}      目标jsdom对象;
 * @ targetValue {[type]}  目标jsdom对象的value
 */// 监听回调函数,函数会拿到targetvalue 的值, target js dom对象,便于对变化的字段进行操作!!!
var User= require('../../entry/module/twoWayAudio.js');
var phone = new User('phone',verficationCallback);
 function verficationCallback(message,prop_name,target,targetValue){
}

引入的源代码 twoWayAudio

function DataBinder(object_id,verficationCallback){  
// 创建一个简单的pubSub对象
var pubSub = {
callbacks: {},
on: function(msg,callback) {
this.callbacks[msg] = this.callbacks[msg] || [];
this.callbacks[msg].push(callback);
},
publish: function(msg) {
\

this.callbacks[msg] = this.callbacks[msg] || [];
for (var i = 0,len = this.callbacks[msg].length; i < len; i++) {
this.callbacks[msg][i].apply(this,arguments);
};
}
},

data_attr = "data-bind-" + object_id,
message   = object_id + ":change",
changeHandler = function(event) {
var target = event.target || event.srcElement, // IE8兼容
prop_name = target.getAttribute(data_attr);
if (prop_name && prop_name !== "") {
if(verficationCallback){
var targetValue = target.value;
verficationCallback (message,prop_name,target,targetValue);
}
pubSub.publish(message,prop_name,target.value);
}
};

// 监听事件变化,并代理到pubSub
if (document.addEventListener) {
document.addEventListener("keyup",changeHandler,false);
} else{
// IE8使用attachEvent而不是addEventListenter
document.attachEvent("onkeyup",changeHandler);
};

// pubSub将变化传播到所有绑定元素
pubSub.on(message,function(event,prop_name,new_val){
var elements = document.querySelectorAll("[" + data_attr + "=" +prop_name + "]"),
tag_name;
for (var i = 0,len = elements.length; i < len; i++) {
tag_name = elements[i].tagName.toLowerCase();
if (tag_name === "input" || tag_name === "textarea" || tag_name === "select") {
elements[i].value = new_val;

} else{
elements[i].innerHTML = new_val;
};
};
})
return pubSub;
}

function User(uid,verficationCallback) {  
var binder = new DataBinder(uid,verficationCallback),
  user   = {
  attribute : {},
  // 属性设置器使用数据绑定器pubSub来发布
  set : function(attr_name,val) {
  this.attribute[attr_name] = val;
  binder.publish(uid + ":change",attr_name,val,this);
  },
  get : function(attr_name) {
  return this.attribute[attr_name];
  },
  _binder : binder
  };

binder.on(uid + ":change",function(event,attr_name,new_val,initiator) {
if (initiator !== user) {
user.set(attr_name,new_val);
}
});
return user;
}
module.exports = User;
// phone.set( "name", "lwl" );  
// phone.set( "tishi", "提示" );  

替代解决方案

上面只是在掩饰双向数据绑定,其实这种需求可以更简单的实现 嘿嘿

 $('.block-phone #phone')[0].oninput=function(){
 console.log($(this))
}

总结

到此这篇关于js项目中双向数据绑定的简单实现方法的文章就介绍到这了,更多相关js双向数据绑定实现内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • javascript实现数据双向绑定的三种方式小结

    前端数据的双向绑定方法 前端的视图层和数据层有时需要实现双向绑定(two-way-binding),例如mvvm框架,数据驱动视图,视图状态机等,研究了几个目前主流的数据双向绑定框架,总结了下.目前实现数据双向绑定主要有以下三种. 1.手动绑定 比较老的实现方式,有点像观察者编程模式,主要思路是通过在数据对象上定义get和set方法(当然还有其它方法),调用时手动调用get或set数据,改变数据后出发UI层的渲染操作:以视图驱动数据变化的场景主要应用与input.select.textarea等

  • JavaScript中双向数据绑定详解

    双向数据绑定指的是将对象属性变化绑定到UI,或者反之.换句话说,如果我们有一个拥有name属性的user对象,当我们给user.name赋予一个新值是UI也会相应的显示新的名字.同样的,如果UI包括了一个输入字段用来输入用户名,输入一个新的值会导致user对象中的那么属性发生变化. 许多流行的客户端JavaScript框架例如Ember.js,AngularJS以及KnockoutJS都将双向数据绑定作为自己的头号特性.但是这并不意味着从零开始实现双向数据绑定就很困难,同样的当我们需要双向数据绑

  • 轻松实现javascript数据双向绑定

    双向数据绑定指的是当对象的属性发生变化时能够同时改变对应的UI,反之亦然.换句话说,如果我们有一个user对象,这个对象有一个name属性,无论何时你对user.name设置了一个新值,UI也会展示这个新的值.同样的,如果UI包含一个用于数据用户名字的输入框,输入一个新值也会导致user对象的name属性发生相应的改变. 许多流行的javascript框架,像Ember.js,Angular.js或者KnockoutJS都会把双向数据绑定作为其中的主要特性来宣传.这并不意味着从头开始实现它很难,

  • 实现非常简单的js双向数据绑定

    双向数据绑定指的就是,绑定对象属性的改变到用户界面的变化的能力,反之亦然.换种说法,如果我们有一个user对象和一个name属性,一旦我们赋了一个新值给user.name,在UI上就会显示新的姓名了.同样地,如果UI包含了一个输入用户姓名的输入框,输入一个新值就应该会使user对象的name属性做出相应的改变. 很多热门的JS框架客户端如Ember.js,Angular.js 或者KnockoutJS ,都在最新特性上刊登了双向数据绑定.这并不意味着从零实现它很难,也不是说需要这些功能的时候,采

  • JS原生数据双向绑定实现代码

    代码如下: <span style="font-family:Times New Roman;font-size:14px;" deep="7"><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Demo</title> <script> fu

  • js实现视图和数据双向绑定的方法分析

    本文实例讲述了js实现视图和数据双向绑定的方法.分享给大家供大家参考,具体如下: 前言 视图和数据绑定,使视图和逻辑层分离,使视图层变为数据驱动是前端的一大进步.由此诞生了mvvm类的前端框架,大大提升了开发的效率. 那么在使用旧有的项目中,如何使用更加先进的设计模式来替换掉大量的面向过程编程. 各大框架对于数据绑定的实现都有各自的方式,这里不做深入只是简单介绍一下. Vue使用了es5  Object.defineProperty的特性来实现对数据读取和设置的监听,是一种元编程的方式.个人感觉

  • vue.js数据绑定的方法(单向、双向和一次性绑定)

    这两天学习了vue.js数据绑定这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记. 前言 感觉 vue 的很多方面的内容,都参考了 angular 的东西,数据绑定方面,更是赤裸裸的"抄袭".对照来看,更有助于我们学习和理解框架本身透露出来的思想,而非框架本身. 一.单向绑定 (一)Mustache 语法,双大括号 {{}}(html 内字符串绑定) <div id="app"> <p>{{text}}</p> <

  • JS数据双向绑定原理与用法实例分析

    本文实例讲述了JS数据双向绑定原理与用法.分享给大家供大家参考,具体如下: 通常在前端开发过程中,经常遇到需要绑定两个甚至多个元素之间的值,比如将input的值绑定到一个h1上,改变input的值,h1的文字也自动更新. <h1 id="title">Hello</h1> <input type="text" id="a" /> 首先是在界面上更改input的值,需要监听input的"input&qu

  • js项目中双向数据绑定的简单实现方法

    目录 前言 发布订阅者模式 结果 调用 总结 前言 双向数据绑定 指的是当对象的属性发生变化时能够同时改变对应的UI,反之亦然.换句话说,如果我们有一个user对象,这个对象有一个name属性,无论何时你对user.name设置了一个新值,UI也会展示这个新的值.同样的,如果UI包含一个用于数据用户名字的输入框,输入一个新值也会导致user对象的name属性发生相应的改变. 许多流行的javascript框架,像Ember.js,Angular.js或者KnockoutJS都会把双向数据绑定作为

  • MVVMLight项目之双向数据绑定

    目录 第一步:先写一个Model,里面包含我们需要的数据信息 第二步:写一个ViewModel 第三步:在ViewModelLocator中注册我们写好的ViewModel: 第四步:编写View(注意标红的代码) MVVM和MVVMLight框架介绍及在项目中的使用详解 MVVMLight项目Model View结构及全局视图模型注入器 前篇我们已经了解了MVVM的框架结构和运行原理.这里我们来看一下伟大的双向数据绑定. 说到双向绑定,大家比较熟悉的应该就是AngularJS了,几乎所有的An

  • Vue.js + Nuxt.js 项目中使用 Vee-validate 表单校验

    vee-validate 是为 Vue.js 量身打造的表单校验框架,允许您校验输入的内容并显示对应的错误提示信息.它内置了很多常见的校验规则,可以组合使用多种校验规则,大部分场景只需要配置就能实现开箱即用,还支持自定义正则表达式.而且支持 40 多种语言,对本地化.多语言支持非常友好. 国内饿了么团队开源项目 Element UI 就用到了 vee-validate . vee-validate 官网:https://baianat.github.io/vee-validate/ 1. 安装

  • vue项目中在外部js文件中直接调用vue实例的方法比如说this

    一般我们都是在main.js中引入vue,然后在vue文件中直接使用this(this指向的是vue实例),但是在实际开发中,我们往往会引入外部的js文件使用this,这个this就会指向window,并不是我们期待的vue实例,那么就需要重新引入vue文件(import Vue from 'vue'),这样很麻烦.在目前项目中我使用的方法是mian.js导出vue实例,然后在需要使用的js中引入. 步骤一:main.js导出vue实例 var vue = new Vue({ el: '#app

  • Vue.js项目中管理每个页面的头部标签的两种方法

    在 Vue SPA 应用中,如果想要修改 HTML 的头部标签,如页面的 title ,我们只能去修改 index.html 模板文件,但是这个是全局的修改,如何为每个页面都设置不一样的 title 呢?下面介绍两种方法. 使用router.meta 在路由里面配置每个路由的地址: routes: [ { /* (首页)默认路由地址 */ path: '/', name: 'Entrance', component: Entrance, meta: { title: '首页入口' } }, {

  • JS项目中对本地存储进行二次的封装的实现

    目录 前言 定义恒量的键名 下层实现 上层调用 总结 前言 平时在开发的中,发现身边同事在使用localStorage和sessionStorage的时候,喜欢在代码里面直接调用,举个的栗子: function login() { //...请求 const userInfo = {userId: 123, userName: '张三'} sessionStorage.setItem('userInfo', JSON.stringify(userInfo)) } function getUser

  • 深入了解Vue中双向数据绑定原理

    目录 数据的变化反应到视图 命令式操作视图 声明式操作视图 小结 视图的变化反应到数据 现存的问题 数据的变化反应到视图 前面我们了解到数据劫持之后,我们可以在数据发生修改之后做任何我们想要做的事情,操作视图当然也是OK的 命令式操作视图 目标:我们通过原始的操作dom的方式让每一次的name的最新值都能显示到p元素内部 <div id="app"> <p></p> </div> <script> let data = { n

  • vue项目中引入noVNC远程桌面的方法

    1 .首先,先简单介绍一下概念. VNCServer 是一个为了满足分布式用户共享服务器资源,而在服务器开启的一项服务,对应的客户端软件有图形化客户端 VNCViewer,而 noVNC 则是 HTML5 VNC 客户端,它采用 HTML 5 WebSocket, Canvas 和 JavaScript 实现. noVNC 被普遍用在各大云计算.虚拟机控制面板中.noVNC 采用 WebSockets 实现,但是当前大多 VNC 服务器不支持 WebSocket,所以 noVNC 不能直连 VN

  • vue多页面项目中路由使用history模式的方法

    前言 之前写了一个vue项目中需要添加一个打印的页面,需要使用多页面的模式进行开发,vue-cli3出初始化的项目配置多页面还是很容易的,但是发现print.html没有办法配置history模式的路由,一旦使用history模式的路由.写了一个简单的demo在网上寻求帮助没有能解决问题,后来没有办法只能使用hash模式完整项目了. 如何解决 有一天看webpack文档的时候,突然看到了historyApiFallback配置项,一瞬间感觉找到方法了.下班后回家就下载下之前的项目折腾了. 之前的

  • jQuery NProgress.js加载进度插件的简单使用方法

    NProgress.js 说明: NProgress是基于jquery的,且版本要 >1.8 下载地址: https://github.com/rstacruz/nprogress API: NProgress.start() - 启动进度条 NProgress.set(0.4) - 将进度设置到具体的百分比位置 NProgress.inc() - 少量增加进度 NProgress.done() - 将进度条标为完成状态 使用步骤: 1. 引入 <link rel="styleshe

随机推荐