{"id":25276044,"url":"https://github.com/afine970/study_reactivity","last_synced_at":"2025-07-26T14:36:46.528Z","repository":{"id":162797851,"uuid":"384866112","full_name":"AFine970/study_reactivity","owner":"AFine970","description":null,"archived":false,"fork":false,"pushed_at":"2021-07-30T08:15:37.000Z","size":43,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-12T15:48:38.211Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AFine970.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-11T05:19:02.000Z","updated_at":"2021-07-30T08:15:39.000Z","dependencies_parsed_at":"2023-05-19T03:15:17.183Z","dependency_job_id":null,"html_url":"https://github.com/AFine970/study_reactivity","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AFine970%2Fstudy_reactivity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AFine970%2Fstudy_reactivity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AFine970%2Fstudy_reactivity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AFine970%2Fstudy_reactivity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AFine970","download_url":"https://codeload.github.com/AFine970/study_reactivity/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247464218,"owners_count":20942970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-12T15:37:17.831Z","updated_at":"2025-04-06T10:18:34.425Z","avatar_url":"https://github.com/AFine970.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 数据响应式原理\n\n## 快速开始\n\n```bash\nnpm install\n\nnpm run serve\n```\n\n## 项目结构\n\n```txt\n|-- study_reactivity\n    |-- .gitignore\n    |-- package-lock.json\n    |-- package.json\n    |-- readme.md\n    |-- webpack.config.js\n    |-- src\n    |   |-- array.js\n    |   |-- defineReactive.js // 数据响应式的主要实现\n    |   |-- Dep.js // Dep类\n    |   |-- index.js // 主入口\n    |   |-- observe.js\n    |   |-- Observer.js // Observer类\n    |   |-- utils.js\n    |   |-- Watch.js // Watch类型\n    |-- www\n        |-- index.html\n```\n\n## 实现原理\n\n- Vue2.x 中使用的是`Object.defineProperty()`方法中的 `get` 和 `set` 这两个方法对数据进行劫持\n- Vue3.x 中使用的是`Object.proxy()`来代理整个对象，来实现数据劫持\n- 两者的区别：\n  - `Object.defineProperty()`一次只能劫持目标对象中的一个属性\n  - `Object.proxy()`可以劫持整个目标对象，`Object.defineProperty()`要劫持整个目标对象，需要循环遍历整个对象才能实现\n  - `Object.defineProperty()`无法检测到对象属性的添加和删除，数组的 API 方法也无法监听\n  - `Object.proxy()`在性能上更优秀，配合`Reflect`使用，能让我们快速地执行`this`绑定\n\n### 侵入式和非侵入式响应式\n\nvue (非侵入式)\n\n```js\nthis.vm.a++;\n```\n\nreact (侵入式)\n\n```js\nthis.setState({\n  a: this.state.a + 1,\n});\n```\n\n### Observer 类--实现响应式的关键\n\n![Observer类.jpg](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fe1927672a7248a9b6c5451b0a63ba5e~tplv-k3u1fbpfcp-watermark.image)\n\n### 数组响应式--重写 7 个数组操作方法\n\n![重写数组的7个方法.jpg](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8bf63b0399fe474d967b8a7aede05346~tplv-k3u1fbpfcp-watermark.image)\n\n## 依赖收集\n\n### 什么是依赖？\n\n数据响应式原理中的依赖，不是我们平常使用的 npm 包的依赖，而指的是 Vue 中需要用到数据的地方\n\n- Vue1.x，**细粒度**依赖，用到数据的**DOM**都是依赖\n- Vue2.x，**中等粒度**依赖，用到数据的组件是依赖\n- 在 **getter** 中收集依赖，在 **setter** 中触发依赖\n\n### Dep 类和 Watch 类\n\n- 把依赖收集的代码封装成一个 Dep 类，它专门用来管理用来，**每个 Observer 类的实例，都内置了一个 Dep 类的实例**\n- Watch 是一个中介，数据发生变化时，通过 Watch 中转，通知组件\n- 工作过程简单描述\n  - 有一个已经被响应式处理的 A 对象（也就是 Observe 类的实例）\n  - 使用 Watch 类的实例 B 去监测数据变化，对 A 对象添加监测的那一刻触发了 getter\n  - 触发了 getter，A 对象中 Dep 类实例就会进行依赖收集工作，把当前的实例 B 收集起来\n  - 当 A 对象的数据变化时，触发 setter\n  - 触发 setter，这时候 A 对象中 Dep 类实例通知实例 B，实例 B 就触发响应回调\n\n![数据监测工作原理.jpg](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/146c6de9c4d943b1a6b37db924f3c43d~tplv-k3u1fbpfcp-watermark.image)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fafine970%2Fstudy_reactivity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fafine970%2Fstudy_reactivity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fafine970%2Fstudy_reactivity/lists"}