摘要:依赖收集观察数据添加到中编译为抽象语法树这里要简单得多获取设置为根节点,传入的指令名指令对应指令所属实例指令对应值绑定属性值
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数据添加到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}设置${newVal}`); if (value !== newVal) { value = newVal; binding._directives.forEach(item => item.update()); } } }); } } } _compile(root) { // root为根节点,传入的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; // 指令对应dom this.vm = vm; // 指令所属实例 this.exp = exp; // 指令对应值 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++; } } });
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/103078.html
摘要:上一篇写了实现框架的一些基本概念本篇用代码来实现一个完整的框架思考假设有如下代码,里面的会和试图中的一一映射,修改的值,会直接引起试图中对应数据的变化如何实现上述呢回想下这篇讲的观察者模式和数据监听主题是什么观察者是什么观察者何时订阅主题主 上一篇写了实现 MVVM 框架的一些基本概念 本篇用代码来实现一个完整的 MVVM 框架 思考 假设有如下代码,data里面的name会和试图中的...
摘要:小白一枚,一直使用的是,想要多了解一些其它的框架,正好最近越来越火热,上的数已经超过了。框架理解说起这个模型,就不得不说框架。函数表示创建一个文本节点,函数表示创建一个数组。 小白一枚,一直使用的是React,想要多了解一些其它的框架,正好最近Vue越来越火热,Github上的Star数已经超过了React。而其背后蕴含的MVVM框架思想也一直跟React的组件化开发思想并驾齐驱,在这...
摘要:在前端页面中,把用纯对象表示,负责显示,两者做到了最大化的分离把和关联起来的就是。了解了思想后,自己用原生实现一个框架。注意数据描述符和存储描述符不能同时存在,否则会报错报错数据拦截使用来实现数据拦截,从而实现数据监听。 在前端页面中,把 Model 用纯 JS 对象表示,View 负责显示,两者做到了最大化的分离 把 Model 和 View 关联起来的就是 ViewModel。Vi...
摘要:框架的诞生以上便是一个简短精简的风格的学生信息的示例。至此,一个精简的框架其实已经出来了什么你确定不是在开玩笑一个只有十行的框架请记住框架是对如何组织代码和整个项目如何通用运作的抽象。 前言 MVVM模式相信做前端的人都不陌生,去网上搜MVVM,会出现一大堆关于MVVM模式的博文,但是这些博文大多都只是用图片和文字来进行抽象的概念讲解,对于刚接触MVVM模式的新手来说,这些概念虽然能够...
摘要:为了将对象和视图绑定在一起,我们需要设置一个回调函数,当对象的属性发生改变时发送一个更新视图的通知。下面是值发生变化的时候调用的回调函数,当然现在我们可以使用更简单的进行数据的监听,这在我们后面的将会讲到。 MVC MVC是一种设计模式,它将应用划分为3个部分:数据(模型)、展示层(视图)和用户交互层。结合一下下图,更能理解三者之间的关系。showImg(https://segment...
阅读 3368·2021-11-24 09:38
阅读 1371·2021-11-22 15:08
阅读 1428·2021-09-29 09:35
阅读 456·2021-09-02 15:11
阅读 1282·2019-08-30 12:55
阅读 364·2019-08-29 17:16
阅读 475·2019-08-29 11:30
阅读 386·2019-08-26 13:23