Vue双向数据绑定原理(面试必问)

2023-11-04

答案:
vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。
在这里插入图片描述
具体步骤

  1. 需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
    这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
  2. compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
  3. Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
    (1)在自身实例化时往属性订阅器(dep)里面添加自己
    (2)自身必须有一个update()方法
    (3)待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
  4. MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

1. 什么是Object.defineProperty?

1.1 语法:

Object.defineProperty(obj, prop, descriptor)

参数说明:

  1. obj:必需。目标对象
  2. prop:必需。需定义或修改的属性的名字
  3. descriptor:必需。目标属性所拥有的特性

返回值:
传入函数的对象。即第一个参数obj;

针对属性,我们可以给这个属性设置一些特性,比如是否只读不可以写;是否可以被for…in或Object.keys()遍历。

给对象的属性添加特性描述,目前提供两种形式:数据描述和存取器描述。

当修改或定义对象的某个属性的时候,给这个属性添加一些特性:

数据描述:

var obj = {
    test:"hello"
}
//对象已有的属性添加特性描述
Object.defineProperty(obj,"test",{
    configurable:true | false,
    enumerable:true | false,
    value:任意类型的值,
    writable:true | false
});
//对象新添加的属性的特性描述
Object.defineProperty(obj,"newKey",{
    configurable:true | false,
    enumerable:true | false,
    value:任意类型的值,
    writable:true | false
});

数据描述中的属性都是可选的,来看一下设置每一个属性的作用。

value

属性对应的值,可以使任意类型的值,默认为undefined

var obj = {}
//第一种情况:不设置value属性
Object.defineProperty(obj,"newKey",{

});
console.log( obj.newKey );  //undefined
------------------------------
//第二种情况:设置value属性
Object.defineProperty(obj,"newKey",{
    value:"hello"
});
console.log( obj.newKey );  //hello

writable
属性的值是否可以被重写。设置为true可以被重写;设置为false,不能被重写。默认为false。

var obj = {}
//第一种情况:writable设置为false,不能重写。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false
});
//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //hello

//第二种情况:writable设置为true,可以重写
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true
});
//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //ch

enumerable
此属性是否可以被枚举(使用for…in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false。

var obj = {}
//第一种情况:enumerable设置为false,不能被枚举。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false
});

//枚举对象的属性
for( var attr in obj ){
    console.log( attr );  //console不出来
}
//第二种情况:enumerable设置为true,可以被枚举。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:true
});

//枚举对象的属性
for( var attr in obj ){
    console.log( attr );  //newKey
}

configurable
是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被可以被删除或不可以重新设置特性。默认为false。

这个属性起到两个作用:

目标属性是否可以使用delete删除

目标属性是否可以再次设置特性

//-----------------测试目标属性是否能被删除------------------------
var obj = {}
//第一种情况:configurable设置为false,不能被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});
//删除属性
delete obj.newKey;
console.log( obj.newKey ); //hello

//第二种情况:configurable设置为true,可以被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",

除了可以给新定义的属性设置特性,也可以给已有的属性设置特性

//定义对象的时候添加的属性,是可删除、可重写、可枚举的。
var obj = {
    test:"hello"
}

//改写值
obj.test = 'change value';

console.log( obj.test ); //'change value'

Object.defineProperty(obj,"test",{
    writable:false
})


//再次改写值
obj.test = 'change value again';

console.log( obj.test ); //依然是:'change value'

提示:一旦使用Object.defineProperty给对象添加属性,那么如果不设置属性的特性,那么configurable、enumerable、writable这些值都为默认的false

var obj = {};
//定义的新属性后,这个属性的特性中configurable,enumerable,writable都为默认的值false
//这就导致了neykey这个是不能重写、不能枚举、不能再次设置特性
//
Object.defineProperty(obj,'newKey',{

});

//设置值
obj.newKey = 'hello';
console.log(obj.newKey);  //undefined

//枚举
for( var attr in obj ){
    console.log(attr);
}

2. 什么是setter、getter

答:首先,别误以为他们就是一会要说的get、set
对象有两种属性:

  1. 数据属性: 就是我们经常使用的属性
  2. 访问器属性: 也称存取器属性(存取器属性就是一组获取和设置值的函数)
    再看一行代码:

在这里插入图片描述
log打印出来的如下:
在这里插入图片描述
数据属性就是a和b;

get和set就是关键字 它们后面各自对应一个函数,这个函数就是上面红字部分所讲的,存储器属性。

get对应的方法称为getter,负责获取值,它不带任何参数。set对应的方法为setter,负责设置值,在它的函数体中,一切的return都是无效的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue双向数据绑定原理(面试必问) 的相关文章

