23

私は、ほとんどが JavaScript で構築された面倒な Web インターフェイスに取り組んでいます。基本的に、多くのセクションを持つ 1 つの (非常に) 大きなフォームです。各セクションは、フォームの他の部分のオプションに基づいて作成されます。これらのオプションが変更されるたびに、新しい値が「レジストリ」タイプのオブジェクトに記録され、それに応じて他のセクションが再設定されます。

多くのフォーム フィールドにイベント リスナーを配置すると処理が遅くなり、変更のたびにフォーム全体を更新するのは、ユーザーにとって重すぎたり遅すぎたりします。

リスナをフォーム要素ではなくレジストリ オブジェクトの属性に追加して、処理を少し高速化できるかどうか疑問に思っています。もしそうなら、サンプルコードを提供/指摘してもらえますか?

さらに詳しい情報:

  • これは jQuery のプラグインであるため、そのライブラリから構築できる機能は役に立ちますが、必須ではありません。
  • ユーザーは IE6/7、Safari、および FF2/3 を使用しているため、可能であれば、「最新の」ブラウザーのみを対象として、別の解決策を見つける必要があります。
4

7 に答える 7

6

私の知る限り、オブジェクト属性の変更で発生するイベントはありません(編集:を除いて、明らかにObject.watch)。

可能な限りイベント委任を使用してみませんか?つまり、個々のフォーム要素ではなくフォーム上のイベントで、バブルが発生したときにイベントをキャプチャしますか?

たとえば(私のjQueryは錆びています。代わりにプロトタイプを使用することを許してください。ただし、簡単に適応できると確信しています):

$(form).observe('change', function(e) {
    // To identify changed field, in Proto use e.element()
    // but I think in jQuery it's e.target (as it should be)
});

フォーカスを失う前にテキストフィールドで発生させたい場合は、イベントとinputイベントをキャプチャすることもできます。これに対する私の解決策は通常次のとおりです。keyuppaste

  1. Gecko / Webkitベースのブラウザ:で観察inputしてformください。
  2. また、Webkitベースのブラウザーの場合: sでの監視keyuppasteイベント(何らかの理由でsで起動しtextareaません)。inputtextarea
  3. IE:観察keyuppasteform
  4. (これはsで発生します)を観察changeします。formselect
  5. keyupおよびイベントの場合、テキストフィールドをpasteそのデフォルトと比較することにより、フィールドの現在の値をデフォルト(ページがロードされたときの値)と比較します。valuedefaultValue

編集:変更されていないフォームの送信などを防ぐために私が開発したサンプルコードは次のとおりです。

javascriptを介してフォームの変更を追跡するための最良の方法は何ですか?

于 2008-10-27T17:18:42.037 に答える
6

コメントをありがとう。私は次のことを行ってきました:

var EntriesRegistry = (function(){

    var instance = null;

    function __constructor() {

        var
            self = this,
            observations = {};

        this.set = function(n,v)
        {
            self[n] = v;

            if( observations[n] )
                for( var i=0; i < observations[n].length; i++ )
                    observations[n][i].apply(null, [v, n]);

        }

        this.get = function(n)
        {
            return self[n];
        }

        this.observe = function(n,f)
        {

            if(observations[n] == undefined)
                observations[n] = [];

            observations[n].push(f);
        }

    }

    return new function(){
        this.getInstance = function(){
            if (instance == null)
            {
                instance = new __constructor();
                instance.constructor = null;
            }
            return instance;
        }
    }
})();

var entries = EntriesRegistry.getInstance();

var test = function(v){ alert(v); };

entries.set('bob', 'meh');

entries.get('bob');

entries.observe('seth', test);

entries.set('seth', 'dave');

コメントを取り入れて、フォームオブジェクトのイベント委任を使用して、レジストリを更新し、登録された監視メソッドをトリガーします。

これは今のところ私にとってうまく機能しています...皆さんはこれに関する問題を見ることができますか?

于 2008-10-28T10:56:08.720 に答える
2

リスナーをコンテナー(本体またはフォーム)にアタッチしてから、イベントパラメーターを使用して変更に対応することができます。すべてのリスナーの良さを得ることができますが、すべての要素に1つではなく、コンテナーに1つだけアタッチする必要があります。

