摘要:依賴收集觀察數(shù)據(jù)添加到中編譯為抽象語法樹這里要簡單得多獲取設(shè)置為根節(jié)點,傳入的指令名指令對應(yīng)指令所屬實例指令對應(yīng)值綁定屬性值
Document
class MyVue { constructor(options) { this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$methods = options.methods; this._binding = {}; // 依賴收集 this._observe(this.$data); // 觀察data數(shù)據(jù)添加到Watcher中 this._compile(this.$el); // 編譯為抽象語法樹AST 這里要簡單得多 } _observe(obj) { for (let key in obj) { if (obj.hasOwnProperty(key)) { this._binding[key] = { _directives: [] }; console.log("this._binding[key]", this._binding[key]); let value = obj[key]; if (typeof value === "object") { this._observe(value); } let binding = this._binding[key]; Object.defineProperty(this.$data, key, { enumerable: true, configurable: true, get() { console.log(`${key}獲取${value}`); return value; }, set(newVal) { console.log(`${key}設(shè)置${newVal}`); if (value !== newVal) { value = newVal; binding._directives.forEach(item => item.update()); } } }); } } } _compile(root) { // root為根節(jié)點,傳入的el let _this = this; let nodes = root.children; for (let i = 0; i < nodes.length; i++) { let node = nodes[i]; if (node.children.length) { this._compile(node); } if (node.hasAttribute("v-click")) { node.onclick = (function () { let attrVal = nodes[i].getAttribute("v-click"); return _this.$methods[attrVal].bind(_this.$data); })(); } if ( node.hasAttribute("v-model") && (node.tagName === "INPUT" || node.tagName === "TEXTAREA") ) { node.addEventListener( "input", (function (key) { let attrVal = nodes[i].getAttribute("v-model"); _this._binding[attrVal]._directives.push( new Watcher("input", node, _this, attrVal, "value") ); return function () { _this.$data[attrVal] = nodes[key].value; }; })(i) ); } if (node.hasAttribute("v-bind")) { let attrVal = nodes[i].getAttribute("v-bind"); _this._binding[attrVal]._directives.push( new Watcher("text", node, _this, attrVal, "innerHTML") ); } } } } class Watcher { constructor(name, el, vm, exp, attr) { this.name = name; // 指令名 this.el = el; // 指令對應(yīng)dom this.vm = vm; // 指令所屬實例 this.exp = exp; // 指令對應(yīng)值 this.attr = attr; // 綁定屬性值 this.update(); } update() { this.el[this.attr] = this.vm.$data[this.exp]; } } var app = new MyVue({ el: "#app", data: { number: 0 }, methods: { increment() { this.number++; } } });
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/103078.html
摘要:上一篇寫了實現(xiàn)框架的一些基本概念本篇用代碼來實現(xiàn)一個完整的框架思考假設(shè)有如下代碼,里面的會和試圖中的一一映射,修改的值,會直接引起試圖中對應(yīng)數(shù)據(jù)的變化如何實現(xiàn)上述呢回想下這篇講的觀察者模式和數(shù)據(jù)監(jiān)聽主題是什么觀察者是什么觀察者何時訂閱主題主 上一篇寫了實現(xiàn) MVVM 框架的一些基本概念 本篇用代碼來實現(xiàn)一個完整的 MVVM 框架 思考 假設(shè)有如下代碼,data里面的name會和試圖中的...
摘要:小白一枚,一直使用的是,想要多了解一些其它的框架,正好最近越來越火熱,上的數(shù)已經(jīng)超過了??蚣芾斫庹f起這個模型,就不得不說框架。函數(shù)表示創(chuàng)建一個文本節(jié)點,函數(shù)表示創(chuàng)建一個數(shù)組。 小白一枚,一直使用的是React,想要多了解一些其它的框架,正好最近Vue越來越火熱,Github上的Star數(shù)已經(jīng)超過了React。而其背后蘊含的MVVM框架思想也一直跟React的組件化開發(fā)思想并駕齊驅(qū),在這...
摘要:在前端頁面中,把用純對象表示,負責(zé)顯示,兩者做到了最大化的分離把和關(guān)聯(lián)起來的就是。了解了思想后,自己用原生實現(xiàn)一個框架。注意數(shù)據(jù)描述符和存儲描述符不能同時存在,否則會報錯報錯數(shù)據(jù)攔截使用來實現(xiàn)數(shù)據(jù)攔截,從而實現(xiàn)數(shù)據(jù)監(jiān)聽。 在前端頁面中,把 Model 用純 JS 對象表示,View 負責(zé)顯示,兩者做到了最大化的分離 把 Model 和 View 關(guān)聯(lián)起來的就是 ViewModel。Vi...
摘要:框架的誕生以上便是一個簡短精簡的風(fēng)格的學(xué)生信息的示例。至此,一個精簡的框架其實已經(jīng)出來了什么你確定不是在開玩笑一個只有十行的框架請記住框架是對如何組織代碼和整個項目如何通用運作的抽象。 前言 MVVM模式相信做前端的人都不陌生,去網(wǎng)上搜MVVM,會出現(xiàn)一大堆關(guān)于MVVM模式的博文,但是這些博文大多都只是用圖片和文字來進行抽象的概念講解,對于剛接觸MVVM模式的新手來說,這些概念雖然能夠...
摘要:為了將對象和視圖綁定在一起,我們需要設(shè)置一個回調(diào)函數(shù),當(dāng)對象的屬性發(fā)生改變時發(fā)送一個更新視圖的通知。下面是值發(fā)生變化的時候調(diào)用的回調(diào)函數(shù),當(dāng)然現(xiàn)在我們可以使用更簡單的進行數(shù)據(jù)的監(jiān)聽,這在我們后面的將會講到。 MVC MVC是一種設(shè)計模式,它將應(yīng)用劃分為3個部分:數(shù)據(jù)(模型)、展示層(視圖)和用戶交互層。結(jié)合一下下圖,更能理解三者之間的關(guān)系。showImg(https://segment...
閱讀 3426·2021-11-24 09:38
閱讀 1409·2021-11-22 15:08
閱讀 1501·2021-09-29 09:35
閱讀 505·2021-09-02 15:11
閱讀 1328·2019-08-30 12:55
閱讀 414·2019-08-29 17:16
閱讀 518·2019-08-29 11:30
閱讀 446·2019-08-26 13:23