zoukankan      html  css  js  c++  java
  • JGUI源码:实现简单MVVM单项绑定学习笔记(15)

    前面几节都是jquery界面方面的东西,本节研究些数据方面的东西:MVVM。

    MVVM由三部分组成:Model <=> ViewModel <=> View,当Model数据改变时,通知所有与Model关联的View进行数据更新。

    以vuejs一个简单例子实现为例:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Vue 测试实例</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
      <p>{{ message }}</p>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue.js!'
      }
    })
    </script>
    </body>
    </html>

    显示效果如下

    现在模拟实现这一过程,ES5,6语法以前也没怎么接触,在网上翻看大神的资料,看到一篇实现相对较完整的
    https://segmentfault.com/a/1190000016236834

    根据他的实现原理本文进行了简化,只模拟实现绑定过程(不能拿来用于生产环境),稍微有点javascript基础的应该都能看懂。下次面试时面试官问你原理你说可以手写一个。

    网上许多文章都是观察者,订阅者一堆名词,把读者都看晕了,其实核心代码就像下面这段代码这么简单.

    <body>
        <div id="app">
          <p>{{ message }}</p>
          <p>{{ message1 }}</p>
        </div>
        <div id="log"></div>
        <script>
          class JMVVM {
            constructor(p_obj) {
              this.init(p_obj);
            }
            init(p_obj) {
              $("#log").append("获取绑定对象初始化数据信息</br>");
              this.element = document.querySelector(p_obj.el);
              this.data = p_obj.data;
              $("#log").append("el:" + this.element.id + "</br>");
              for (let key in this.data) {
                let val = this.data[key];
                $("#log").append("key:" + key + "</br>");
                $("#log").append("1、给对象创建get,set方法</br>");
                let element=this.element;
                Object.defineProperty(this.data, key, {
                  configurable: true,
                  enumerable: true,
                  get() {
                    return val;
                  },
                  set(newVal) {
                    val = newVal;
                    let reg = eval("/{{([^}]*) "+key+" }}/g");
                    // let reg1 =  /{{([^}]*) +key+ }}/g;
                    let match;
                    $("#log").append("2、替换模板</br>");//模拟,只查找一级。
                    element.childNodes.forEach(childNode=>{
                        while ((match = reg.exec(childNode.textContent))) {
                            childNode.textContent=val;
                        }
                    })
                    // $("#log").append("2、替换模板</br>");
                    // for(let children in element.childNodes)
                    // while ((match = reg.exec(children.textContent))) {
                    //   children.textContent=val;
                    // }
                    
                  }
                });
           //触发set
    this.data[key] =val; } } } </script> <script> // new Vue({ // el: "#app", // data: { // message: "Hello Vue.js!" // } // }); new JMVVM({ el: "#app", data: { message1: "Hello JMVVM.js!" } }); </script> </body>

    执行结果如下

    上面写法比较简单,只能替换一次,因为替换后{{ message }}就不存在了,那么就应该在第一次替换成功时候将对应元素缓存下来,具体怎么实现有多种方法,如果理解的不对,欢迎大家指正。

     演示地址:www.jgui.com

    注释:

    ES6 新增了let命令,用来声明局部变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效,而且有暂时性死区的约束。

    后续:ES6对IE兼容性挺差的,如果是客户习惯使用低版本IE的话,尽量不要使用ES6或者让客户更换浏览器。

  • 相关阅读:
    [WPF系列] window自定义
    [WPF系列]-Prism+EF
    C#基础-事件 继承类无法直接引发基类的事件
    [WPF系列] 高级 调试
    [WPF系列]-DynamicResource与StaticResource的区别
    [WPF系列]-DataBinding 绑定计算表达式
    [WPF系列]- Style
    [WPF系列]-基础 TextBlock
    [WPF系列]-ListBox
    [WPF系列]-DataBinding 枚举类型数据源
  • 原文地址:https://www.cnblogs.com/zhaogaojian/p/10500519.html
Copyright © 2011-2022 走看看