JavaScript自定义响应式对象
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自定义响应式对象的更多相关文章
- 由浅入深,带你用JavaScript实现响应式原理(Vue2、Vue3响应式原理)
由浅入深,带你用JavaScript实现响应式原理 前言 为什么前端框架Vue能够做到响应式?当依赖数据发生变化时,会对页面进行自动更新,其原理还是在于对响应式数据的获取和设置进行了监听,一旦监听到数 ...
- 读Vue源码二 (响应式对象)
vue在init的时候会执行observer方法,如果value是对象就直接返回,如果对象上没有定义过_ob_这个属性,就 new Observer实例 export function observe ...
- 二、vue响应式对象
Object.defineProperty Object.defineProperty 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象,先来看一下它的语法: Obj ...
- Vue.set 向响应式对象中添加响应式属性,及设置数组元素触发视图更新
一.为什么需要使用Vue.set? vue中不能检测到数组和对象的两种变化: 1.数组长度的变化 vm.arr.length = 4 2.数组通过索引值修改内容 vm.arr[1] = ‘aa’ Vu ...
- Vue3中的响应式对象Reactive源码分析
Vue3中的响应式对象Reactive源码分析 ReactiveEffect.js 中的 trackEffects函数 及 ReactiveEffect类 在Ref随笔中已经介绍,在本文中不做赘述 本 ...
- JavaScript辅助响应式
js响应式 rem辅助响应式布局:其实就是指在HTML页面的大小不断变化的时候,里面的宽.高.字体等等也随之变化,主要是通过获取window.innerwidth的值来进行判断,7.5rem===10 ...
- JavaScript自定义类和对象的方法
备注:JavaScript中没有类class的概念,一般把原型对象看作类 1. 工厂方法--使用new Object创建对象并添加相关属性 var Obj = new Object; ...
- Javascript之响应式相册
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- javascript自定义简单map对象功能
这里介绍一种js创建简单map对象的方法: function Map() { //创建object对象, 并给object对象添加key和value属性 var obj1=new Object(); ...
- vue2.0与3.0响应式原理机制
vue2.0响应式原理 - defineProperty 这个原理老生常谈了,就是拦截对象,给对象的属性增加set 和 get方法,因为核心是defineProperty所以还需要对数组的方法进行拦截 ...
随机推荐
- Linux-wget命令使用及参数详解
wget简介 Linux系统中的wget是一个下载文件的工具,它用在命令行下.对于Linux用户是必不可少的工具,我们经常要下载一些软件或从远程服务器恢复备份到本地服务器.wget支持HTTP,HTT ...
- NC14685 加边的无向图
题目链接 题目 题目描述 给你一个 n 个点,m 条边的无向图,求至少要在这个的基础上加多少条无向边使得任意两个点可达~ 输入描述 第一行两个正整数 n 和 m . 接下来的m行中,每行两个正整数 i ...
- 基于keras的卷积神经网络(CNN)
1 前言 本文以MNIST手写数字分类为例,讲解使用一维卷积和二维卷积实现 CNN 模型.关于 MNIST 数据集的说明,见使用TensorFlow实现MNIST数据集分类.实验中主要用到 Conv1 ...
- 跨越千年医学对话:用AI技术解锁中医古籍知识,构建能够精准问答的智能语言模型,成就专业级古籍解读助手(LLAMA)
跨越千年医学对话:用AI技术解锁中医古籍知识,构建能够精准问答的智能语言模型,成就专业级古籍解读助手(LLAMA) 介绍:首先在 Ziya-LLaMA-13B-V1基线模型的基础上加入中医教材.中医各 ...
- Go 项目的文件布局
转自 kcq 的 https://github.com/golang-standards/project-layout https://github.com/golang-standards/proj ...
- [BUUCTF][Web][ACTF2020 新生赛]Exec 1
打开靶机对应url 显示可以输出ip 来进行ping操作 尝试试一下是否有命令注入的可能 127.0.0.1|ls 果然可以,输出结果 index.php PING 127.0.0.1 (127.0. ...
- go值接收者和指针接收者的区别
方法的接收者 package main import ( "fmt" ) type Person struct { Name string Age int } func (p Pe ...
- rpartition和partition按分割符分割
# rpartition 从目标字符串的末尾也就是右边开始搜索分割符,如果字符串包含指定的分割符 则返回一个3元的元组,第一个为分割符左边的子串,第二个为分割符本身, 第三个为分割符右边的字串. st ...
- queryset高级用法:select_related
在提取某个模型的数据的同时,也提前将相关联的数据提取出来.比如提取文章数据,可以使用select_related将author信息提取出来,以后再次使用article.author的时候就不需要再次去 ...
- 亲测可行,Android Studio 查看源码出现 Source for ‘Android API xxx Platform’ not found 的解决方法
亲测可行,Android Studio 查看源码出现 Source for 'Android API xxx Platform' not found 的解决方法 如标题中的问题,产生的原因就是 SDK ...