$('body').change(function(event){
    /* do whatever you want with event.target here */
    console.debug(event.target); /* assuming firebug */
 });

event.targetは、クリックされた要素を保持します。

SitePointには、イベント委任についての優れた説明があります。

JavaScriptイベント委任は、複数の子要素にイベントハンドラーを追加する必要をなくすために、親要素に単一のイベントハンドラーを追加する簡単な手法です。

于 2008-10-27T17:10:35.860 に答える
1

MozillaエンジンのブラウザはObject.watchをサポートしていますが、クロスブラウザ互換の同等のものを私は知りません。

速度低下の原因を正確に把握するために、Firebugを使用してページのプロファイルを作成しましたか、それとも「多数のイベントハンドラー」が推測されますか?

于 2008-10-27T17:16:44.820 に答える
1

前の回答への小さな変更: 監視可能なコードをオブジェクトに移動することで、それを抽象化し、それを使用して jQuery の extends メソッドで他のオブジェクトを拡張できます。

ObservableProperties = {
    events : {},
    on : function(type, f)
    {
        if(!this.events[type]) this.events[type] = [];
        this.events[type].push({
            action: f,
            type: type,
            target: this
        });
    },
    trigger : function(type)
    {
        if (this.events[type]!==undefined)
        {
            for(var e = 0, imax = this.events[type].length ; e < imax ; ++e)
            {
                this.events[type][e].action(this.events[type][e]);
            }
        }
    },
    removeEventListener : function(type, f)
    {
        if(this.events[type])
        {
            for(var e = 0, imax = this.events[type].length ; e < imax ; ++e)
            {
                if(this.events[type][e].action == f)
                    this.events[type].splice(e, 1);
            }
        }
    }
};
Object.freeze(ObservableProperties);

var SomeBusinessObject = function (){
    self = $.extend(true,{},ObservableProperties);
    self.someAttr = 1000
    self.someMethod = function(){
        // some code
    }
    return self;
}

フィドルを参照してください: https://jsfiddle.net/v2mcwpw7/3/

于 2015-09-01T16:10:00.153 に答える
0

jQueryは素晴らしいです。ASP.NETAJAXプレビューを見ることができますが。

一部の機能は.jsファイルであり、.NETとの依存関係はありません。オブザーバーパターンの実装に役立つかもしれません。

var o = { foo: "Change this string" };

Sys.Observer.observe(o);

o.add_propertyChanged(function(sender, args) {
    var name = args.get_propertyName();
    alert("Property '" + name + "' was changed to '" + sender[name] + "'.");
});

o.setValue("foo", "New string value.");

また、クライアント側のテンプレートは、いくつかの興味深いシナリオですぐに使用できます。

最後に、これはjQueryと完全に互換性があります($では問題ありません)

リンク:ホームページ現在使用しているバージョン

于 2008-10-27T17:25:51.540 に答える
0

私は同じものを探していて、あなたの質問に答えました...私のニーズを満たす答えはなかったので、共有したいこの解決策を思いつきました:

var ObservedObject = function(){
    this.customAttribute = 0
    this.events = {}
    // your code...
}
ObservedObject.prototype.changeAttribute = function(v){
     this.customAttribute = v
     // your code...
     this.dispatchEvent('myEvent')
}
ObservedObject.prototype.addEventListener = function(type, f){
    if(!this.events[type]) this.events[type] = []
    this.events[type].push({
        action: f,
        type: type,
        target: this
    })
}
ObservedObject.prototype.dispatchEvent = function(type){
    for(var e = 0; e < this.events[type].length; ++e){
        this.events[type][e].action(this.events[type][e])
    }
}
ObservedObject.prototype.removeEventListener = function(type, f){
    if(this.events[type]) {
        for(var e = 0; e < this.events[type].length; ++e){
            if(this.events[type][e].action == f)
                this.events[type].splice(e, 1)
        }
    }
}

var myObj = new ObservedObject()

myObj.addEventListener('myEvent', function(e){// your code...})

これは DOM Events API を単純化したもので、問題なく動作します。より完全な例を次に示します

于 2013-02-28T20:19:52.877 に答える