随机推荐

  • CTF.show:萌新:web13

    这次过滤了更多的
  • 用javascript实现动态增加DataGrid行

  • STM32——TIM编码器接口

    文章目录 一 编码器接口简介 二 正交编码器 三 通用定时器框图 四 编码器接口基本结构 五 工作模式 六 实例 均不反相 七 实例 TI1反相 八 编码器接口测速 电路设计 关键代码 一 编码器接口简介 Encoder Interface
  • [转]scanf函数用法

    sscanf 读取格式化的字符串中的数据 swscanf 是 sscanf 的宽字符版本 swscanf 的参数是宽字符串 swscanf不处理 Unicode 全角十六进制或 兼容性区 字符 除此以外 swscanf 和 sscanf 的
  • iOS SDK开发流程

    文章目录 搭建工作区间 1 创建一个本地代码库文件夹 2 创建一个工作区间 3 创建一个项目 4 创建Framework制作的项目 5 添加项目到Workspace 编写和调试Framework 编写SDK代码 1 添加一个类 2 在类里添
  • 读取xml文件,实现JTree树形结构的构建(一)

    JTree是Swing的一个组件 树 一颗树由若干节点 通过层级关系组成 在java中JTree的节点通过DefaultMutableTreeNode类创建 该类实现TreeNode接口 目前我只会一点基础的应用 例如使用DefaultMu
  • 苹果系统itunes连iphone连不上服务器,itunes无法连接iphone的解决方法

    如果是苹果用户 那么基本上都会用到iTunes这款软件 有时候我们在用数据线将iTunes连接上电脑的时候 却发现itunes无法连接iphone 那么 itunes无法连接iphone怎么办呢 处理起来并不难 下面跟着小编一起来看看itu
  • Sping Security前后端分离两种方案

    前言 本篇文章是基于Spring Security实现前后端分离登录认证及权限控制的实战 主要包括以下四方面内容 Spring Seciruty简单介绍 通过Spring Seciruty实现的基于表单和Token认证的两种认证方式 自定义
  • python类的定义——为什么都写了_init_()方法

    在看很多python代码中 都发现关于类的定义 很多都有 init 为什么 初次理解 写上 init 就是为了方便后面的创建实例的时候 给实例绑定上属性 也方便后续类中方法的定义 简言之 就是方便我们后续代码的编写 所以 应该学会掌握 此处
  • unity build 报错 The name 'XXX' does not exist in the current context

    unity build 报错 The name XXX does not exist in the current context The type or namespace name XXX could not be found are
  • 嗅探HTTP网页用户账户密码

    嗅探HTTP网页 一 测试基础 1 ARP基础 使用mac地址和ip地址进行通信的局域网协议 2 HTTP 一种上网 网页请求通信协议 该协议以明文传输 即在传输时不对数据进行加密 因为http的不安全性 所以在局域网环境中 可以通过ARP
  • Android平台GB28181设备接入端如何实现本地录像?

    实现Android平台GB28181设备接入的时候 有个功能点不可避免 那就是本地录像 实际上 在实现GB28181设备接入模块之前 我们前些年做RTMP推送和轻量级RTSP服务的时候 早已经实现了本地录像功能 本地录像功能 我们实现的主要
  • 七、Docker网络模式详解

    目录 一 docker网络概述 1 docker网络实现的原理 2 容器的端口映射 1 端口映射 2 四种端口映射 3 端口映射演示 1 随机端口映射 P 2 指定端口映射 p 宿主机端口 容器端口 3 指定网卡随机端口映射 p 4 指定网
  • 用python画个佩奇来瞧瞧

    闲来无事 用turtle画了个小猪佩奇 代码其实很简单的 就是烦了点 没必要每行代码都发出来 给大家看几个主要的函数好了 另外我给绝大多数代码都加上了注释 相同的代码我就不加了 首先需要初始化画笔的一些属性 包括颜色 画笔的画画速度等 de
  • 由于找不到MSVCR120.dll【实测解决】

    添加打印机时遇到的问题 由于找不到MSVCR120 dll 无法继续执行代码 重新安装程序可能会解决此问题 查了官网下载驱动 下载dll等等 最后还是在mysql的一个链接上解决了问题 总结 看来是一个通用问题 解决方案 https www
  • 数据仓库_数据仓库_缓慢渐变维度实现的几种思路

    数仓缓慢渐变维度表设计 另一篇比较好的文章结合实际案例 数仓建设 缓慢变化维的10种处理方式 雾岛与鲸的博客 CSDN博客 缓慢渐变维度 维度数据会随着时间发生变化 变化速度比较缓慢 这种维度数据通常称作缓慢渐变维 由于数据仓库需要追溯历史
  • Opencart3.0后台选择产品分类处分类显示不全解决方案

    无论后台有多少个分类 这里总是显示不全 解决方法 修改admin controller catalog category php 里面的autocomplete方法 过滤数组默认限制了5条数据 修改为自己想要的即可 filter data
  • ARM架构的STM32F103和RISC-V架构的CH32V103对比

    STM32F103和CH32V103对比如下图 STM32F103 概述 STM32F103 资源配置 CH32V103概述 CH32V103资源配置
  • 探索react技术栈-技术选型

    一 前言 陆陆续续接触react有一年多了 深感react的简单优雅 急切地想用react去开发程序 但是热情之后 发现react社区的种种问题 比如在社区打打常常提到的 angular vs react react作为view层的库 并没
  • Vue双向数据绑定原理(面试必问)

    答案 vue js是采用数据劫持结合发布者 订阅者模式的方式 通过Object defineProperty 来劫持各个属性的setter getter 在数据变动时发布消息给订阅者 触发相应的监听回调来渲染视图 具体步骤 需要observ