浅析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 Ajax xmlhttp请求成功问题
Feb 04 Javascript
Javascript节点关系实例分析
May 15 Javascript
判断数组是否包含某个元素的js函数实现方法
May 19 Javascript
基于JS代码实现实时显示系统时间
Jun 16 Javascript
jQuery实现iframe父窗体和子窗体的相互调用
Jun 17 Javascript
微信小程序中的onLoad详解及简单实例
Apr 05 Javascript
JavaScript中常见的八个陷阱总结
Jun 28 Javascript
原生js获取left值和top值的三种方法
Aug 02 Javascript
JS实现点击链接切换显示隐藏内容的方法
Oct 19 Javascript
详解使用React进行组件库开发
Feb 06 Javascript
jQuery实现的简单拖拽功能示例【测试可用】
Aug 14 jQuery
使用vue-router在Vue页面之间传递数据的方法
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
php使用base64加密解密图片示例分享
2014/01/20 PHP
win7 64位系统 配置php最新版开发环境(php+Apache+mysql)
2014/08/15 PHP
Laravel中七个非常有用但很少人知道的Carbon方法
2017/09/21 PHP
php+jQuery ajax实现的实时刷新显示数据功能示例
2019/09/12 PHP
16个最流行的JavaScript框架[推荐]
2011/05/29 Javascript
Javascript面向对象编程(二) 构造函数的继承
2011/08/28 Javascript
Jquery submit()无法提交问题
2013/04/21 Javascript
JavaScript中使用document.write向页面输出内容实例
2014/10/16 Javascript
javascript设置连续两次点击按钮时间间隔的方法
2014/10/28 Javascript
通过伪协议解决父页面与iframe页面通信的问题
2015/04/05 Javascript
详解JavaScript的while循环的使用
2015/06/03 Javascript
学习使用AngularJS文件上传控件
2016/02/16 Javascript
bootstrap表单按回车会自动刷新页面的解决办法
2017/03/08 Javascript
基于javascript 显式转换与隐式转换(详解)
2017/12/15 Javascript
Vue实现用户自定义字段显示数据的方法
2018/08/28 Javascript
用node撸一个监测复联4开售短信提醒的实现代码
2019/04/10 Javascript
vue将后台数据时间戳转换成日期格式
2019/07/31 Javascript
vue v-for出来的列表,点击某个li使得当前被点击的li字体变红操作
2020/07/17 Javascript
如何利用vue实现波谱拟合详解
2020/11/05 Javascript
[04:16]完美世界DOTA2联赛PWL S2 集锦第一期
2020/11/23 DOTA
python 将字符串转换成字典dict
2013/03/24 Python
Python求算数平方根和约数的方法汇总
2016/03/09 Python
python如何在列表、字典中筛选数据
2018/03/19 Python
pytorch实现mnist数据集的图像可视化及保存
2020/01/14 Python
Python嵌入C/C++进行开发详解
2020/06/09 Python
python连接mysql有哪些方法
2020/06/24 Python
如何基于python把文字图片写入word文档
2020/07/31 Python
Python通过fnmatch模块实现文件名匹配
2020/09/30 Python
详解canvas多边形(蜘蛛图)的画法示例
2018/01/29 HTML / CSS
金智子午JAVA面试题
2015/09/04 面试题
资产经营总监岗位职责范文
2013/12/01 职场文书
优秀班主任主要事迹材料
2014/12/16 职场文书
军训后的感想
2015/08/07 职场文书
生日宴会家属答谢词
2015/09/29 职场文书
学习党章心得体会2016
2016/01/15 职场文书
24年收藏2000多部退役军用电台
2022/02/18 无线电