【问题标题】:jQuery event callback runs only once (Angular-like framework development)jQuery 事件回调只运行一次(类 Angular 框架开发)
【发布时间】:2014-07-28 17:32:06
【问题描述】:

我正在构建一个 JS 框架来模拟 AngularJS 模型,仅用于教育目的。

问题是:我在模型(输入)更新时分配了一个回调来运行,但在它们第一次运行后,它们“消失”了。

在尝试使用 jQuery 执行此操作之前,我尝试使用 querySelectorAll 并遇到了同样的问题。

这里是:http://jsfiddle.net/YmY2w/

HTML

<div class="container" jd-app="test">
    <input type="text" jd-model="name" value="foo" /><br />
    <input type="text" jd-model="email" value="foo@foo" />
    <hr />
    <p>Name: {{ name }}</p>
    <p>Email: {{ email }}</p>
</div>

JAVASCRIPT

(function($, window, document, undefined) {
    'use strict';

    // registering models
    (function() {
        var $app = $('[jd-app]');
        var $models = $('[jd-model]', $app);

        $models.each(function(index) {
            UpdateModel.apply(this);
        });

        function UpdateModel() {
            var model = { name: $(this).attr('jd-model'), value: this.value }
            var re    = new RegExp('{{\\s+('+ model.name +')\\s+}}', 'gm');

            $('*', $app).each(function(index) {
                var $this = $(this);
                $this.text( $this.text().replace(re, model.value) );
            });

            $(this).on('keyup', UpdateModel);
        }
    })();

})(jQuery, window, document);

我做错了什么?有没有更好的方法来做到这一点?

【问题讨论】:

    标签: javascript jquery angularjs callback


    【解决方案1】:

    您遇到的问题是,当您的脚本第一次看到 {{ name }} 时,它会将其转换为模型“name”的值。但是在你的 html 中,你有文本“foo”而不是 {{ name }} (你试图搜索/替换的东西),所以你不能更新显示的文本。

    您需要做的是跟踪单个 DOM 节点(附加到特定模型),其中包含最初具有“{{ }}”的文本以及正确的模型名称。

    我在这里想出了一种丑陋的原型:

    http://jsfiddle.net/YmY2w/11/

    我不确定它在识别正确的模板位置方面有多灵活,但它可以作为我正在谈论的那种实现的演示。另外-我猜效率不是很高。 (但是 angularjs 也不是真的......)

    (function($, window, document, undefined) {
        'use strict';
    
        // From http://stackoverflow.com/questions/298750/how-do-i-select-text-nodes-with-jquery
        function getTextNodesIn(node, includeWhitespaceNodes) {
            var textNodes = [], nonWhitespaceMatcher = /\S/;
    
            function getTextNodes(node) {
                if (node.nodeType == 3) {
                    if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
                        textNodes.push(node);
                    }
                } else {
                    for (var i = 0, len = node.childNodes.length; i < len; ++i) {
                        getTextNodes(node.childNodes[i]);
                    }
                }
            }
    
            getTextNodes(node);
            return textNodes;
        }
    
        // registering models
        (function() {
            var $app = $('[jd-app]');
            var $models = $('[jd-model]', $app);
            var models = [];
    
            $models.each(function(index) {
                registerModel.apply(this);
            });
    
            function registerModel() {
              var model = { name: $(this).attr('jd-model'), value: this.value, domElements: [] };            
              var re    = new RegExp('{{\\s+('+ model.name +')\\s+}}', 'gm');
              $app.contents().each(function(index) {
              if ($(this).text().match(re)) {
                var textNodes = getTextNodesIn(this, false);
                console.log(textNodes);
                $.each(textNodes, function(index, elem) {
                  if (elem.nodeValue.match(re)) {
                    var text = elem.nodeValue;
                    var myArray = re.exec(text);
                    var match = myArray[0];
    
                    var firstIndex = text.indexOf(match);
    
                    var newElem = elem.splitText(firstIndex);
    
                    newElem.splitText(match.length);
    
                    model.domElements.push(newElem);
                 }
               });
             }
          });
    
          models.push(model);
    
          $(this).on('keyup', updateModel);
          $(this).trigger('keyup');
        }
    
    
            function updateModel() {
                var $input = $(this);
                $.each(models, function(index, model) {
                    if (model.name === $input.attr('jd-model')) {
                        var newVal = $input.val();
                        $.each(model.domElements, function(index, elem) {
                            elem.nodeValue = newVal;
                        });
                    }
                });
            }
    
        })();
    
    })(jQuery, window, document);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 2016-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多