【问题标题】:Javascript closure function not called on form submit表单提交时未调用 Javascript 闭包函数
【发布时间】:2013-01-03 10:14:16
【问题描述】:

这让我很困惑。我有一个文本框。你输入一些东西,然后按回车。 Javascript 以单独的形式创建一个只读输入元素。文本输入框旁边是删除它们的按钮。该表单底部还有一个提交按钮,用于提交所有只读文本输入。

由于单击表单内的按钮将提交表单(我只想删除包含按钮及其相应文本输入的父 div),因此在提交表单时会调用一个函数。此函数确定按下了哪种类型的按钮(删除或提交)并采取相应措施。

问题来了。当按下移除按钮时,函数destinations.enter 永远不会被调用。我为解决这个问题所做的是创建一个名为submitDestinations 的全局函数,它复制了destinations.enter 的功能。如果改为调用此函数,一切都会顺利进行。

有人知道为什么destinations.enter 不会在提交时运行,但submitDestinations 会吗?我想相信它与闭包有关,因为函数范围似乎是这两个函数之间的唯一区别。不过,这是我第一次使用闭包,对它们的了解还很有限。

Javascript:

var destinations = (function(){
    var max_destinations = 7;
    var counter = 0;

    function increment(){
        counter += 1;
        if(counter > max_destinations){
            throw 'Too many destinations. (Max 7)'
        }
    }
    function decrement(){
        counter += 0;
        if(counter < 0){
            alert('Cannot have less than 0 destinations..')
            throw 'Too few destinations. Get out of the console!'
        }
    }
    return {
        add : function(form){
            try{
                var formInput = form.elements[0];
                var destination = formInput.value;
                // Dont do anything if the input is empty
                if(destination == ""){
                    return false;
                }else{
                    // increment the destinations counter
                    increment();
                }
            }catch(err){
                alert(err);
                return false;
            }
            // add the text value to a visual element
            var elem = document.createElement('div');
            elem.setAttribute('class','destination');
            // create the input
            var input = document.createElement('input');
            input.setAttribute('id','dest'+String(counter));
            input.setAttribute('class','destinationText');
            input.setAttribute('style','border: none');
            input.setAttribute('name','destinations');
            input.setAttribute('readonly','readonly');
            input.setAttribute('value',destination);
            // create the remove button
            var button = document.createElement('button');
            button.setAttribute('onclick','this.form.submitted=this;');//'return destinations.remove(this);');
            button.setAttribute('class','removeButton')
            button.setAttribute('id','but'+String(counter))
            var buttonText = document.createTextNode('Remove');
            button.appendChild(buttonText);
            // add the elements to the div
            elem.appendChild(input);
            elem.appendChild(button);

            var parent = document.getElementById('destinationsDiv');
            parent.appendChild(elem);
            // clear the input box
            formInput.value = '';
            return false;
        },
        enter : function(form){
            alert('hi')
            var button = form.submitted;
            if(button.id != 'submitBtn'){
                return remove(button);
            }else{
                return true;
            }
            return false;
        },
        remove : function(button){
            try{
                decrement();
            }catch(err){
                // do not allow less than 0 counter
                alert(err);
                return false;
            }
            // remove the button's parent div altogether
            var toDelete = button.parentNode;
            toDelete.parentNode.removeChild(toDelete);
            return false;
        }

    }
})();

还有html:

        <div>
            <form id='hi' onsubmit="return destinations.add(this);">
                <input type="text" value="" />
            </form>
            <!--form id='submitDiv' method="post" onsubmit="alert(this.submitted);return submitDestinations(this);"-->
            <form id='submitDiv' method="post" onsubmit="alert(this.submitted);return destinations.enter(this);">
                <div id='destinationsDiv'>
                    <div>
                        <input id="dest1" class="destinationText" style="border: none" name="destinations" readonly="readonly" value="aadasd" \>
                        <button onclick="this.form.submitted=this;" class="removeButton" id="but1" \></button>
                    </div>
                    <div>
                        <input id="dest2" class="destinationText" style="border: none" name="destinations" readonly="readonly" value="Hi Stackoverflow" \>
                        <button onclick="this.form.submitted=this;" class="removeButton" id="but2" \></button>
                    </div>
                </div>
                <input type="submit" id='submitBtn' onclick="this.form.submitted=this;"/>
            </form>
        </div>

如果我将以下 javascript 函数添加到全局范围并改为调用它,则一切正常。这与destinations.enter 的作用完全相同

function submitDestinations(form){
    var button = form.submitted;
    if(button.id != 'submitBtn'){
        return destinations.remove(button);
    }else{
        return true;
    }
}

我在 html 中更改的只是提交时调用的方法:

        <div>
            <form id='hi' onsubmit="return destinations.add(this);">
                <input type="text" value="" />
            </form>
            <form id='submitDiv' method="post" onsubmit="alert(this.submitted);return submitDestinations(this);">
            <!--form id='submitDiv' method="post" onsubmit="alert(this.submitted);return destinations.enter(this);"-->
                <div id='destinationsDiv'>
                    <div>
                        <input id="dest1" class="destinationText" style="border: none" name="destinations" readonly="readonly" value="aadasd" \>
                        <button onclick="this.form.submitted=this;" class="removeButton" id="but1" \></button>
                    </div>
                    <div>
                        <input id="dest2" class="destinationText" style="border: none" name="destinations" readonly="readonly" value="Hi Stackoverflow" \>
                        <button onclick="this.form.submitted=this;" class="removeButton" id="but2" \></button>
                    </div>
                </div>
                <input type="submit" id='submitBtn' onclick="this.form.submitted=this;"/>
            </form>
        </div>

【问题讨论】:

  • 你能发一个jsfiddle吗?提供帮助会更容易。
  • @Juhana 这两种方法似乎都没有在 jsfiddle 中调用。 jsfiddle.net/FcxAA/2
  • 试着想出一个更简单的例子来展示同样的问题。这将帮助您和其他人弄清楚发生了什么。

标签: javascript html forms javascript-events


【解决方案1】:

原来存在命名冲突。我创建的文本输入的名称属性设置为“destinations”,与我在提交时调用的 javascript 对象同名。因此,“onsubmit”中的 javascript 试图引用 DOM 元素并在其上调用 enter,而不是引用我的 javascript 函数。

【讨论】:

    【解决方案2】:

    destinations.enter() 的实现有错误。它调用remove() 来移除按钮,但是名称'remove' 并没有绑定在destinations.enter() 定义的范围内。

    似乎destinations.remove() 从未在其他地方调用过,因此最简单的解决方法是将其移至destinations 构造函数中的私有函数,而不是使其成为destinations 对象上的方法。

    修改后的版本有效,因为您已将 submitDestinations() 的主体更改为调用destinations.remove(),它绑定在该范围内。

    【讨论】:

    • 啊,谢谢。事实证明,这与导致我出现问题的问题不同。在我解决了destinations.enter 的问题后,这会立即显现出来。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 1970-01-01
    • 2013-11-12
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    相关资源
    最近更新 更多