赞
踩
1、众所周知,vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变。这段话应该每个面试找工作的前端都背过。但是究竟是如何实现的,我个人按照个人理解,简单的梳理一下。
input触发input事件 > Object.defineProperty set() 赋值 > 回调直接传入值更新视图 或者 使用Object.defineProperty get()方法取值更新视图
我觉得还是直接看代码,打印,大家更能明白流程
2、这是使用了get取值,也可以不用get取值,直接回调传入值
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title></title>
- </head>
- <body>
- <div></div>
- <input type="text" id="Input" oninput="onInput()" />
- </body>
- <script>
- let myObj = {
- text: "",
- }
-
- function inputWatch(obj, name, cb) {
- let objName = obj[name];
- Object.defineProperty(obj, name, {
- // writable: true, // 是否可以修改属性的值
- configurable: true, //配置项(writable、enumerable)是否可以修改
- enumerable: true ,// 是否可以枚举
- get() {
- //获取属性值的时候进入
- console.log("get取值")
- return objName
- },
- set(val) {
- console.log("set赋值")
- // 触发setter给obj赋值
- objName = val
- //执行劫持后的操作
- setHtml();
- }
- })
- }
-
- // 回调赋值
- function setHtml() {
- console.log("回调更新视图")
- document.querySelector('div').innerHTML = myObj.text;
- document.querySelector('input').value = myObj.text;
-
- }
- // input变化赋值
- function onInput() {
- console.log("input变化")
- myObj.text = document.getElementById('Input').value
- }
-
- // 调用传入对象,对象属性,回调方法
- inputWatch(myObj, 'text', setHtml);
- </script>
- </html>
3、不使用get取值,直接回调传入值
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title></title>
- </head>
- <body>
- <div></div>
- <input type="text" id="Input" oninput="onInput()" />
- </body>
- <script>
- let myObj = {
- text: "",
- }
-
- function inputWatch(obj, name, cb) {
- let objName = obj[name];
- Object.defineProperty(obj, name, {
- // writable: true, // 是否可以修改属性的值
- configurable: true, //配置项(writable、enumerable)是否可以修改
- enumerable: true ,// 是否可以枚举
- get() {
- //获取属性值的时候进入
- console.log("get取值")
- return objName
- },
- set(val) {
- console.log("set赋值")
- // 触发setter给obj赋值
- objName = val
- //执行劫持后的操作
- setHtml(val);
- }
- })
- }
-
- // 回调赋值
- function setHtml(val) {
- console.log("回调更新视图值:",val)
- document.querySelector('div').innerHTML = val;
- document.querySelector('input').value = val
-
- }
- // input变化赋值
- function onInput() {
- console.log("input变化")
- myObj.text = document.getElementById('Input').value
- }
-
- // 调用传入对象,对象属性,回调方法
- inputWatch(myObj, 'text', setHtml);
- </script>
- </html>
总结:不要盲目的背答案,毕竟一段代码可以有千百种实现方式,没有最好只有更好。上面两种方式只是有一点小小的改动,都能实现双向绑定。但是个人觉得第二种直接调用方法传值,有点儿违背了模型驱动试图的逻辑,但是他的值都是同一个值。我甚至觉得不需要模型一样可以直接拿到值更改视图。(纯属个人想法, 大佬勿喷)
附加:此方法可衍生用于微信小程序,监听全局变量,实现全局监听器
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。