vue用Object.defineProperty手写一个简单的双向绑定的示例


Posted in Javascript onJuly 09, 2018

前言 上次写了一个Object.defineProperty() 不详解,文末说要写用它来写个双向绑定。说话算话,说来就来

前文链接 Object.defineProperty() 不详解

先看最后效果

vue用Object.defineProperty手写一个简单的双向绑定的示例

model演示.gif

什么是双向绑定?

1.当一个对象(或变量)的属性改变,那么调用这个属性的地方显示也应该改变,模型到视图(model => view)

2.当调用属性的这个地方改变了这个属性(通常是一个表单元素),那么这个对象(或变量)的属性也会改为最新的值 ,即视图到模型(view => model)

我们怎么知道对象的属性变了?

上文说到,Object.defineProperty 设置对象属性的描述字段里面有两个属性 set (设置属性时被调用)和get(获取属性时被调用),只说不练,你再讲什么?眼见为实好吗?OK ,上代码

var user = {};
var defaultName = "狂奔的蜗牛";
Object.defineProperty(user,"name",{
  get:function(){
    console.log("你是不是来获取值啦");
    return defaultName;
  },
  set:function(value){
    console.log("你是不是来设置值啦");
    defaultName = value;
  }
})

console.log(user.name);
user.name = "狂奔的萝卜";
console.log(user.name);

vue用Object.defineProperty手写一个简单的双向绑定的示例

get和set存取时被调用

如上图所示 每当我获取user.name属性时,get方法被调用,get 方法对应的函数被执行,输出 你是不是来获取值啦;每当我设置user.name属性时,set方法对应的函数被执行,输出 你是不是来设置值啦 ; 是的,我们监控到了代码对user.name属性的存取。

说明 假设id="model" 的元素的 value 是user.name的值,既然我们可以在改变属性的执行日志输出(console.log("你是不是来设置值啦");),那么,我们在设置值的时候给id="model" 的元素设置下新值,不就实现了从模型到视图?!!,说干就干

模型到视图(model => view)的同步

说明 假设id="model" 的元素的 value 是user.name的值,既然我们可以在改变属性的执行日志输出(console.log("你是不是来设置值啦");),那么,我们在设置值的时候给id="model" 的元素设置下新值,不就实现了从模型到视图?!!,说干就干

<body>
  手写一个简单双向绑定<br/>
  <input type="text" id="model"><br/>
  <div id="modelText"></div>
</body>
<script>
var user = {};
var defaultName = "狂奔的蜗牛";

document.querySelector("#model").value = defaultName;
document.querySelector("#modelText").textContent = defaultName;

//定义属性 监控改变
Object.defineProperty(user,"name",{
  get:function(){
    console.log("你是不是来获取值啦");
    return defaultName;
  },
  set:function(newValue){
    console.log("设置新值");
    defaultName = newValue;
    console.log("实现 模型 => 视图");
    document.querySelector("#model").value = newValue;
    document.querySelector("#modelText").textContent = newValue;
  }
})

console.log("2s 后改变值");

setTimeout(() => {
  //改变值
  user.name = "狂奔的萝卜";
}, 2000);
</script>

vue用Object.defineProperty手写一个简单的双向绑定的示例

模型到视图(model => view)的同步

视图到模型(view => model)的同步

问: 我们能捕捉到view对值更改吗?

答:可以!! id="model" 的input元素的 value 是user.name的值,填充在这个文本框里面,文本框有个“ keyup” 事件,当我们在文本框中输入文字的时候,文本框的值会跟着改变,并且会连续触发keyup事件,那么我们只需要监听这个事件,是不是就可以捕捉到view对值的更改了??既然文本框的值会跟着改变,我们获取最新的值再把新值更新到user.name属性,不就实现了视图到模型(view => model)的同步?没代码说个啥

<body>
  手写一个简单双向绑定<br/>
  <input type="text" id="model"><br/>
  <div id="modelText"></div>
</body>
<script>
  var user = {};
  var defaultName = "狂奔的蜗牛";
  var model = document.querySelector("#model");
  var modelText = document.querySelector("#modelText");

  model.value = defaultName;
  modelText.textContent = defaultName;

  //定义属性 监控改变
  Object.defineProperty(user,"name",{
    get:function(){
      console.log("你是不是来获取值啦");
      return defaultName;
    },
    set:function(newValue){
      console.log("设置新值");
      defaultName = newValue;
      model.value = newValue;
      modelText.textContent = newValue;
    }
  })

  model.addEventListener("keyup", function () {
    user.name = this.value;
    console.log("实现 视图 => 模型");
  }, false)
</script>

vue用Object.defineProperty手写一个简单的双向绑定的示例

view2model.gif

【最终源码】

在上述代码的基础上,加入了 用户输入中文的判断(用户输入中文时,频繁触发 keyup事件,但实际上输入并没有结束。)

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>双向绑定</title>
</head>
<body>
  手写一个简单双向绑定<br/>
  <input type="text" id="model"><br/>
  <div id="modelText"></div>
