浅析vue中的MVVM实现原理


Posted in Javascript onMarch 04, 2019

现成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>

视图影响数据

浅析vue中的MVVM实现原理

数据影响视图

浅析vue中的MVVM实现原理

项目构架

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

元素节点

浅析vue中的MVVM实现原理

文本节点

浅析vue中的MVVM实现原理

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

浅析vue中的MVVM实现原理

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery photoFrame 图片边框美化显示插件
Jun 28 Javascript
JavaScript作用域链使用介绍
Aug 29 Javascript
js中substring和substr的详细介绍与用法
Aug 29 Javascript
javascript删除元素节点removeChild()用法实例
May 26 Javascript
使用 JavaScript 进行函数式编程 (一) 翻译
Oct 02 Javascript
详解 javascript中offsetleft属性的用法
Nov 11 Javascript
JS动态修改网页body的背景色实例代码
Oct 07 Javascript
vue仿淘宝订单状态的tab切换效果
Jun 23 Javascript
详解在网页上通过JS实现文本的语音朗读
Mar 28 Javascript
vue-cli和v-charts实现可视化图表过程解析
Oct 08 Javascript
微信小程序实现选项卡滑动切换
Oct 22 Javascript
js基础语法与maven项目配置教程案例
Jul 15 Javascript
JavaScript实现的九种排序算法
Mar 04 #Javascript
如何在JavaScript中优雅的提取循环内数据详解
Mar 04 #Javascript
iview tabs 顶部导航栏和模块切换栏的示例代码
Mar 04 #Javascript
Vuex mutitons和actions初使用详解
Mar 04 #Javascript
JS重学系列之聊聊new操作符
Mar 04 #Javascript
jQuery实现的导航条点击后高亮显示功能示例
Mar 04 #jQuery
ES10 特性的完整指南小结
Mar 04 #Javascript
You might like
消息持续发送的完整例子
2006/10/09 PHP
Laravel解决nesting level错误和隐藏index.php的问题
2019/10/12 PHP
从URL中提取参数与将对象转换为URL查询参数的实现代码
2012/01/12 Javascript
javascript 全选与全取消功能的实现代码
2012/12/23 Javascript
jquery获得option的值和对option进行操作
2013/12/13 Javascript
Javascript 浮点运算精度问题分析与解决
2014/03/26 Javascript
js模仿php中strtotime()与date()函数实现方法
2015/08/11 Javascript
详解javascript数组去重问题
2015/11/06 Javascript
微信小程序通过api接口将json数据展现到小程序示例
2017/01/20 Javascript
Webpack打包慢问题的完美解决方法
2017/03/16 Javascript
基于bootstrap实现bootstrap中文网巨幕效果
2017/05/02 Javascript
jquery实现图片轮播器
2017/05/23 jQuery
Vue下拉框回显并默认选中随机问题
2018/09/06 Javascript
详解NodeJs项目 CentOs linux服务器线上部署
2019/09/16 NodeJs
webpack HappyPack实战详解
2019/10/08 Javascript
原生javascript运动函数的封装示例【匀速、抛物线、多属性的运动等】
2020/02/23 Javascript
[40:12]Liquid vs Chaos 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python异常处理总结
2014/08/15 Python
Python写的英文字符大小写转换代码示例
2015/03/06 Python
python如何去除字符串中不想要的字符
2020/07/05 Python
多个应用共存的Django配置方法
2018/05/30 Python
对Python函数设计规范详解
2019/07/19 Python
浅析python中while循环和for循环
2019/11/19 Python
Python实现大数据收集至excel的思路详解
2020/01/03 Python
tensorflow安装成功import tensorflow 出现问题
2020/04/16 Python
详解webapp页面滚动卡顿的解决办法
2018/12/26 HTML / CSS
美国新蛋IT数码商城:Newegg.com
2016/07/21 全球购物
德国最大的网上鞋店之一:Schuhe24.de
2017/06/10 全球购物
微软美国官方网站:Microsoft美国
2018/05/10 全球购物
单位消防安全制度
2014/01/12 职场文书
运动会领导邀请函
2014/02/05 职场文书
安全生产计划书
2014/05/04 职场文书
委托书怎么写
2014/07/31 职场文书
春风化雨观后感
2015/06/11 职场文书
四大名著读书笔记
2015/06/25 职场文书
浅谈resultMap的用法及关联结果集映射
2021/06/30 Java/Android