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 相关文章推荐
jQuery学习总结之元素的相对定位和选择器(持续更新)
Apr 26 Javascript
在JavaScript中监听IME键盘输入事件
May 29 Javascript
推荐11款jQuery开发的复选框和单选框美化插件
Aug 02 Javascript
js数组转json并在后台对其解析具体实现
Nov 20 Javascript
基于JQuery实现的图片自动进行缩放和裁剪处理
Jan 31 Javascript
jQuery判断指定id的对象是否存在的方法
May 22 Javascript
jquery对象访问是什么及使用方法介绍
May 03 Javascript
封装获取dom元素的简单实例
Jul 08 Javascript
javascript匀速动画和缓冲动画详解
Oct 20 Javascript
解决vue单页面应用中动态修改title问题
Jun 09 Javascript
原生JavaScript创建不可变对象的方法简单示例
May 07 Javascript
Ajax 的初步实现(使用vscode+node.js+express框架)
Jun 18 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(视频)Http下载
2006/12/12 PHP
mysql4.1以上版本连接时出现Client does not support authentication protocol问题解决办法
2007/03/15 PHP
php array_map array_multisort 高效处理多维数组排序
2009/06/11 PHP
记录mysql性能查询过程的使用方法
2013/05/02 PHP
PHP回调函数与匿名函数实例详解
2017/08/16 PHP
Yii2.0框架实现带分页的多条件搜索功能示例
2019/02/20 PHP
javascrip客户端验证文件大小及文件类型并重置上传
2011/01/12 Javascript
最新28个很棒的jQuery 教程
2011/05/28 Javascript
jquery 获取标签名(tagName)示例代码
2013/07/11 Javascript
JS读取XML文件示例代码
2013/11/15 Javascript
js判断undefined类型示例代码
2014/02/10 Javascript
node.js中的buffer.Buffer.isEncoding方法使用说明
2014/12/14 Javascript
jQuery中$.click()无效问题分析
2015/01/29 Javascript
javascript实现复选框超过限制即弹出警告框的方法
2015/02/25 Javascript
jquery移动点击的项目到列表最顶端的方法
2015/06/24 Javascript
jQuery实现从身份证号中获取出生日期和性别的方法分析
2016/02/25 Javascript
jQuery实时显示鼠标指针位置和键盘ASCII码
2016/03/28 Javascript
jQuery 获取屏幕高度、宽度的简单实现案例
2016/05/17 Javascript
超实用的javascript时间处理总结
2016/08/16 Javascript
js内置对象处理_打印学生成绩单的简单实现
2016/09/24 Javascript
js实现跟随鼠标移动的小球
2019/08/26 Javascript
Typescript3.9 常用新特性一览(推荐)
2020/05/14 Javascript
[03:16]DOTA2完美大师赛主赛事首日集锦
2017/11/23 DOTA
[01:15:00]LGD vs Mineski Supermajor 胜者组 BO3 第一场 6.5
2018/06/06 DOTA
python基于右递归解决八皇后问题的方法
2015/05/25 Python
python解析含有重复key的json方法
2019/01/22 Python
Python实现html转换为pdf报告(生成pdf报告)功能示例
2019/05/04 Python
python Matplotlib底图中鼠标滑过显示隐藏内容的实例代码
2019/07/31 Python
前端H5 Video常见使用场景简介
2020/08/21 HTML / CSS
墨西哥运动服饰和鞋网上商店:Netshoes墨西哥
2016/07/28 全球购物
Paradigit比利时电脑卖场:购买笔记本、电脑、平板和外围设备
2016/11/28 全球购物
数控技术专业推荐信
2013/11/01 职场文书
面试后的感谢信范文
2014/02/01 职场文书
师德师风整改措施
2014/10/24 职场文书
2016道德模范先进事迹材料
2016/02/26 职场文书
一次线上mongo慢查询问题排查处理记录
2022/03/18 MongoDB