浅析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 相关文章推荐
javascript 放大镜效果js组件 qsoft.PopBigImage.v0.35 加入了chrome支持
Apr 07 Javascript
分享十五个最佳jQuery 幻灯插件和教程
Mar 27 Javascript
同一页面多个商品倒计时JS 基于面向对象的javascript
Feb 16 Javascript
JS控制日期显示的小例子
Nov 23 Javascript
js表头排序实现方法
Jan 16 Javascript
Javascript中实现trim()函数的两种方法
Feb 04 Javascript
jQuery的each循环用法简单示例
Jun 12 Javascript
最全的Javascript编码规范(推荐)
Jun 22 Javascript
jQuery的$.extend 浅拷贝与深拷贝
Mar 08 Javascript
本地搭建微信小程序服务器的实现方法
Oct 27 Javascript
Angular实现表单验证功能
Nov 13 Javascript
Vue2.0生命周期的理解
Aug 20 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
PHP数组与对象之间使用递归实现转换的方法
2015/06/24 PHP
PHP实现的支付宝支付功能示例
2019/03/26 PHP
基于Laravel 多个中间件的执行顺序详解
2019/10/21 PHP
laravel框架创建授权策略实例分析
2019/11/22 PHP
聊聊 PHP 8 新特性 Attributes
2020/08/19 PHP
jQuery实现长文字部分显示代码
2013/05/13 Javascript
通过JS来判断页面控件是否获取焦点
2014/01/03 Javascript
js propertychange和oninput事件
2014/09/28 Javascript
浅谈JavaScript事件的属性列表
2015/03/01 Javascript
JS实现简单的键盘打字的效果
2015/04/24 Javascript
js实现兼容性好的微软官网导航下拉菜单效果
2015/09/07 Javascript
javascript轻量级库createjs使用Easel实现拖拽效果
2016/02/19 Javascript
PHP实现本地图片上传和验证功能
2017/02/27 Javascript
js实现功能比较全面的全选和多选
2017/03/02 Javascript
Javascript(es2016) import和require用法和区别详解
2017/08/11 Javascript
使用Webpack提升Vue.js应用程序的4种方法(翻译)
2019/10/09 Javascript
解决vue加scoped后就无法修改vant的UI组件的样式问题
2020/09/07 Javascript
Python入门教程之运算符与控制流
2016/08/17 Python
Python2实现的LED大数字显示效果示例
2017/09/04 Python
解决python 无法加载downsample模型的问题
2018/10/25 Python
详解小白之KMP算法及python实现
2019/04/04 Python
解决win7操作系统Python3.7.1安装后启动提示缺少.dll文件问题
2019/07/15 Python
Python随机函数库random的使用方法详解
2019/08/21 Python
Python爬取爱奇艺电影信息代码实例
2019/11/26 Python
Anaconda+Pycharm环境下的PyTorch配置方法
2020/03/13 Python
纯CSS3绘制打火机动画火焰效果
2016/07/18 HTML / CSS
HTML里显示pdf、word、xls、ppt的方法示例
2020/04/14 HTML / CSS
美国高端寝具品牌:Coyuchi
2017/02/08 全球购物
Pottery Barn阿联酋:购买家具、家居装饰及更多
2019/12/08 全球购物
Java里面有没有全局变量?为什么?
2015/02/06 面试题
小摄影师教学反思
2014/04/27 职场文书
作风整顿剖析材料
2014/09/30 职场文书
乡镇党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
皇城相府导游词
2015/02/06 职场文书
2015暑假社会调查报告
2015/07/13 职场文书
文艺委员竞选稿
2015/11/19 职场文书