当前位置: 移动技术网 > IT编程>脚本编程>vue.js > 浅析vue中的MVVM实现原理

浅析vue中的MVVM实现原理

2019年05月24日  | 移动技术网IT编程  | 我要评论

梅州旅游景点大全,恶魔岛第二季,松野秋鸣

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

视图影响数据

数据影响视图

项目构架

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

元素节点

文本节点

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网