一个简单的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>


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM