浅析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 相关文章推荐
鼠标经过的文本框textbox变色
May 21 Javascript
Javascript拓展String方法小结
Jul 08 Javascript
js jquery ajax的几种用法总结(及优缺点介绍)
Jan 28 Javascript
javascript将异步校验表单改写为同步表单
Jan 27 Javascript
基于jquery实现的仿优酷图片轮播特效代码
Jan 13 Javascript
jQuery如何跳转到另一个网页 就这么简单
Dec 28 Javascript
vue.js实现的绑定class操作示例
Jul 06 Javascript
Vue中使用ElementUI使用第三方图标库iconfont的示例
Oct 11 Javascript
node获取客户端ip功能简单示例
Aug 24 Javascript
浅谈TypeScript的类型保护机制
Feb 23 Javascript
electron 如何将任意资源打包的方法步骤
Apr 16 Javascript
Vue路由切换页面不更新问题解决方案
Jul 10 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
采用memcache在web集群中实现session的同步会话
2014/07/05 PHP
thinkPHP删除前弹出确认框的简单实现方法
2016/05/16 PHP
PHP调用API接口实现天气查询功能的示例
2017/09/21 PHP
删除select中所有option选项jquery代码
2013/08/12 Javascript
JavaScript中的cacheStorage使用详解
2015/07/29 Javascript
Augularjs-起步详解
2016/07/08 Javascript
javascript 四十条常用技巧大全
2016/09/09 Javascript
KnockoutJS 3.X API 第四章之事件event绑定
2016/10/10 Javascript
js print打印网页指定区域内容的简单实例
2016/11/01 Javascript
bootstrap模态框消失问题的解决方法
2016/12/02 Javascript
javascript实现table单元格点击展开隐藏效果(实例代码)
2017/04/10 Javascript
javaScript 逻辑运算符使用技巧整理
2017/05/03 Javascript
Angular 2父子组件之间共享服务通信的实现
2017/07/04 Javascript
微信小程序 如何引入外部字体库iconfont的图标
2018/01/31 Javascript
浅谈vue-cli 3.0.x 初体验
2018/04/11 Javascript
vue2中引用及使用 better-scroll的方法详解
2018/11/15 Javascript
详解Vue 如何监听Array的变化
2019/06/06 Javascript
在PyCharm下打包*.py程序成.exe的方法
2018/11/29 Python
python 获取毫秒数,计算调用时长的方法
2019/02/20 Python
k-means 聚类算法与Python实现代码
2020/06/01 Python
粉红色的鲸鱼:Vineyard Vines
2018/02/17 全球购物
Stubhub英国:购买体育、演唱会和剧院门票
2018/06/10 全球购物
英国豪华装饰照明品牌的在线零售商:Inspyer Lighting
2019/12/10 全球购物
美国新娘礼品店:The Paisley Box
2020/09/08 全球购物
护士毕业实习感言
2014/03/05 职场文书
廉洁自律承诺书
2014/03/27 职场文书
爱国主义演讲稿
2014/05/07 职场文书
2014教育局对照检查材料思想汇报
2014/09/23 职场文书
2014年秘书工作总结
2014/11/25 职场文书
项目验收申请报告
2015/05/15 职场文书
2015年小学教科研工作总结
2015/07/20 职场文书
运动会主持人开幕词
2016/03/04 职场文书
2016年圣诞节义工活动总结
2016/04/01 职场文书
elementui的el-popover修改样式不生效的解决
2021/06/30 Javascript
js面向对象编程OOP及函数式编程FP区别
2022/07/07 Javascript
Win10服务全部禁用了怎么启动?Win10服务全部禁用解决方法
2022/09/23 数码科技