7853


先日、画像を左右にスワイプできるslider系のjQueryライブラリを利用していた時、標準のjQueryには存在しないメソッドを呼び出すことで、ライブラリ専用のインスタンスを取得でき、そのインスタンスを利用することで様々なメソッドにアクセスできる、というものがありました。

そこで、自分もjQueryを拡張してみようと思い、真似をして以下の様なコードを書いてみました。

[code]

    $.fn.extend({
      slider: function(){
        var idx = 0;
        this.method = function(){ return ++idx; };
        return this;
      }
    });
    
    var slider = $('body').slider(); // 特にbodyを指定することに意味は無い
    slider.method(); // -> 1
    slider.method(); // -> 2
    
[/code]

うまく実行することが出来ました。

しかし、同じようにもう一度slider()メソッドを利用してインスタンスを取得すると、別のインスタンスになってしまい値はリセットされてしまいます。

[code]

    var slider = $('body').slider();
    slider.method(); // -> 1
    slider.method(); // -> 2
    
    slider = $('body').slider();
    slider.method(); // -> 1
    slider.method(); // -> 2
    
[/code]

この場合、複雑なシステムなどでjsファイルが複数存在する場合、ファイルをまたいで同じインスタンスを利用するには、予めインスタンスを取得しておき、必要なメソッドにインスタンスを渡すというような方法が考えられます。

コード的にはそういった書き方をしたほうが適切なのかもしれません。しかし、いろいろと面倒なので同じDOMで一度呼び出したことがあるインスタンスには同じインスタンスが返ってくるように以下のような更なる別の拡張を追加しました。

[code]

    window.instances = window.instances || {}
    
    $.extend({ // $.fn.extendではない
      getInstance: function(jqobj){
        if(jqobj.length==0) return undefined;
        return window.instances[jqobj.attr('instance-id')];
      },
    
      setInstance: function(instance){
        var id = (Math.random()+'').substr(2);
        instance.attr('instance-id', id);
        return window.instances[id] = instance;
      }
    });
    
[/code]

インスタンスを作成した際に`instance-id`属性に乱数を設定たものを割り当て、取得するときに`instance-
id`属性が存在していれば、idからインスタンスを取得するというわけです。

そして、$.fn.extendのsliderを以下のようにします。

[code]

    $.fn.extend({
      slider: function(){
        instance = $.getInstance(this);
        if(instance) return instance;
    
        var idx = 0;
        this.method = function(){ return ++idx; }
        return $.setInstance(this);
      }
    });
    
    var slider = $('body').slider();
    slider.method(); // -> 1
    slider.method(); // -> 2
    
    slider = $('body').slider();
    slider.method(); // -> 3
    slider.method(); // -> 4
    
[/code]

少し無理やりなような気もするのですが、これでどこからでも同じ対象DOMであれば、同じインスタンスを取得することが出来るようになりました。

しかし、なにかしてはいけないことをしている気がして気持ちが悪いです。  
皆様は、このような状況をどう感じますでしょうか？

より良い解決策や、アドバイスなどございましたらよろしくお願いいたしますm(_ _)m


CC BY-SA 3.0
2015-03-12T23:30:10.123
7851
2015-03-13T07:23:18.320
2015-03-13T07:23:18.320
8752
8351
question
javascript jquery
$.fn.extendによるjQueryの拡張で得られるインスタンスをあらゆる場所から使いまわすには？


`data()`を使って対象DOMに値を設定するとシンプルです。

[code]

    $.fn.extend({
      slider: function(){
        var idx = this.data('__slider_data__');
        if( idx == undefined){
            idx = 0;
        }
        this.method = function(){
            this.data('__slider_data__', ++idx);
            return idx;
        };
        return this;
      }
    });
    
    $(document).ready(function(){
        
        var slider = $('#target').slider();
        
        $('#target').append(slider.method());
        $('#target').append(slider.method());
        
        slider = $('#target').slider();
        
        $('#target').append(slider.method());
        $('#target').append(slider.method());
        
    });
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    
    <div id="target"><div>
[/code]


CC BY-SA 3.0
2015-03-13T00:27:40.497
7853
2015-03-13T00:27:40.497
7214
7851
answer