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 相关文章推荐
在JS中最常看到切最容易迷惑的语法(转)
Oct 29 Javascript
jQuery延迟加载图片插件Lazy Load使用指南
Mar 25 Javascript
JavaScript判断表单中多选框checkbox选中个数的方法
Aug 17 Javascript
解决JS请求服务器gbk文件乱码的问题
Oct 16 Javascript
Centos7 中 Node.js安装简单方法
Nov 02 Javascript
AngularJS动态加载模块和依赖的方法分析
Nov 08 Javascript
原生JS+HTML5实现的可调节写字板功能示例
Aug 30 Javascript
Angular6 用户自定义标签开发的实现方法
Jan 08 Javascript
微信小程序收货地址API兼容低版本解决方法
May 18 Javascript
elementUI select组件value值注意事项详解
May 29 Javascript
vue实现路由监听和参数监听
Oct 29 Javascript
关于uniApp editor微信滑动问题
Jan 15 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执行速度全攻略(下)
2006/10/09 PHP
PHPMYADMIN 简明安装教程 推荐
2010/03/07 PHP
php结合安卓客户端实现查询交互实例
2015/05/05 PHP
PHP中set error handler函数用法小结
2015/11/11 PHP
yii2.0整合阿里云oss删除单个文件的方法
2017/09/19 PHP
在TP5数据库中四个字段实现无限分类的示例
2019/10/18 PHP
Javascript判断对象是否相等实现代码
2013/03/18 Javascript
js为鼠标添加右击事件防止默认的右击菜单弹出
2013/07/29 Javascript
getAsDataURL在Firefox7.0下无法预览本地图片的解决方法
2013/11/15 Javascript
Seajs的学习笔记
2014/03/04 Javascript
JS使用cookie实现DIV提示框只显示一次的方法
2015/11/05 Javascript
Web前端开发工具——bower依赖包管理工具
2016/03/29 Javascript
工作中比较实用的JavaScript验证和数据处理的干货(经典)
2016/08/03 Javascript
js倒计时小实例(多次定时)
2016/12/08 Javascript
使用yeoman构建angular应用的方法
2017/08/14 Javascript
微信小程序 循环及嵌套循环的使用总结
2017/09/26 Javascript
JavaScript基于面向对象实现的猜拳游戏
2018/01/03 Javascript
在小程序中集成redux/immutable/thunk第三方库的方法
2018/08/12 Javascript
python用字典统计单词或汉字词个数示例
2014/04/22 Python
Python Web框架Flask中使用七牛云存储实例
2015/02/08 Python
Python实现删除文件中含“指定内容”的行示例
2017/06/09 Python
Python读写zip压缩文件的方法
2018/08/29 Python
Python多进程方式抓取基金网站内容的方法分析
2019/06/03 Python
在python中将list分段并保存为array类型的方法
2019/07/15 Python
numpy ndarray 按条件筛选数组,关联筛选的例子
2019/11/26 Python
Python利用逻辑回归分类实现模板
2020/02/15 Python
Python中logging日志的四个等级和使用
2020/11/17 Python
8款精美的CSS3表单设计(登录表单/下拉选择/按钮附演示及源码)
2013/02/04 HTML / CSS
Boda Skins皮衣官网:奢侈皮夹克,全球配送
2016/12/15 全球购物
美国打印机墨水和碳粉购物网站:QuikShip Toner
2018/08/29 全球购物
Rentalcars.com中国:世界上最大的在线汽车租赁服务
2019/08/22 全球购物
销售代表求职自荐信
2013/10/01 职场文书
住宅使用说明书
2014/05/09 职场文书
2016廉政教育学习心得体会
2016/01/25 职场文书
python文件目录操作之os模块
2021/05/08 Python
Pytest中skip skipif跳过用例详解
2021/06/30 Python