1. 引言

这里的响应式对象是指JavaScript中的变量与HTML中的内容相绑定,变量更新则内容更新,也叫数据绑定

此时不得不说MVVM架构,MVVM架构思想的实现步骤如下:

  • 模型(Model):负责处理数据的读写操作,包括从服务器获取数据、存储数据等
  • 视图(View):负责渲染用户界面,包括HTML、CSS和JavaScript等,但不包括业务逻辑
  • 视图模型(ViewModel):连接视图和模型的桥梁,负责从模型中获取数据,并将其转换为视图可以使用的格式,同时也负责将视图中的用户交互事件转换为模型可以理解的操作。视图模型中不包含任何与视图相关的代码,从而实现了解耦

响应式对象或者说数据绑定,是视图模型(VM)的核心,只需改变JS中的变量的内容(修改Model),HTML中的内容也会随之变化(视图变化)

MVVM框架很多,典型如Vue、React等

以下记述的是自定义一个响应式对象,分别是使用JavaScript的Object.defineProperty方法和Proxy对象来实现

2. Proxy

Proxy 是ES6中的对象用于创建一个对象的代理,从而实现对对象的操作的拦截,基础用法为const p = new Proxy(target, handler),更为详细的文档可以参考MDN:Proxy - JavaScript | MDN (mozilla.org)

使用Proxy对象是Vue3响应式的实现方法

自定义一个响应式对象,此处的思路也很简单,就是使用Proxy对象来代理目标对象,然后设置handler.set()方法,实现目标对象的赋值拦截并更新DOM

示例代码如下:

<body>
<div id="container"></div> <script>
function reactive(obj) {
const handler = {
get(target, key) {
return Reflect.get(target, key)
},
set(target, key, value) {
if (key === 'value')
document.getElementById('container').innerHTML = value
return Reflect.set(target, key, value)
}
}
return new Proxy(obj, handler)
} const obj = reactive({}) </script>
</body>

此时,设置obj.value = <new value>,DOM中也会随之更新

3. Object.defineProperty

Object.defineProperty() 静态方法会直接在一个对象上定义一个新属性,或修改其现有属性,并返回此对象,其基本语法为Object.defineProperty(obj, prop, descriptor),其中descriptor表示要定义或修改的属性的描述符,可以设置 getter 和 setter 的函数,更为详细的文档可参考MDN:Object.defineProperty() - JavaScript | MDN (mozilla.org)

使用Object.defineProperty方法是Vue2响应式的实现方法

自定义一个响应式对象,此处的思路也很简单,就是使用Object.defineProperty来给目标对象设置属性,然后设置setter 函数方法,实现目标对象的赋值拦截并更新DOM

示例代码如下:

<body>
<div id="container"></div> <script>
function reactive(obj) {
return Object.defineProperty(obj, 'value', {
get() {
return this._value
},
set(value) {
this._value = value
document.getElementById('container').innerHTML = value
}
})
} const obj = reactive({}) </script>
</body>

此时,设置obj.value = <new value>,DOM中也会随之更新

4. 参考资料

[1] Proxy - JavaScript | MDN (mozilla.org)

[2] Object.defineProperty() - JavaScript | MDN (mozilla.org)

