模拟实现vue双向绑定:思路:
-
以form表单为例,写一个方法,在方法中先声明一个空对象来存储生成的表单对象。
-
获取所有表单元素节点,将其name属性值设置为对象的属性名,将表单元素的值设置为对象的属性值
- 获取所有节点并遍历
- 获取每个节点的name属性值和value值
- 通过defineProperty为对象配置set和get,规则为:当修改对象属性值时(set执行),修改的值赋值给表单元素的值,同时将该值赋值给本属性的_ 属性;当访问对象属性值时(get执行),直接将最新的_ 属性作为返回值返回
- 通过[]的形式添加对象中与表单对应的属性名与值
-
用户输入值,对象对应的属性值会同步更新
- 为表单绑定onchange事件(事件委托),在事件响应函数中,获取事件源的value值,和事件源的name属性值,再通过[]形式去修改obj即可
-
最后将obj作为整个函数的返回值返回
// 模拟实现vue双向绑定: function initObj(formId) { let obj = {} // 1)根据表单内容,自动生成obj,以及对应的值 let iptNodes = document.querySelectorAll(`${formId} input`)//获取表单中的所有子元素 iptNodes.forEach(function (ipt) {//遍历子元素,并形成对应的obj let nameVal = ipt.name//获取每个input框的name属性(作为obj的属性名) let val = ipt.value//获取每个input框的值(作为obj的属性值) Object.defineProperty(obj, nameVal, {//配置obj中的每个属性,当修改属性值时,将修改的属性值赋值给对应表单元素,将obj的替代属性值进行修改 set: function (v) { ipt.value = v// 将赋的属性值设置为对应的表单值 obj[`_${nameVal}`] = v }, get: function () { return obj[`_${nameVal}`]//将赋予最新值的替代属性值返回(这样用户看到的对应表单之就是最新值) }, }) obj[nameVal] = val//为obj添加对应input框的属性名和属性值 }) // 2)根据用户输入的值同步更新obj中的值(通过事件委托) document.querySelector(formId).onchange=function(e){ obj[e.target.name]=e.target.value } return obj } //验证是否成功实现双向绑定 let formObj=initObj("#loginForm") document.querySelector("#btn").onclick=function(e){ e.preventDefault() console.log("提交",formObj); }