{"id":25179563,"url":"https://github.com/21hook/mvvm","last_synced_at":"2026-05-04T05:43:23.410Z","repository":{"id":144074179,"uuid":"137223130","full_name":"21hook/MVVM","owner":"21hook","description":"MVVM Mechanism","archived":false,"fork":false,"pushed_at":"2018-08-16T00:29:21.000Z","size":73,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-04T04:16:11.368Z","etag":null,"topics":["listener-pattern","mvvm","vue"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/21hook.png","metadata":{"files":{"readme":"README-zh_cn.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2018-06-13T13:57:45.000Z","updated_at":"2018-10-10T06:06:54.000Z","dependencies_parsed_at":"2024-06-19T04:49:43.007Z","dependency_job_id":null,"html_url":"https://github.com/21hook/MVVM","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/21hook/MVVM","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21hook%2FMVVM","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21hook%2FMVVM/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21hook%2FMVVM/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21hook%2FMVVM/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/21hook","download_url":"https://codeload.github.com/21hook/MVVM/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21hook%2FMVVM/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32596533,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"online","status_checked_at":"2026-05-04T02:00:06.625Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["listener-pattern","mvvm","vue"],"created_at":"2025-02-09T15:37:02.031Z","updated_at":"2026-05-04T05:43:23.383Z","avatar_url":"https://github.com/21hook.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MVVM\nMVVM实现原理\n\n[README English](https://github.com/21hook/MVVM/blob/master/README.md)\n\n## 关键概念\n树遍历, get/set事件，发布-订阅模式，解释器模式，单向数据绑定\n\n## 原理\n实现一个data观察器，它可以监听数据对象子属性的get/set事件;\n实现一个dep对象，该对象为数据对象的每个子属性添加一个观察者列表。\n实现指令和表达式compiler。它扫描，分析每个元素节点中的指令或表达式，根据它们的名字计算指令的值。\n实现一个watcher对象，并将其添加为数据对象的子属性的观察者。当数据对象的子属值改变时，将通知依赖对象，并且它将自动更新子属性的所有订阅者 - 观察者对象。\n并且它将自动更新子属性的所有订阅者 - watcher对象。\n\n## 目录\n1. [Observe operation](#demo1-observe-operationsource)\n2. [Property dependencies](#demo2-property-dependenciessource)\n3. [Collect subscribers](#demo3-collect-subscriberssource)\n4. [Template compiler](#demo4-template-compilersource) \n5. [View update](#demo5-view-updatesource)\n6. [MVVM](##demo6-mvvmsource)\n\n## Demo1: Observe operation([Source](https://github.com/21hook/MVVM/blob/master/demo1))\n使用树递归遍历data对象的所有子属性节点。对于每个节点，使用object.defineProperty()绑定get/set事件。\n\n## Demo2: Property dependencies([Source](https://github.com/21hook/MVVM/blob/master/demo2))\n定义一个Dep类，它是data对象的属性依赖。\n另外，定义一个Watcher类，它是一个dep订阅者。这个类存储一个exp字段，是一个在Vue组件中的指令\u0026插值的[expression](https://en.wikipedia.org/wiki/Expression_(computer_science))\n\n## Demo3: Collect subscribers([Source](https://github.com/21hook/MVVM/blob/master/demo3))\n当访问data对象的子属性时，dep对象开始收集订阅者。它将添加一个watcher对象作为它的订阅者。\n\n## Demo4: Template compiler([Source](https://github.com/21hook/MVVM/blob/master/demo4))\n编译器将接收节点树（这就是为什么\u003ctemplate\u003e必须具有根标签），并返回token stream。\n编译器分析每个指令和插值，然后它将创建一个watcher对象用于计算\n他们的每一个的值。创建watcher对象时，它将计算存储表达式的exp字段\n指令或插值。因此，将访问data对象的所有子属性。它开始了订阅者收集\n\n## Demo5: View update([Source](https://github.com/21hook/MVVM/blob/master/demo5))\n当使用指令或插值中的表达式创建一个watcher对象时，它还绑定一个更新视图函数。\n如果data对象的相关子属性发生突变，它的dep对象将会被\n通知，然后dep对象的所有订阅者将被更新。最后，每个观察者将调用它的更新\n视图函数更新视图。\n\n## Demo6: MVVM([Source](https://github.com/21hook/MVVM/blob/master/demo6))\nVue实例的主程序。它需要遍历数据对象的所有子属性，如图所示\n[Demo1](#demo1-observe-operationsource)。然后，开始编译模板以收集\n数据对象的每个子属性的订阅者，如[Demo4](#demo4-template-compilersource)所示。\n\n## MVVM architecture\n- watcher订阅者收集\n```\n          init              trigger get event              add subscribers\nTemplate --------\u003e Watcher  ------------------\u003e Observe --------------------\u003e Dep \n```\n\n- 单向数据绑定\n```\n       set                     notify              update           view update\nData -------\u003e Observe --------------------\u003e Dep  ---------\u003e Watcher -------------\u003e View\n```\n\n## License\nMIT\n\n## Reference \n[1] *Design patterns: elements of reusable object-oriented software* \u003cbr\u003e\n[2] \u003c\u003cJavaScript设计模式与开发实践\u003e\u003e \u003cbr\u003e\n[3] Wikipedia [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F21hook%2Fmvvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F21hook%2Fmvvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F21hook%2Fmvvm/lists"}