zoukankan      html  css  js  c++  java
  • 一个简单的MVVM雏形

    这是@尚春实现的MVVM,使用定时器轮询,只支持{{}}与input.value的修改。

    这只能算是一个玩具,真正的MVVM需要有更复杂的扫描机制,JS解析器,双向绑定链什么的。

    <!DOCTYPE html>
    <html>
    <head>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
      <meta charset="utf-8">
      <title>JS Bin</title>
      
    </head>
    <body>
      <div data-component="input">
        <template>
          <input type="text" name="username" tb-model="username" value="" />
          <span>{{ username }}</span>
        </template>
      </div>
      <script>
    var DIRECTIVE_ATTR_MODEL = 'tb-model',
        regMustache = /{{s*(w+)s*}}/g,
        slice = Array.prototype.slice;
    
    function boot() {
        var components = slice.call(document.querySelectorAll('[data-component]'), 0);
        components.forEach(function (el) {
            var component = el.getAttribute('data-component');
            bootComponent(el, window[component + 'Controller']);
        });
    }
    
    function bootComponent(el, controller) {
        var $scope = {},
            elFrag = el.querySelector('template').content.cloneNode(true);
        traverse(elFrag, $scope);
        el.appendChild(elFrag);
        controller($scope);
    }
    
    function traverse(root, $scope) {
        for (var el = root.firstChild; el; el = el.nextSibling) {
            parseElement(el, $scope);
            if (el) {
                traverse(el, $scope);
            }
        }
    }
    
    function parseElement(el, $scope) {
        if (el.nodeType === 1) {
            // element
            if (el.hasAttribute(DIRECTIVE_ATTR_MODEL)) {
                var model = el.getAttribute(DIRECTIVE_ATTR_MODEL);
                el.removeAttribute(DIRECTIVE_ATTR_MODEL);
                el.addEventListener('input', function () {
                    $scope[model] = this.value;        
                });
            }
        } else if (el.nodeType === 3) {
            // text node
            var text = el.textContent,
                tpl = [],
                lastIndex = 0,
                match = regMustache.exec(text);
            while (match) {
                tpl.push(text.substring(lastIndex, regMustache.lastIndex - match[0].length));
                tpl.push({
                    type: 'var',
                    content: match[1]
                });
                lastIndex = regMustache.lastIndex;
                match = regMustache.exec(text);
            }
            watch($scope, function () {
                text = '';
                tpl.forEach(function (item) {
                    text += typeof item === 'string' ? item : $scope[item.content];
                });
                el.textContent = text;
            });
        }
    }
    
    function watch($scope, cb) {
        var old = _.cloneDeep($scope),
            timer;
        timer = setInterval(function () {
            if (!_.isEqual($scope, old)) {
                cb($scope, old);
                old = _.cloneDeep($scope);
            }
        }, 50);
    }
    
    function inputController($scope) {
        $scope.username = 'spring';
    }
    
    boot();
      </script>
    </body>
    </html>
    

  • 相关阅读:
    (二)Vue + Element 案例
    npm使用快速的安装源(nrm)
    windows下安装pm2
    windows下Mongodb和Memcached安装笔记
    利用UnblockNeteaseMusic实现网易云破版权,并实现shell可快速访问
    mac下相关操作命令
    apache下设置域名多站点访问及禁止apache访问80端口
    判断密码是否含有字母数字
    隐藏手机号
    开发相关工具
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/3796079.html
Copyright © 2011-2022 走看看