{"id":3223,"date":"2021-04-12T10:48:57","date_gmt":"2021-04-12T02:48:57","guid":{"rendered":"http:\/\/www.yuguoxy.com\/geekhome\/?p=3223"},"modified":"2026-08-18T12:35:34","modified_gmt":"2026-08-18T04:35:34","slug":"vue-%e5%93%8d%e5%ba%94%e5%bc%8f%e5%8e%9f%e7%90%86%e6%a8%a1%e6%8b%9f","status":"publish","type":"post","link":"https:\/\/ai.zhousir.top\/?p=3223","title":{"rendered":"Vue \u54cd\u5e94\u5f0f\u539f\u7406\u6a21\u62df"},"content":{"rendered":"<section id=\"wenyan\" style=\"font-family: system-ui, 'Apple Color Emoji', 'Segoe UI', 'Segoe UI Symbol', 'Noto Sans', Roboto, sans-serif; line-height: 1.75; font-size: 16px; color: #000000; caret-color: #000000;\" data-provider=\"WenYan\">\n<p style=\"margin: 1em 0px;\">Vue \u6700\u72ec\u7279\u7684\u4e00\u70b9\u662f <strong style=\"color: #4870ac;\">\u6570\u636e\u9a71\u52a8<\/strong>\uff1a\u6539\u6570\u636e\u5c31\u6539\u89c6\u56fe\uff0c\u5c11\u624b\u5199 DOM\u3002\u672c\u7bc7\u5148\u5bf9\u9f50\u6570\u636e\u54cd\u5e94\u5f0f\u3001\u53d1\u5e03\u8ba2\u9605\u548c\u89c2\u5bdf\u8005\uff0c\u518d\u6a21\u62df Vue 2 \u7684 <code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">Vue<\/code> \/ <code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">Observer<\/code> \/ <code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">Compiler<\/code> \/ <code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">Dep<\/code> \/ <code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">Watcher<\/code>\u3002<\/p>\n<p style=\"margin: 1em 0px;\">\u6240\u6709\u793a\u610f\u56fe\uff08\u542b\u672c\u5730 file:\/\/ \u8def\u5f84\u548c\u7ad9\u70b9\u56fe\uff09\u5747\u6309\u539f\u6587\u4fdd\u7559\u3002<\/p>\n<h2 style=\"padding: 1px 12.5px; color: #ffffff; margin: 1.2em 0px 1em; border-radius: 4px; display: inline-block; background-color: #4870ac; font-size: 1.3em;\">\u4e00\u3001\u4e09\u4e2a\u6982\u5ff5<\/h2>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">1. \u6570\u636e\u9a71\u52a8<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section><strong style=\"color: #4870ac;\">\u6570\u636e\u54cd\u5e94\u5f0f<\/strong>\uff1adata \u53ea\u662f\u666e\u901a\u5bf9\u8c61\uff0c\u6539\u5b83\u89c6\u56fe\u66f4\u65b0\uff0c\u5c11\u64cd\u4f5c DOM<\/section>\n<\/li>\n<li>\n<section><strong style=\"color: #4870ac;\">\u53cc\u5411\u7ed1\u5b9a<\/strong>\uff1a\u6570\u636e\u53d8\u89c6\u56fe\u53d8\uff0c\u89c6\u56fe\u53d8\u6570\u636e\u4e5f\u53d8\uff1b\u8868\u5355\u7528 <code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">v-model<\/code><\/section>\n<\/li>\n<li>\n<section>\u5f00\u53d1\u65f6\u76ef\u6570\u636e\u672c\u8eab\uff0c\u4e0d\u5fc5\u5173\u5fc3\u5982\u4f55\u6e32\u67d3\u5230\u89c6\u56fe<\/section>\n<\/li>\n<\/ul>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">2. \u6838\u5fc3\u539f\u7406<\/h3>\n<p style=\"margin: 1em 0px;\"><strong style=\"color: #4870ac;\">Vue 2.x<\/strong> \u7528 <code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">Object.defineProperty<\/code> \u52ab\u6301\uff1a<\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">\/\/ \u6a21\u62df Vue \u4e2d\u7684 data \u9009\u9879\nlet data = {\n    msg: 'hello'\n}\n\/\/ \u6a21\u62df Vue \u7684\u5b9e\u4f8b\nlet vm = {}\n\/\/ \u6570\u636e\u52ab\u6301\uff1a\u5f53\u8bbf\u95ee\u6216\u8005\u8bbe\u7f6e vm \u4e2d\u7684\u6210\u5458\u7684\u65f6\u5019\uff0c\u505a\u4e00\u4e9b\u5e72\u9884\u64cd\u4f5c\nObject.defineProperty(vm, 'msg', {\n    \/\/ \u53ef\u679a\u4e3e\uff08\u53ef\u904d\u5386\uff09\n    enumerable: true,\n    \/\/ \u53ef\u914d\u7f6e\uff08\u53ef\u4ee5\u4f7f\u7528 delete \u5220\u9664\uff0c\u53ef\u4ee5\u901a\u8fc7 defineProperty \u91cd\u65b0\u5b9a\u4e49\uff09\n    configurable: true,\n    \/\/ \u5f53\u83b7\u53d6\u503c\u7684\u65f6\u5019\u6267\u884c\n    get () {\n        console.log('get: ', data.msg)\n        return data.msg\n    },\n    \/\/ \u5f53\u8bbe\u7f6e\u503c\u7684\u65f6\u5019\u6267\u884c\n    set (newValue) {\n        console.log('set: ', newValue)\n        if (newValue === data.msg) {\n            return\n        }\n        data.msg = newValue\n        \/\/ \u6570\u636e\u66f4\u6539\uff0c\u66f4\u65b0 DOM \u7684\u503c\n        document.querySelector('#app').textContent = data.msg\n    }\n})\n\/\/ \u6d4b\u8bd5\nvm.msg = 'Hello World'\nconsole.log(vm.msg)<\/code><\/pre>\n<p style=\"margin: 1em 0px;\"><strong style=\"color: #4870ac;\">Vue 3.x<\/strong> \u7528 <code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">Proxy<\/code>\uff1a<\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">\/\/ \u6a21\u62df Vue \u4e2d\u7684 data \u9009\u9879\nlet data = {\n    msg: 'hello',\n    count: 0\n}\n\/\/ \u6a21\u62df Vue \u5b9e\u4f8b\nlet vm = new Proxy(data, {\n    \/\/ \u5f53\u8bbf\u95ee vm \u7684\u6210\u5458\u4f1a\u6267\u884c\n    get (target, key) {\n        console.log('get, key: ', key, target[key])\n        return target[key]\n    },\n    \/\/ \u5f53\u8bbe\u7f6e vm \u7684\u6210\u5458\u4f1a\u6267\u884c\n    set (target, key, newValue) {\n        console.log('set, key: ', key, newValue)\n        if (target[key] === newValue) {\n            return\n        }\n        target[key] = newValue\n        document.querySelector('#app').textContent = target[key]\n    }\n})\n\/\/ \u6d4b\u8bd5\nvm.msg = 'Hello World'\nconsole.log(vm.msg)<\/code><\/pre>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">3. \u53d1\u5e03\u8ba2\u9605 vs \u89c2\u5bdf\u8005<\/h3>\n<p style=\"margin: 1em 0px;\"><strong style=\"color: #4870ac;\">\u53d1\u5e03\/\u8ba2\u9605<\/strong>\uff1a\u6709\u4fe1\u53f7\u4e2d\u5fc3\u3002\u4efb\u52a1\u5b8c\u6210\u5c31 publish\uff0c\u5176\u4ed6\u4efb\u52a1 subscribe\u3002\u53d1\u5e03\u8005\u548c\u8ba2\u9605\u8005\u4e0d\u5fc5\u8ba4\u8bc6\u5bf9\u65b9\u3002<\/p>\n<p style=\"margin: 1em 0px;\">Vue \u81ea\u5b9a\u4e49\u4e8b\u4ef6\uff1a<\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">let vm = new Vue()\nvm.$on('dataChange', () =&gt; {\n    console.log('dataChange')\n})\nvm.$on('dataChange', () =&gt; {\n    console.log('dataChange1')\n})\nvm.$emit('dataChange')<\/code><\/pre>\n<p style=\"margin: 1em 0px;\">\u5144\u5f1f\u7ec4\u4ef6\u7528 eventBus\uff1a<\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">\/\/ eventBus.js\n\/\/ \u4e8b\u4ef6\u4e2d\u5fc3\nlet eventHub = new Vue()\n\/\/ ComponentA.vue\n\/\/ \u53d1\u5e03\u8005\naddTodo: function () {\n    \/\/ \u53d1\u5e03\u6d88\u606f(\u4e8b\u4ef6)\n    eventHub.$emit('add-todo', { text: this.newTodoText })\n    this.newTodoText = ''\n}\n\/\/ ComponentB.vue\n\/\/ \u8ba2\u9605\u8005\ncreated: function () {\n    \/\/ \u8ba2\u9605\u6d88\u606f(\u4e8b\u4ef6)\n    eventHub.$on('add-todo', this.addTodo)\n}<\/code><\/pre>\n<p style=\"margin: 1em 0px;\">\u6a21\u62df $on \/ $emit\uff1a<\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">class EventEmitter {\n    constructor () {\n        \/\/ { eventType: [ handler1, handler2 ] }\n        this.subs = {}\n    }\n    \/\/ \u8ba2\u9605\u901a\u77e5\n    $on (eventType, handler) {\n        this.subs[eventType] = this.subs[eventType] || []\n        this.subs[eventType].push(handler)\n    }\n    \/\/ \u53d1\u5e03\u901a\u77e5\n    $emit (eventType) {\n        if (this.subs[eventType]) {\n            this.subs[eventType].forEach(handler =&gt; {\n                handler()\n            })\n        }\n    }\n}\n\/\/ \u6d4b\u8bd5\nvar bus = new EventEmitter()\n\/\/ \u6ce8\u518c\u4e8b\u4ef6\nbus.$on('click', function () {\n    console.log('click')\n})\nbus.$on('click', function () {\n    console.log('click1')\n})\n\/\/ \u89e6\u53d1\u4e8b\u4ef6\nbus.$emit('click')<\/code><\/pre>\n<p style=\"margin: 1em 0px;\"><strong style=\"color: #4870ac;\">\u89c2\u5bdf\u8005\u6a21\u5f0f<\/strong>\uff1a\u89c2\u5bdf\u8005 Watcher \u6709 <code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">update()<\/code>\uff1b\u76ee\u6807 Dep \u6709 subs\u3001<code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">addSub<\/code>\u3001<code style=\"font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; color: #4870ac; font-size: 0.9em; font-weight: normal; overflow-wrap: break-word; padding: 2px 4px; border-radius: 3px; margin: 2px; background-color: #f6f8fa; word-break: break-all;\">notify<\/code>\u3002\u6ca1\u6709\u4e8b\u4ef6\u4e2d\u5fc3\uff0c\u8ba2\u9605\u8005\u548c\u53d1\u5e03\u8005\u4e92\u76f8\u4f9d\u8d56\u3002<\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">\/\/ \u76ee\u6807(\u53d1\u5e03\u8005)\n\/\/ Dependency\nclass Dep {\n    constructor () {\n        \/\/ \u5b58\u50a8\u6240\u6709\u7684\u89c2\u5bdf\u8005\n        this.subs = []\n    }\n    \/\/ \u6dfb\u52a0\u89c2\u5bdf\u8005\n    addSub (sub) {\n        if (sub &amp;&amp; sub.update) {\n        this.subs.push(sub)\n        }\n    }\n    \/\/ \u901a\u77e5\u6240\u6709\u89c2\u5bdf\u8005\n    notify () {\n        this.subs.forEach(sub =&gt; {\n            sub.update()\n        })\n    }\n}\n\/\/ \u89c2\u5bdf\u8005(\u8ba2\u9605\u8005)\nclass Watcher {\n    update () {\n        console.log('update')\n    }\n}\n\/\/ \u6d4b\u8bd5\nlet dep = new Dep()\nlet watcher = new Watcher()\ndep.addSub(watcher)\ndep.notify()<\/code><\/pre>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u89c2\u5bdf\u8005\uff1a\u7531\u5177\u4f53\u76ee\u6807\u8c03\u5ea6\uff0cDep \u76f4\u63a5\u8c03\u89c2\u5bdf\u8005\u65b9\u6cd5<\/section>\n<\/li>\n<li>\n<section>\u53d1\u5e03\/\u8ba2\u9605\uff1a\u7531\u8c03\u5ea6\u4e2d\u5fc3\u8c03\u7528\uff0c\u53cc\u65b9\u4e0d\u7528\u77e5\u9053\u5bf9\u65b9\u5b58\u5728<\/section>\n<\/li>\n<\/ul>\n<p style=\"margin: 1em 0px;\"><img decoding=\"async\" src=\"file:\/\/H:\\yuguoxy\\%E6%95%99%E5%AD%A6\\03web%E5%89%8D%E7%AB%AF\\%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0\\vue%E7%9B%B8%E5%85%B3\\media\\20210412102945.png\" alt=\"\" \/><a href=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/20210412102945.png\" rel=\"fancybox\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-3225\" src=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/20210412102945.png\" alt=\"20210412102945\" width=\"794\" height=\"679\" \/><\/a><\/p>\n<h2 style=\"padding: 1px 12.5px; color: #ffffff; margin: 1.2em 0px 1em; border-radius: 4px; display: inline-block; background-color: #4870ac; font-size: 1.3em;\">\u4e8c\u3001\u54cd\u5e94\u5f0f\u539f\u7406\u6a21\u62df<\/h2>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">1. Vue<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u63a5\u6536\u521d\u59cb\u5316\u9009\u9879<\/section>\n<\/li>\n<li>\n<section>\u628a data \u5c5e\u6027\u6ce8\u5165\u5b9e\u4f8b\uff0c\u53d8\u6210 getter\/setter<\/section>\n<\/li>\n<li>\n<section>\u8c03\u7528 observer \u76d1\u542c data<\/section>\n<\/li>\n<li>\n<section>\u8c03\u7528 compiler \u89e3\u6790\u6307\u4ee4\u548c\u63d2\u503c<\/section>\n<\/li>\n<\/ul>\n<p style=\"margin: 1em 0px;\"><img decoding=\"async\" src=\"file:\/\/H:\\yuguoxy\\%E6%95%99%E5%AD%A6\\03web%E5%89%8D%E7%AB%AF\\%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0\\vue%E7%9B%B8%E5%85%B3\\media\\%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20210412103108.png\" alt=\"\" \/><a href=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103108.png\" rel=\"fancybox\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-3226\" src=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103108.png\" alt=\"\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103108\" width=\"224\" height=\"242\" \/><\/a><\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">class Vue {\n    constructor (options) {\n        \/\/ 1. \u4fdd\u5b58\u9009\u9879\u7684\u6570\u636e\n        this.$options = options || {}\n        this.$data = options.data || {}\n        const el = options.el\n        this.$el = typeof options.el === 'string' ? document.querySelector(el) : el\n        \/\/ 2. \u8d1f\u8d23\u628a data \u6ce8\u5165\u5230 Vue \u5b9e\u4f8b\n        this._proxyData(this.$data)\n        \/\/ 3. \u8d1f\u8d23\u8c03\u7528 Observer \u5b9e\u73b0\u6570\u636e\u52ab\u6301\n        new Observer(this.$data)\n        \/\/ 4. \u8d1f\u8d23\u8c03\u7528 Compiler \u89e3\u6790\u6307\u4ee4\/\u63d2\u503c\u8868\u8fbe\u5f0f\u7b49\n        new Compiler(this)\n    }\n    _proxyData (data) {\n        \/\/ \u904d\u5386 data \u7684\u6240\u6709\u5c5e\u6027\n        Object.keys(data).forEach(key =&gt; {\n            Object.defineProperty(this, key, {\n                get () {\n                    return data[key]\n                },\n                set (newValue) {\n                    if (data[key] === newValue) {\n                        return\n                    }\n                    data[key] = newValue\n                }\n            })\n        })\n    }\n}<\/code><\/pre>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">2. Observer<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u628a data \u5c5e\u6027\u53d8\u6210\u54cd\u5e94\u5f0f<\/section>\n<\/li>\n<li>\n<section>\u5c5e\u6027\u82e5\u662f\u5bf9\u8c61\uff0c\u7ee7\u7eed\u9012\u5f52<\/section>\n<\/li>\n<li>\n<section>\u6570\u636e\u53d8\u5316\u53d1\u901a\u77e5<\/section>\n<\/li>\n<\/ul>\n<p style=\"margin: 1em 0px;\"><img decoding=\"async\" src=\"file:\/\/H:\\yuguoxy\\%E6%95%99%E5%AD%A6\\03web%E5%89%8D%E7%AB%AF\\%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0\\vue%E7%9B%B8%E5%85%B3\\media\\%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20210412103145.png\" alt=\"\" \/><a href=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103145.png\" rel=\"fancybox\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-3227\" src=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103145.png\" alt=\"\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103145\" width=\"262\" height=\"245\" \/><\/a><\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">\/\/ \u8d1f\u8d23\u6570\u636e\u52ab\u6301\n\/\/ \u628a $data \u4e2d\u7684\u6210\u5458\u8f6c\u6362\u6210 getter\/setter\nclass Observer {\n    constructor(data) {\n        this.walk(data)\n    }\n    \/\/ 1. \u5224\u65ad\u6570\u636e\u662f\u5426\u662f\u5bf9\u8c61\uff0c\u5982\u679c\u4e0d\u662f\u5bf9\u8c61\u8fd4\u56de\n    \/\/ 2. \u5982\u679c\u662f\u5bf9\u8c61\uff0c\u904d\u5386\u5bf9\u8c61\u7684\u6240\u6709\u5c5e\u6027\uff0c\u8bbe\u7f6e\u4e3a getter\/setter\n    walk(data) {\n        if (!data || typeof data !== 'object') {\n            return\n        }\n        \/\/ \u904d\u5386 data \u7684\u6240\u6709\u6210\u5458\n        Object.keys(data).forEach(key =&gt; {\n            this.defineReactive(data, key, data[key])\n        })\n    }\n    \/\/ \u5b9a\u4e49\u54cd\u5e94\u5f0f\u6210\u5458\n    defineReactive(data, key, val) {\n        const that = this\n        \/\/ \u5982\u679c val \u662f\u5bf9\u8c61\uff0c\u7ee7\u7eed\u8bbe\u7f6e\u5b83\u4e0b\u9762\u7684\u6210\u5458\u4e3a\u54cd\u5e94\u5f0f\u6570\u636e\n        this.walk(val)\n        Object.defineProperty(data, key, {\n            configurable: true,\n            enumerable: true,\n            get() {\n                return val\n            },\n            set(newValue) {\n                if (newValue === val) {\n                    return\n                }\n                \/\/ \u5982\u679c newValue \u662f\u5bf9\u8c61\uff0c\u8bbe\u7f6e newValue \u7684\u6210\u5458\u4e3a\u54cd\u5e94\u5f0f\n                that.walk(newValue)\n                val = newValue\n            }\n        })\n    }\n}<\/code><\/pre>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">3. Compiler<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u7f16\u8bd1\u6a21\u677f\uff0c\u89e3\u6790\u6307\u4ee4\/\u63d2\u503c<\/section>\n<\/li>\n<li>\n<section>\u8d1f\u8d23\u9996\u6b21\u6e32\u67d3<\/section>\n<\/li>\n<li>\n<section>\u6570\u636e\u53d8\u5316\u540e\u66f4\u65b0\u89c6\u56fe<\/section>\n<\/li>\n<\/ul>\n<p style=\"margin: 1em 0px;\"><img decoding=\"async\" src=\"file:\/\/H:\\yuguoxy\\%E6%95%99%E5%AD%A6\\03web%E5%89%8D%E7%AB%AF\\%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0\\vue%E7%9B%B8%E5%85%B3\\media\\%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20210412103226.png\" alt=\"\" \/><a href=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103226.png\" rel=\"fancybox\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-3228\" src=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103226.png\" alt=\"\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103226\" width=\"224\" height=\"245\" \/><\/a><\/p>\n<p style=\"margin: 1em 0px;\"><strong style=\"color: #4870ac;\">\u2460 compile()<\/strong><\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">\/\/ \u8d1f\u8d23\u89e3\u6790\u6307\u4ee4\/\u63d2\u503c\u8868\u8fbe\u5f0f\nclass Compiler {\n    constructor(vm) {\n        this.vm = vm\n        this.el = vm.$el\n        \/\/ \u7f16\u8bd1\u6a21\u677f\n        this.compile(this.el)\n    }\n    \/\/ \u7f16\u8bd1\u6a21\u677f\n    \/\/ \u5904\u7406\u6587\u672c\u8282\u70b9\u548c\u5143\u7d20\u8282\u70b9\n    compile(el) {\n        const nodes = el.childNodes\n        Array.from(nodes).forEach(node =&gt; {\n            \/\/ \u5224\u65ad\u662f\u6587\u672c\u8282\u70b9\u8fd8\u662f\u5143\u7d20\u8282\u70b9\n            if (this.isTextNode(node)) {\n                this.compileText(node)\n            } else if (this.isElementNode(node)) {\n                this.compileElement(node)\n            }\n            if (node.childNodes &amp;&amp; node.childNodes.length) {\n                \/\/ \u5982\u679c\u5f53\u524d\u8282\u70b9\u4e2d\u8fd8\u6709\u5b50\u8282\u70b9\uff0c\u9012\u5f52\u7f16\u8bd1\n                this.compile(node)\n            }\n        })\n    }\n    \/\/ \u5224\u65ad\u662f\u5426\u662f\u6587\u672c\u8282\u70b9\n    isTextNode(node) {\n        return node.nodeType === 3\n    }\n    \/\/ \u5224\u65ad\u662f\u5426\u662f\u5c5e\u6027\u8282\u70b9\n    isElementNode(node) {\n        return node.nodeType === 1\n    }\n    \/\/ \u5224\u65ad\u662f\u5426\u662f\u4ee5 v- \u5f00\u5934\u7684\u6307\u4ee4\n    isDirective(attrName) {\n        return attrName.startsWith('v-')\n    }\n    \/\/ \u7f16\u8bd1\u6587\u672c\u8282\u70b9\n    compileText(node) {\n    }\n    \/\/ \u7f16\u8bd1\u5c5e\u6027\u8282\u70b9\n    compileElement(node) {\n    }\n}<\/code><\/pre>\n<p style=\"margin: 1em 0px;\"><strong style=\"color: #4870ac;\">\u2461 compileText()<\/strong><\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">\/\/ \u7f16\u8bd1\u6587\u672c\u8282\u70b9\ncompileText(node) {\n    const reg = \/\\{\\{(.+)\\}\\}\/\n    \/\/ \u83b7\u53d6\u6587\u672c\u8282\u70b9\u7684\u5185\u5bb9\n    const value = node.textContent\n    if (reg.test(value)) {\n        \/\/ \u63d2\u503c\u8868\u8fbe\u5f0f\u4e2d\u7684\u503c\u5c31\u662f\u6211\u4eec\u8981\u7684\u5c5e\u6027\u540d\u79f0\n        const key = RegExp.$1.trim()\n        \/\/ \u628a\u63d2\u503c\u8868\u8fbe\u5f0f\u66ff\u6362\u6210\u5177\u4f53\u7684\u503c\n        node.textContent = value.replace(reg, this.vm[key])\n    }\n}<\/code><\/pre>\n<p style=\"margin: 1em 0px;\"><strong style=\"color: #4870ac;\">\u2462 compileElement()\uff1av-text \/ v-model \u9996\u6b21\u6e32\u67d3<\/strong><\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">\/\/ \u7f16\u8bd1\u5c5e\u6027\u8282\u70b9\ncompileElement(node) {\n    \/\/ \u904d\u5386\u5143\u7d20\u8282\u70b9\u4e2d\u7684\u6240\u6709\u5c5e\u6027\uff0c\u627e\u5230\u6307\u4ee4\n    Array.from(node.attributes).forEach(attr =&gt; {\n        \/\/ \u83b7\u53d6\u5143\u7d20\u5c5e\u6027\u7684\u540d\u79f0\n        let attrName = attr.name\n        \/\/ \u5224\u65ad\u5f53\u524d\u7684\u5c5e\u6027\u540d\u79f0\u662f\u5426\u662f\u6307\u4ee4\n        if (this.isDirective(attrName)) {\n            \/\/ attrName \u7684\u5f62\u5f0f v-text v-model\n            \/\/ \u622a\u53d6\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u83b7\u53d6 text model\n            attrName = attrName.substr(2)\n            \/\/ \u83b7\u53d6\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u5c5e\u6027\u7684\u540d\u79f0\u5c31\u662f\u6211\u4eec\u6570\u636e\u5bf9\u8c61\u7684\u5c5e\u6027 v-text=\"name\"\uff0c\u83b7\u53d6\u7684\u662fname\n            const key = attr.value\n            \/\/ \u5904\u7406\u4e0d\u540c\u7684\u6307\u4ee4\n            this.update(node, key, attrName)\n        }\n    })\n}\n\/\/ \u8d1f\u8d23\u66f4\u65b0 DOM\n\/\/ \u521b\u5efa Watcher\nupdate(node, key, dir) {\n    \/\/ node \u8282\u70b9\uff0ckey \u6570\u636e\u7684\u5c5e\u6027\u540d\u79f0\uff0cdir \u6307\u4ee4\u7684\u540e\u534a\u90e8\u5206\n    const updaterFn = this[dir + 'Updater']\n    updaterFn &amp;&amp; updaterFn(node, this.vm[key])\n}\n\/\/ v-text \u6307\u4ee4\u7684\u66f4\u65b0\u65b9\u6cd5\ntextUpdater(node, value) {\n    node.textContent = value\n}\n\/\/ v-model \u6307\u4ee4\u7684\u66f4\u65b0\u65b9\u6cd5\nmodelUpdater(node, value) {\n    node.value = value\n}<\/code><\/pre>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">4. Dep<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u6536\u96c6\u4f9d\u8d56\uff0c\u6dfb\u52a0 watcher<\/section>\n<\/li>\n<li>\n<section>\u901a\u77e5\u6240\u6709\u89c2\u5bdf\u8005<\/section>\n<\/li>\n<\/ul>\n<p style=\"margin: 1em 0px;\"><img decoding=\"async\" src=\"file:\/\/H:\\yuguoxy\\%E6%95%99%E5%AD%A6\\03web%E5%89%8D%E7%AB%AF\\%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0\\vue%E7%9B%B8%E5%85%B3\\media\\%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20210412103310.png\" alt=\"\" \/><a href=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103310.png\" rel=\"fancybox\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-3229\" src=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103310.png\" alt=\"\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103310\" width=\"223\" height=\"237\" \/><\/a><\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">class Dep {\n    constructor() {\n        \/\/ \u5b58\u50a8\u6240\u6709\u7684\u89c2\u5bdf\u8005\n        this.subs = []\n    }\n    \/\/ \u6dfb\u52a0\u89c2\u5bdf\u8005\n    addSub(sub) {\n        if (sub &amp;&amp; sub.update) {\n            this.subs.push(sub)\n        }\n    }\n    \/\/ \u901a\u77e5\u6240\u6709\u89c2\u5bdf\u8005\n    notify() {\n        this.subs.forEach(sub =&gt; {\n            sub.update()\n        })\n    }\n}\n\/\/ \u4ee5\u4e0b\u4ee3\u7801\u5728 Observer \u7c7b\u4e2d defineReactive \u65b9\u6cd5\u4e2d\u6dfb\u52a0\n\/\/ \u521b\u5efa dep \u5bf9\u8c61\u6536\u96c6\u4f9d\u8d56\nconst dep = new Dep()\n\/\/ getter \u4e2d\n\/\/ get \u7684\u8fc7\u7a0b\u4e2d\u6536\u96c6\u4f9d\u8d56\nDep.target &amp;&amp; dep.addSub(Dep.target)\n\/\/ setter \u4e2d\n\/\/ \u5f53\u6570\u636e\u53d8\u5316\u4e4b\u540e\uff0c\u53d1\u9001\u901a\u77e5\ndep.notify()<\/code><\/pre>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">5. Watcher<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u6570\u636e\u53d8\u5316\u65f6 Dep \u901a\u77e5\u6240\u6709 Watcher \u66f4\u65b0\u89c6\u56fe<\/section>\n<\/li>\n<li>\n<section>\u5b9e\u4f8b\u5316\u65f6\u628a\u81ea\u5df1\u52a0\u8fdb Dep<\/section>\n<\/li>\n<\/ul>\n<p style=\"margin: 1em 0px;\"><img decoding=\"async\" src=\"file:\/\/H:\\yuguoxy\\%E6%95%99%E5%AD%A6\\03web%E5%89%8D%E7%AB%AF\\%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0\\vue%E7%9B%B8%E5%85%B3\\media\\%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20210412103341.png\" alt=\"\" \/><a href=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103341.png\" rel=\"fancybox\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-3230\" src=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103341.png\" alt=\"\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103341\" width=\"222\" height=\"240\" \/><\/a><\/p>\n<pre style=\"overflow: auto hidden; word-break: normal; white-space: pre; tab-size: 2; border-radius: 5px; line-height: 2; margin: 1em 0.5em; padding: 0.5em; box-shadow: rgba(0, 0, 0, 0.55) 0px 1px 5px; font-size: 12px; background: #002b36; max-width: 100%; overflow-wrap: normal;\"><code class=\"hljs\" style=\"word-break: normal; white-space: nowrap; tab-size: 2; font-size: 12px; font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Roboto Mono', 'Courier New', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; margin: 0.5em; padding: 3px 5px; color: #93a1a1; background: #002b36; overflow-wrap: normal;\">class Watcher {\n    constructor(vm, key, cb) {\n        this.vm = vm\n        \/\/ data \u4e2d\u7684\u5c5e\u6027\u540d\u79f0\n        this.key = key\n        \/\/ \u5f53\u6570\u636e\u53d8\u5316\u7684\u65f6\u5019\uff0c\u8c03\u7528 cb \u66f4\u65b0\u89c6\u56fe\n        this.cb = cb\n        \/\/ \u5728 Dep \u7684\u9759\u6001\u5c5e\u6027\u4e0a\u8bb0\u5f55\u5f53\u524d watcher \u5bf9\u8c61\uff0c\u5f53\u8bbf\u95ee\u6570\u636e\u7684\u65f6\u5019\u628a watcher \u6dfb\u52a0\u5230dep \u7684 subs \u4e2d\n        Dep.target = this\n        \/\/ \u89e6\u53d1\u4e00\u6b21 getter\uff0c\u8ba9 dep \u4e3a\u5f53\u524d key \u8bb0\u5f55 watcher\n        this.oldValue = vm[key]\n        \/\/ \u6e05\u7a7a target\n        Dep.target = null\n    }\n    update() {\n        const newValue = this.vm[this.key]\n        if (this.oldValue === newValue) {\n            return\n        }\n        this.cb(newValue)\n    }\n}\n\n\/\/ \u5728 compiler.js(\u5373Compiler\u7c7b) \u4e2d\u4e3a\u6bcf\u4e00\u4e2a\u6307\u4ee4\/\u63d2\u503c\u8868\u8fbe\u5f0f\u521b\u5efa watcher \u5bf9\u8c61\uff0c\u76d1\u89c6\u6570\u636e\u7684\u53d8\u5316\ncompileText(node) {\n    const reg = \/\\{\\{(.+?)\\}\\}\/\n    const value = node.textContent\n    if (reg.test(value)) {\n        const key = RegExp.$1.trim()\n        node.textContent = value.replace(reg, this.vm[key])\n        \/\/ \u7f16\u8bd1\u5dee\u503c\u8868\u8fbe\u5f0f\u4e2d\u521b\u5efa\u4e00\u4e2a watcher\uff0c\u89c2\u5bdf\u6570\u636e\u7684\u53d8\u5316\n        new Watcher(this.vm, key, newValue =&gt; {\n            node.textContent = newValue\n        })\n    }\n}\n\/\/ \u56e0\u4e3a\u5728 textUpdater\u7b49\u4e2d\u8981\u4f7f\u7528 this\nupdaterFn &amp;&amp; updaterFn.call(this, node, this.vm[key], key)\n\/\/ v-text \u6307\u4ee4\u7684\u66f4\u65b0\u65b9\u6cd5\ntextUpdater(node, value, key) {\n    node.textContent = value\n    \/\/ \u6bcf\u4e00\u4e2a\u6307\u4ee4\u4e2d\u521b\u5efa\u4e00\u4e2a watcher\uff0c\u89c2\u5bdf\u6570\u636e\u7684\u53d8\u5316\n    new Watcher(this.vm, key, value =&gt; {\n        node.textContent = value\n    })\n}\n\n\/\/ \u89c6\u56fe\u53d8\u5316\u66f4\u65b0\u6570\u636e\n\/\/ v-model \u6307\u4ee4\u7684\u66f4\u65b0\u65b9\u6cd5\nmodelUpdater(node, value, key) {\n    node.value = value\n    \/\/ \u6bcf\u4e00\u4e2a\u6307\u4ee4\u4e2d\u521b\u5efa\u4e00\u4e2a watcher\uff0c\u89c2\u5bdf\u6570\u636e\u7684\u53d8\u5316\n    new Watcher(this.vm, key, value =&gt; {\n        node.value = value\n    })\n    \/\/ \u76d1\u542c\u89c6\u56fe\u7684\u53d8\u5316\n    node.addEventListener('input', () =&gt; {\n        this.vm[key] = node.value\n    })\n}<\/code><\/pre>\n<h2 style=\"padding: 1px 12.5px; color: #ffffff; margin: 1.2em 0px 1em; border-radius: 4px; display: inline-block; background-color: #4870ac; font-size: 1.3em;\">\u4e09\u3001\u603b\u7ed3<\/h2>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">1. \u4e24\u4e2a\u95ee\u9898<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u7ed9\u5c5e\u6027\u91cd\u65b0\u8d4b\u503c\u4e3a\u5bf9\u8c61\uff0c\u8fd8\u662f\u4e0d\u662f\u54cd\u5e94\u5f0f\uff1f\uff08Observer.walk \u5bf9\u65b0\u5bf9\u8c61\u4f1a\u518d defineReactive\uff09<\/section>\n<\/li>\n<li>\n<section>\u7ed9 Vue \u5b9e\u4f8b\u65b0\u589e\u6210\u5458\u662f\u4e0d\u662f\u54cd\u5e94\u5f0f\uff1f\uff08\u6ca1\u6709\u9884\u5148 defineProperty \u5219\u4e0d\u662f\uff09<\/section>\n<\/li>\n<\/ul>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">2. \u6574\u4f53\u6d41\u7a0b<\/h3>\n<p style=\"margin: 1em 0px;\"><img decoding=\"async\" src=\"file:\/\/H:\\yuguoxy\\%E6%95%99%E5%AD%A6\\03web%E5%89%8D%E7%AB%AF\\%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0\\vue%E7%9B%B8%E5%85%B3\\media\\%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20210412103429.png\" alt=\"\" \/><a href=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_202104121034291.png\" rel=\"fancybox\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-3233\" src=\"https:\/\/ai.zhousir.top\/wp-content\/uploads\/2021\/04\/\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_202104121034291.png\" alt=\"\u256c\u0432\u2568\u253c\u255c\u256a\u2550\u255d_20210412103429\" width=\"1254\" height=\"541\" \/><\/a><\/p>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">3. Vue<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u8bb0\u4e0b\u9009\u9879\uff0c\u8bbe\u7f6e $data \/ $el<\/section>\n<\/li>\n<li>\n<section>\u628a data \u6210\u5458\u6ce8\u5165\u5b9e\u4f8b<\/section>\n<\/li>\n<li>\n<section>\u8c03\u7528 Observer \u505a\u6570\u636e\u52ab\u6301<\/section>\n<\/li>\n<li>\n<section>\u8c03\u7528 Compiler \u7f16\u8bd1\u6307\u4ee4\u548c\u63d2\u503c<\/section>\n<\/li>\n<\/ul>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">4. Observer<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u6210\u5458\u548c\u591a\u5c42\u5c5e\u6027\u8f6c getter\/setter\uff1b\u8d4b\u65b0\u5bf9\u8c61\u65f6\u7ee7\u7eed\u8bbe\u7f6e<\/section>\n<\/li>\n<li>\n<section>\u5efa\u7acb Dep \u4e0e Watcher \u5173\u7cfb<\/section>\n<\/li>\n<li>\n<section>\u53d8\u5316\u65f6 notify<\/section>\n<\/li>\n<\/ul>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">5. Compiler<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u7f16\u8bd1\u6a21\u677f<\/section>\n<\/li>\n<li>\n<section>\u9996\u6b21\u6e32\u67d3<\/section>\n<\/li>\n<li>\n<section>\u6570\u636e\u53d8\u5316\u540e\u91cd\u6e32\u67d3<\/section>\n<\/li>\n<\/ul>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">6. Dep<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u6536\u96c6\u4f9d\u8d56<\/section>\n<\/li>\n<li>\n<section>\u901a\u77e5\u8ba2\u9605\u8005<\/section>\n<\/li>\n<\/ul>\n<h3 style=\"padding: 0px; color: #4870ac; margin: 1.2em 0px 1em; font-size: 1.3em;\">7. Watcher<\/h3>\n<ul style=\"padding-left: 1rem; margin-left: 1rem; font-size: 0.9rem; list-style-type: disc;\">\n<li>\n<section>\u5b9e\u4f8b\u5316\u65f6\u52a0\u5165 dep<\/section>\n<\/li>\n<li>\n<section>\u6536\u5230\u901a\u77e5\u540e\u56de\u8c03\u66f4\u65b0 DOM<\/section>\n<\/li>\n<\/ul>\n<p style=\"margin: 1em 0px;\">\u539f\u6587\uff1a<a class=\"url\" href=\"https:\/\/juejin.cn\/post\/6946120511713705992\" target=\"_blank\" rel=\"noopener\">https:\/\/juejin.cn\/post\/6946120511713705992<\/a><\/p>\n<table style=\"display: table; text-align: left; overflow: auto; border-collapse: collapse; margin: 1.4em auto; max-width: 100%; table-layout: fixed; overflow-wrap: break-word; word-break: break-all;\" width=\"800\">\n<thead>\n<tr>\n<th style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top; text-align: center; font-weight: bold; color: #4870ac; background: #f7f7f7;\">\u89d2\u8272<\/th>\n<th style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top; text-align: center; font-weight: bold; color: #4870ac; background: #f7f7f7;\">\u804c\u8d23<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">Vue<\/td>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">\u9009\u9879\u3001$data \u4ee3\u7406\u3001\u542f\u52a8 Observer\/Compiler<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">Observer<\/td>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">defineProperty \/ \u9012\u5f52\u5bf9\u8c61<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">Compiler<\/td>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">\u6307\u4ee4\u4e0e {{}} \uff0c\u9996\u6b21\u6e32\u67d3<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">Dep<\/td>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">subs + notify<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">Watcher<\/td>\n<td style=\"border: 1px solid #d9dfe4; padding: 9px 12px; font-size: 0.75em; line-height: 22px; vertical-align: top;\">Dep.target \u6536\u96c6\uff0cupdate \u89c6\u56fe<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<blockquote style=\"display: block; font-size: 0.9em; border-left: 3px solid #4870ac; padding: 0.5em 1em; margin: 0px; background: #f6f8fa; color: #40464f;\">\n<p style=\"margin: 1em 0px;\"><strong style=\"color: #4870ac;\">\u4e00\u53e5\u8bdd\u603b\u7ed3\uff1aVue2 \u54cd\u5e94\u5f0f\u662f defineProperty \u52ab\u6301 + Dep \u6536\u96c6 Watcher\uff1a\u6539\u6570\u636e\u8d70 setter \u901a\u77e5\uff0cCompiler \u8d1f\u8d23\u628a\u6307\u4ee4\u548c\u63d2\u503c\u63a5\u5230\u8fd9\u4e9b Watcher \u4e0a\u3002<\/strong><\/p>\n<\/blockquote>\n<\/section>\n","protected":false},"excerpt":{"rendered":"<p>Vue \u6700\u72ec\u7279\u7684\u4e00\u70b9\u662f \u6570\u636e\u9a71\u52a8\uff1a\u6539\u6570\u636e\u5c31\u6539\u89c6\u56fe\uff0c\u5c11\u624b\u5199 DOM\u3002\u672c\u7bc7\u5148\u5bf9\u9f50\u6570\u636e\u54cd\u5e94\u5f0f\u3001\u53d1\u5e03\u8ba2\u9605\u548c\u89c2\u5bdf\u8005\uff0c\u518d\u6a21 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3498,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[106,105],"tags":[205],"_links":{"self":[{"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=\/wp\/v2\/posts\/3223"}],"collection":[{"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3223"}],"version-history":[{"count":3,"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=\/wp\/v2\/posts\/3223\/revisions"}],"predecessor-version":[{"id":3693,"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=\/wp\/v2\/posts\/3223\/revisions\/3693"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=\/wp\/v2\/media\/3498"}],"wp:attachment":[{"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ai.zhousir.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}