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 18 Javascript
JS中的构造函数详细解析
Mar 10 Javascript
jQuery插件jPaginate实现无刷新分页
May 04 Javascript
js+html5通过canvas指定开始和结束点绘制线条的方法
Jun 05 Javascript
javascript实现2016新年版日历
Jan 25 Javascript
微信小程序 定义全局数据、函数复用、模版等详细介绍
Oct 27 Javascript
Vue computed计算属性的使用方法
Jul 14 Javascript
小程序视频列表中视频的播放与停止的示例代码
Jul 20 Javascript
使用node.js实现微信小程序实时聊天功能
Aug 13 Javascript
微信小程序如何获取手机验证码
Nov 04 Javascript
JS基础之逻辑结构与循环操作示例
Jan 19 Javascript
解决vue项目 build之后资源文件找不到的问题
Sep 12 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中__FILE__、dirname与basename用法实例分析
2014/12/01 PHP
详解PHP用substr函数截取字符串中的某部分
2016/12/03 PHP
php获取今日开始时间和结束时间的方法
2017/02/27 PHP
一款js和css代码压缩工具[附JAVA环境配置方法]
2010/04/16 Javascript
js Form.elements[i]的使用实例
2011/11/13 Javascript
给页面渲染时间加速 干掉Dom Level 0 Event
2012/12/19 Javascript
『JavaScript』限制Input只能输入数字实现思路及代码
2013/04/22 Javascript
jquery中get和post的简单实例
2014/02/04 Javascript
jQuery源码解读之removeClass()方法分析
2015/02/20 Javascript
javascript:void(0)点击登录没反应怎么解决
2015/11/13 Javascript
js实现字符串和数组之间相互转换操作
2016/01/12 Javascript
再次谈论Javascript中的this
2016/06/23 Javascript
解析如何利用iframe标签以及js制作时钟
2016/12/08 Javascript
详解jQuery停止动画——stop()方法的使用
2016/12/14 Javascript
原生js实现返回顶部缓冲效果
2017/01/18 Javascript
vue-router 手势滑动触发返回功能
2018/09/30 Javascript
小程序实现日历左右滑动效果
2019/10/21 Javascript
javascript如何使用函数random来实现课堂随机点名方法详解
2020/07/28 Javascript
浅析JavaScript预编译和暗示全局变量
2020/09/03 Javascript
用Python实现一个简单的线程池
2015/04/07 Python
Python验证码识别的方法
2015/07/10 Python
八大排序算法的Python实现
2021/01/28 Python
使用Python实现博客上进行自动翻页
2017/08/23 Python
Python基于lxml模块解析html获取页面内所有叶子节点xpath路径功能示例
2018/05/16 Python
Python直接赋值、浅拷贝与深度拷贝实例分析
2019/06/18 Python
python实现异常信息堆栈输出到日志文件
2019/12/26 Python
Selenium自动化测试工具使用方法汇总
2020/06/12 Python
web字体加载方案优化小结
2019/11/29 HTML / CSS
写好自荐信的要点
2013/11/06 职场文书
房屋过户委托书范本
2014/10/07 职场文书
民主生活会批评与自我批评总结
2014/10/17 职场文书
售票员岗位职责
2015/02/15 职场文书
城管个人总结
2015/02/28 职场文书
2015年读书月活动总结
2015/03/26 职场文书
你有一份《诚信考试承诺书》待领取
2019/11/13 职场文书
html5移动端禁止长按图片保存的实现
2021/04/20 HTML / CSS