JavaScript自定义响应式对象的更多相关文章

  1. 由浅入深,带你用JavaScript实现响应式原理(Vue2、Vue3响应式原理)

    由浅入深,带你用JavaScript实现响应式原理 前言 为什么前端框架Vue能够做到响应式?当依赖数据发生变化时,会对页面进行自动更新,其原理还是在于对响应式数据的获取和设置进行了监听,一旦监听到数 ...

  2. 读Vue源码二 (响应式对象)

    vue在init的时候会执行observer方法,如果value是对象就直接返回,如果对象上没有定义过_ob_这个属性,就 new Observer实例 export function observe ...

  3. 二、vue响应式对象

    Object.defineProperty Object.defineProperty 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象,先来看一下它的语法: Obj ...

  4. Vue.set 向响应式对象中添加响应式属性,及设置数组元素触发视图更新

    一.为什么需要使用Vue.set? vue中不能检测到数组和对象的两种变化: 1.数组长度的变化 vm.arr.length = 4 2.数组通过索引值修改内容 vm.arr[1] = ‘aa’ Vu ...

  5. Vue3中的响应式对象Reactive源码分析

    Vue3中的响应式对象Reactive源码分析 ReactiveEffect.js 中的 trackEffects函数 及 ReactiveEffect类 在Ref随笔中已经介绍,在本文中不做赘述 本 ...

  6. JavaScript辅助响应式

    js响应式 rem辅助响应式布局:其实就是指在HTML页面的大小不断变化的时候,里面的宽.高.字体等等也随之变化,主要是通过获取window.innerwidth的值来进行判断,7.5rem===10 ...

  7. JavaScript自定义类和对象的方法

    备注:JavaScript中没有类class的概念,一般把原型对象看作类 1. 工厂方法--使用new Object创建对象并添加相关属性 var Obj = new Object;         ...

  8. Javascript之响应式相册

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  9. javascript自定义简单map对象功能

    这里介绍一种js创建简单map对象的方法: function Map() { //创建object对象, 并给object对象添加key和value属性 var obj1=new Object(); ...

  10. vue2.0与3.0响应式原理机制

    vue2.0响应式原理 - defineProperty 这个原理老生常谈了,就是拦截对象,给对象的属性增加set 和 get方法,因为核心是defineProperty所以还需要对数组的方法进行拦截 ...

随机推荐

  1. 借助Rich库实现Pandas DataFrame颜值升级

    pandas的DataFrame功能强大自不必说,它可以帮助我们极大的提高统计分析的效率. 不过,使用DataFrame开发我们的分析程序的时候,经常需要打印出DataFrame的内容,以验证和调试数 ...

  2. Spring Boot + MyBatis-Plus 实现 MySQL 主从复制动态数据源切换

    MySQL 主从复制是一种常见的数据库架构,它可以提高数据库的性能和可用性.动态数据源切换则可以根据业务需求,在不同场景下使用不同的数据源,比如在读多写少的场景下,可以通过切换到从库来分担主库的压力. ...

  3. 【开工大吉】推荐4款开源、美观的WPF UI组件库

    前言 经常有小伙伴在技术群里提问:WPF有什么好用的UI组件库?,今天大姚给大家推荐4款开源.美观的WPF UI组件库. WPF介绍 WPF 是一个强大的桌面应用程序框架,用于构建具有丰富用户界面的 ...

  4. 如何从零实现属于自己的 API 网关?

    序言 上一篇文章:你连对外接口签名都不会知道?有时间还是要学习学习. 有很多小伙伴反应,对外的 API 中相关的加签,验签这些工作可以统一使用网关去处理. 说到网关,大家肯定比较熟悉.市面上使用比较广 ...

  5. spring boot 2.0集成并使用redis

    项目地址:https://gitee.com/indexman/spring_boot_in_action 前面一章介绍了spring boot自带的缓存,下面讲一下如何在2.0版本中集成并使用red ...

  6. String--getline()

    #include <string> #include <sstream> #include <iostream> int main() { std::wstring ...

  7. 发送HTML模板邮件

    概述 为了增强邮件内容展示的样式,可以将普通的文本邮件转换为HTML内容格式. 在Java中,可以通过页面模板技术来实现.具体来说,可以使用Thymeleaf模板. 具体实现 首先,在项目中引入Thy ...

  8. rpartition和partition按分割符分割

    # rpartition 从目标字符串的末尾也就是右边开始搜索分割符,如果字符串包含指定的分割符 则返回一个3元的元组,第一个为分割符左边的子串,第二个为分割符本身, 第三个为分割符右边的字串. st ...

  9. python中操作csv

    示例 import csv with open('t.csv', mode='r', encoding='utf-8') as f: reader_obj = csv.reader(f) # 通过re ...

  10. day05---系统的重要文件(3)

    1) /usr/local 编辑 安装的软件 第三方软件安装位置 软件安装的三种方法 1.yum安装 自动解决依赖问题 yum [选项参数] 包名 第一个里程碑:我想要安装的软件的名字 或者是 知道命 ...