</body>
<script>
  var model = document.querySelector("#model");
  var modelText = document.querySelector("#modelText");
  var defaultName = "defaultName";
  var userInfo = {}
  model.value = defaultName;
  Object.defineProperty(userInfo, "name", {
    get: function () {
      return defaultName;
    },
    set: function (value) {
      defaultName = value;
      model.value = value;
      console.log("-----value");
      console.log(value);
      modelText.textContent = value;
    }
  })

  userInfo.name = "new value";
  var isEnd = true;

  model.addEventListener("keyup", function () {
    if (isEnd) {
      userInfo.name = this.value;
    }
  }, false)
  //加入监听中文输入事件
  model.addEventListener("compositionstart", function () {
    console.log("开始输入中文");
    isEnd = false;
  })
  model.addEventListener("compositionend", function () {
    isEnd = true;
    console.log("结束输入中文");
  })
</script>
</html>

【完结】

Object.defineProperty 可以做很多好玩儿的,自己慢慢探索哈~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
来自chinaz的ajax获取评论代码
May 03 Javascript
Javascript 圆角div的实现代码
Oct 15 Javascript
jQuery入门知识简介
Mar 04 Javascript
JavaScript数组函数unshift、shift、pop、push使用实例
Aug 27 Javascript
jquery滚动特效集锦
Jun 03 Javascript
使用Bootstrap typeahead插件实现搜索框自动补全的方法
Jul 07 Javascript
angular route中使用resolve在uglify压缩后问题解决
Sep 21 Javascript
详解从零搭建 vue2 vue-router2 webpack3 工程
Nov 22 Javascript
实例讲解javascript实现异步图片上传方法
Dec 05 Javascript
JS基于递归实现网页版计算器的方法分析
Dec 20 Javascript
JavaScript的Object.defineProperty详解
Jul 09 Javascript
Javascript 之封装(Package)
Sep 14 Javascript
js中Object.defineProperty()方法的不详解
Jul 09 #Javascript
微信小程序实现团购或秒杀批量倒计时
Nov 01 #Javascript
微信小程序实现倒计时补零功能
Jul 09 #Javascript
Angular6中使用Swiper的方法示例
Jul 09 #Javascript
微信小程序实现自定义picker选择器弹窗内容
May 26 #Javascript
微信小程序实现漂亮的弹窗效果
May 26 #Javascript
Angular通过指令动态添加组件问题
Jul 09 #Javascript
You might like
PHP判断搜索引擎蜘蛛并自动记忆到文件的代码
2012/02/04 PHP
php绘图之加载外部图片的方法
2015/01/24 PHP
php实现仿写CodeIgniter的购物车类
2015/07/29 PHP
PHP实现多关键字加亮功能
2016/10/21 PHP
PHP解压ZIP文件到指定文件夹的方法
2016/11/17 PHP
动态创建的表格单元格中的事件实现代码
2008/12/30 Javascript
封装的jquery翻页滚动(示例代码)
2013/11/18 Javascript
浅析JavaScript中的同名标识符优先级
2013/12/06 Javascript
JavaScript设计模式之外观模式实例
2014/10/10 Javascript
详解堆的javascript实现方法
2016/11/29 Javascript
bootstrap Validator 模态框、jsp、表单验证 Ajax提交功能
2017/02/17 Javascript
搭建简单的nodejs http服务器详解
2017/03/09 NodeJs
深入理解vue2.0路由如何配置问题
2017/07/18 Javascript
基于jquery的on和click的区别详解
2018/01/15 jQuery
微信小程序适配iphoneX的实现方法
2018/09/18 Javascript
原生JS实现的跳一跳小游戏完整实例
2019/01/27 Javascript
小程序页面动态配置实现方法
2019/02/05 Javascript
Vue组件系列开发之模态框
2019/04/18 Javascript
JS常用排序方法实例代码解析
2020/03/03 Javascript
Javascript基于OOP实实现探测器功能代码实例
2020/08/26 Javascript
[32:39]完美世界DOTA2联赛循环赛 Forest vs Inki BO2第一场 11.04
2020/11/04 DOTA
浅析Python中的getattr(),setattr(),delattr(),hasattr()
2016/06/14 Python
使用Turtle画正螺旋线的方法
2017/09/22 Python
python如何将多个PDF进行合并
2019/08/13 Python
浅谈keras的深度模型训练过程及结果记录方式
2020/01/24 Python
tensorflow获取预训练模型某层参数并赋值到当前网络指定层方式
2020/01/24 Python
Opencv求取连通区域重心实例
2020/06/04 Python
keras 读取多标签图像数据方式
2020/06/12 Python
Python实现Keras搭建神经网络训练分类模型教程
2020/06/12 Python
使用HTML5技术开发一个属于自己的超酷颜色选择器
2013/09/22 HTML / CSS
初三化学教学反思
2014/01/23 职场文书
企业职业病防治方案
2014/05/29 职场文书
先进党员事迹材料
2014/12/24 职场文书
试用期工作表现自我评价
2015/03/06 职场文书
严以用权学习心得体会
2016/01/12 职场文书
零基础学java之循环语句的使用
2022/04/10 Java/Android