最近看了一下 Vue.js 的实现相关的文章,了解到了其数据劫持(双向绑定)的原理,使用到了Object.defineProperty
这个方法,花了点时间,自己尝试着做了一个小 demo。
MDN 解释:Object.defineProperty
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
let obj = {} Object.defineProperty(obj, 'name', { enumerable: true, writable: true, configurable: true, value: 'huqing' })
let obj = {} obj.name = 'huqing'
|
既然写法一样,为何要大费周折去写那么多呢,其实重点在其get
和set
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| let obj = {} let str Object.defineProperty(obj, 'name', { enumerable: true, configurable: true, get() { return str }, set(newValue) { str = newValue } })
obj.name = 'huqing' console.log(obj.name)
|
从这可以看出,我们可以在 get、set 函数中,写出对应的业务逻辑,做一系列我们想做的事情
话不多说,开始做 demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <!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 = { name: "" }
function oberseve(obj) { if (typeof obj !== 'object') return for (let key in obj) { defineReactive(obj, key, obj[key]) if (typeof obj[key] === 'object') { oberseve(obj[key]) } } }
function defineReactive(target, property, value) { Object.defineProperty(target, property, { get () { el.value = value return value }, set (newVal) { el.value = newVal value = newVal } }) }
oberseve(obj) el.addEventListener('input', function () { obj.name = this.value }) </script> </body> </html>
|
当我们在输入框输入之后,在控制台输入obj.name
,会发现值已经与输入框里的值一样
observe1
当我们在控制台,给obj.name赋值时,会发现输入框的内容也会作出相应更改
observe2
这样就完成了一个简陋的数据双向绑定了!
最后更新时间:
当前页访问次数 10