实现vue中的MVVM原理

现成MVVM

菜单教程


Vue 测试实例 - 菜鸟教程(runoob.com)

{{ message }}

视图影响数据

clipboard.png

数据影响视图

clipboard.png

项目构架


Document


Vue 测试实例 - 菜鸟教程(runoob.com)
{{message}}
{{message}}

mvvm.html


Document


Vue 测试实例 - 菜鸟教程(runoob.com)
{{message}}
{{message}}

mvvm.js

class MVVM {constructor(options) {this.$el = options.el;this.$data = options.data;if (this.$el) {new Compile(this.$el);}}
}

compile

把dom节点,放在内存中操作(到35分钟)

class Compile {constructor(el, vm) {this.el = this.isElementNode(el) ? el : document.querySelector(el);this.vm = vm;if (this.el) {let fragment = this.node2frament(this.el);this.compile(fragment);}}//辅助方法isElementNode(node) {return node.nodeType === 1;}//核心方法compile(fragment) {let childNodes = fragment.childNodes;console.log(childNodes)}node2frament(el) {let fragment = document.createDocumentFragment();let firstChild;while (firstChild = el.firstChild) {fragment.appendChild(firstChild);}return fragment}
}

分类元素节点和文本节点(52分钟)

class Compile {constructor(el, vm) {this.el = this.isElementNode(el) ? el : document.querySelector(el);this.vm = vm;if (this.el) {let fragment = this.node2frament(this.el);this.compile(fragment);}}//辅助方法isElementNode(node) {return node.nodeType === 1;}isDirective(name) {return name.includes('v-')}//核心方法compileElement(node) {let attrs = node.attributes;Array.from(attrs).forEach(arrt => {let attrName = attr.name;if (this.isDirective(attrName)) {let expr = attr.value;}})}compileText(node) {let text = node.textContent;let reg = /\{\{([^}]+)\}\}/g;if (reg.test(text)) {}}compile(fragment) {let childNodes = fragment.childNodes;Array.from(childNodes).forEach(node => {if (this.isElementNode(node)) {this.compile(node)} else {console.log('text', node)}})}node2frament(el) {let fragment = document.createDocumentFragment();let firstChild;while (firstChild = el.firstChild) {fragment.appendChild(firstChild);}return fragment}
}

元素节点

clipboard.png

文本节点

clipboard.png

把data中的数据,显示在视图上(到1:16分)

class Compile {constructor(el, vm) {this.el = this.isElementNode(el) ? el : document.querySelector(el);this.vm = vm;if (this.el) {let fragment = this.node2frament(this.el);this.compile(fragment);this.el.appendChild(fragment)}}//辅助方法isElementNode(node) {return node.nodeType === 1;}isDirective(name) {return name.includes('v-')}//核心方法compileElement(node) {let attrs = node.attributes;Array.from(attrs).forEach(attr => {let attrName = attr.name;if (this.isDirective(attrName)) {let expr = attr.value;let [, type] = attrName.split('-');CompileUtil[type](node, this.vm, expr)}})}compileText(node) {console.log(node)let expr = node.textContent;let reg = /\{\{([^}]+)\}\}/g;if (reg.test(expr)) {CompileUtil['text'](node, this.vm, expr)}}compile(fragment) {let childNodes = fragment.childNodes;Array.from(childNodes).forEach(node => {if (this.isElementNode(node)) {this.compileElement(node)this.compile(node)} else {this.compileText(node)}})}node2frament(el) {let fragment = document.createDocumentFragment();let firstChild;while (firstChild = el.firstChild) {fragment.appendChild(firstChild);}return fragment}
}CompileUtil = {getVal(vm, expr) { // 获取实例上对应的数据expr = expr.split('.'); // [message,a]return expr.reduce((prev, next) => { // vm.$data.areturn prev[next];}, vm.$data);},getTextVal(vm, expr) { // 获取编译文本后的结果return expr.replace(/\{\{([^}]+)\}\}/g, (...arguments) => {return this.getVal(vm, arguments[1]);})},text(node, vm, expr) { //文本处理let updateFn = this.updater['textUpdater'];let value = this.getTextVal(vm, expr);updateFn && updateFn(node, value)},model(node, vm, expr) {let updateFn = this.updater['modelUpdater'];updateFn && updateFn(node, this.getVal(vm, expr));},updater: {textUpdater(node, value) {node.textContent = value;},modelUpdater(node, value) {node.value = value;}}
}

v-model类型

        modelUpdater(node, value) {node.value = value;console.log(node)console.log(value)console.log(node.value)}

clipboard.png

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.3

Copyright www.122dh.com Rights Reserved.