Lazy loaded image
前端
🗒️Object.defineProperty妙用——Vue2数据双向绑定的原理
字数 822阅读时长≈ 3 分钟
2019-9-16
2025-4-4
2
type
status
date
slug
summary
tags
category
icon
password
上次编辑时间
Apr 4, 2025 02:15 PM
最近看了一下 Vue.js 实现相关的文章,了解到了其数据劫持(双向绑定)的原理,使用到了Object.defineProperty这个方法,花了点时间,自己尝试着做了一个小 demo。 MDN 解释:Object.defineProperty方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
// 使用Object.defineProperty() // 接收的第一个参数为对象,第二个参数为属性名,第三个参数为配置对象 let obj = {} Object.defineProperty(obj, 'name', { enumerable: true, // 是否可枚举,默认值 false,如果为false,在for in遍历里不会展示属性 writable: true, // 是否可写,默认值 false,如果为false的话,给name赋值,不会生效 configurable: true, // 是否可配置(是否可删除),默认值 false value: 'huqing' // name对应的值 }) // 上面的写法其实和下面的写法是一样的 let obj = {} obj.name = 'huqing'
既然写法一样,为何要大费周折去写那么多呢,其实重点在其getset方法
// 注意!当使用get set时,不能写value和writable let obj = {} let str Object.defineProperty(obj, 'name', { enumerable: true, configurable: true, get() { // 读,当我们读取属性时,会执行get方法 return str // 当我们obj.name进行读取时,会返回'huqing' }, set(newValue) { // 写,当我们写入属性时,会执行set方法 str = newValue } }) obj.name = 'huqing' // 写入 console.log(obj.name) // 'huqing' // 读取
从这可以看出,我们可以在 get、set 函数中,写出对应的业务逻辑,做一系列我们想做的事情
话不多说,开始做 demo
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>数据双向绑定</title> </head> <body> <input id="input" value=""> <script> let el = document.getElementById('input') let obj = { // 1. 创建一个对象 name: "" } function oberseve(obj) { // 2. 对对象进行观察 if (typeof obj !== 'object') return // 2.1 判断参数是否为对象 for (let key in obj) { // 2.2 对对象进行遍历,目的是为了把每个属性都设置get/set defineReactive(obj, key, obj[key]) if (typeof obj[key] === 'object') { oberseve(obj[key]) // 2.3 obj[key]有可能还是一个对象,需要递归,给它的子属性也进行设置 } } } function defineReactive(target, property, value) { // 3. 使用Object.defineProperty Object.defineProperty(target, property, { get () { el.value = value // 3.1 当读取时,把值赋值给input框 return value }, set (newVal) { el.value = newVal // 3.2 当设置时,把赋值给input框 value = newVal } }) } oberseve(obj) // 4.执行该函数,对obj对象里的属性进行设置get/set el.addEventListener('input', function () { // 5.给输入框绑定input事件 obj.name = this.value // 6.当输入框输入内容时,会把输入框的内容赋值给obj.name,触发obj.name的set方法 }) </script> </body> </html>
当我们在输入框输入之后,在控制台输入 obj.name ,会发现值已经与输入框里的值一样
当我们在控制台,给obj.name赋值时,会发现输入框的内容也会作出相应更改
notion image
这样就完成了一个简单的数据双向绑定了!
上一篇
axios获取二进制流并转化生成文件
下一篇
JavaScript实现防抖和节流的方法

评论
Loading...