首页 > 编程 > JavaScript > 正文

浅析vue中的MVVM实现原理

2019-11-19 12:02:43
字体:
来源:转载
供稿:网友

现成MVVM

菜单教程

<!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>  <script src="https://unpkg.com/vue/dist/vue.js"></script></head><body>  <div id="app">    <input type="text" v-model="message">    <p>{{ message }}</p>  </div>  <script>    let vm = new Vue({      el: '#app',      data: {        message: 'Hello Vue.js!'      }    })  </script></body></html>

视图影响数据

数据影响视图

项目构架

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <meta http-equiv="X-UA-Compatible" content="ie=edge">  <title>Document</title></head><body></body></html><!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>  <script src="./js/mvvm.js"></script>  <script src="./js/compile.js"></script></head><body>  <div id="app">    <input type="text" v-model="message">    <div>{{message}}</div>    <ul>      <li></li>    </ul>    {{message}}  </div>  <script>    let vm = new MVVM({      el: '#app',      data: {        message: 'Hello Vue.js!'      }    })  </script></body></html>

mvvm.html

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <meta http-equiv="X-UA-Compatible" content="ie=edge">  <title>Document</title></head><body></body></html><!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>  <script src="./js/mvvm.js"></script>  <script src="./js/compile.js"></script></head><body>  <div id="app">    <input type="text" v-model="message">    <div>{{message}}</div>    <ul>      <li></li>    </ul>    {{message}}  </div>  <script>    let vm = new MVVM({      el: '#app',      data: {        message: 'Hello Vue.js!'      }    })  </script></body></html>

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  }}

元素节点

文本节点

把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.a      return 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)    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表