3

重複した JavaScript コードを削除しようとしています。私は多くのページを持っています<input type="file">。それぞれが画像をロードし、いくつかの異なる処理を実行します。問題は、次のコードの重複が多いことです。

inputFile1.onchange = function (e) {
        var file = e.target.files[0];
        if (typeof file == 'undefined' || file == null) {
            return;
        }
        var imageType = /image.*/;
        if (!file.type.match(imageType)) {
            window.alert('Bad file type!');
            return;
        }
        var reader = new FileReader();
        reader.onloadend = function (e) {
            var imageLoader = new Image();
            imageLoader.onload = function () {
                // process image
            };
            imageLoader.src = e.target.result;
        };
        reader.readAsDataURL(file);
    };

inputFile2.onchange = ... (repeats all but process image)
inputFile3.onchange = ... (repeats all but process image)

process imageコメントのコードのみが異なります。周囲の重複コードを削除するにはどうすればよいですか?

JavaScript 関数がオブジェクトであることは知っています。関数オブジェクトを定義し、イベント ハンドラーごとに 1 つの個別のインスタンスを作成してprocess image、各オブジェクトに異なる関数を渡すにはどうすればよいですか?

4

3 に答える 3

3

個々のコールバックを引数として受け取るクロージャを使用して、そのような関数のジェネレータを作成できます。

function getChangeHandler(loadCallback) {
    return function (e) {
        var file = e.target.files[0];
        if (typeof file == 'undefined' || file == null) {
            return;
        }
        var imageType = /image.*/;
        if (!file.type.match(imageType)) {
            window.alert('Bad file type!');
            return;
        }
        var reader = new FileReader();
        reader.onloadend = function (e) {
            var imageLoader = new Image();
            imageLoader.onload = loadCallback; // <= uses the closure argument
            imageLoader.src = e.target.result;
        };
        reader.readAsDataURL(file);
    };
}
inputFile1.onchange = getChangeHandler(function() { /* custom process image */ });
inputFile2.onchange = getChangeHandler(function() { /* custom process image */ });
inputFile3.onchange = getChangeHandler(function() { /* custom process image */ });

change別の最終的に優れたアプローチは、すべての入力に対して 1 つの -event ハンドラーのみを使用し、入力のnameまたはによってカスタム イメージ プロセッサを動的に選択することです。id

var imageProcessors = {
    "box1": function() { … },
    "anotherbox": function() { … },
    …
};
function changeHandler(e) {
    var input = this; // === e.target
    …
    reader.onloadend = function (e) {
        …
        imageLoader.onload = imageProcessors[input.id];
    };
}
// and bind this one function on all inputs (jQuery-style):
$("#box1, #anotherbox, …").click(changeHandler);
于 2012-08-05T21:15:14.580 に答える
1

関数を返す関数を書くことができます:

function processFile(callback) { //callback is the unique file processing routine
    return function(e) {
        var file = e.target.files[0];
        if (typeof file == 'undefined' || file == null) {
            return;
        }
        var imageType = /image.*/;
        if (!file.type.match(imageType)) {
            window.alert('Bad file type!');
            return;
        }
        var reader = new FileReader();
        reader.onloadend = function (e) {
            var imageLoader = new Image();
            imageLoader.onload = callback; //Put it here!
            imageLoader.src = e.target.result;
        };
        reader.readAsDataURL(file);
    };
}

次に、次のように呼び出します。

inputFile1.onchange = processFile(function() {
      //file processing for number 1
});
inputFile2.onchange = processFile(function() {
      //file processing for number 2
});
inputFile3.onchange = processFile(function() {
      //file processing for number 3
});
于 2012-08-05T21:17:59.677 に答える
1

ここに EMCA5 ソリューションを示します。これをミックスに投入するだけです。要素に応じて動的イベント コールバックをバインドします。

各フィールドには ID (input1など) があると仮定しましたが、コードを変更すると (つまり、他の方法でトリガー要素を識別する)、これは必要なくなります。

Array.prototype.slice.call(document.querySelectorAll('input[type=file]')).forEach(function(element) {

    /* prepare code specific to the element */
    var input_specific_code = (function() {
        switch (element.id) {
            case 'input1': return function() { /* #input1 code here */ };
            case 'input2': return function() { /* #input2 code here */ };
            case 'input3': return function() { /* #input3 code here */ };
        }
    })();

    element.addEventListener('change', (function(input_specific_code) { return function(evt) {
        var id_of_trigger_input = element.id;

        /* common code here */

        /* element-specific code */
        input_specific_code();

        /* continuation of common code */

    }; })(input_specific_code), false);
});
于 2012-08-05T21:26:52.867 に答える