2

Backboneの継承に関するこの質問を見てきました: Backbone.jsビューの継承。便利ですが、私の質問には答えません。

私が経験している問題はこれです:

クラスPanel(この例ではモデル)があるとします。

var Panel = Backbone.Model.extend({
    defaults : {
        name : 'my-panel'
    }
});

そしてAdvancedPanel;

var AdvancedPanel = Panel.extend({
    defaults : {
        label : 'Click to edit'
    }
});

以下は機能しません。

var advancedPanel = new AdvancedPanel();
alert(advancedPanel.get('name')); // Undefined :(

ここのJSFiddle:http: //jsfiddle.net/hWmnb/

プロトタイプのディープコピーを作成するカスタム拡張関数を使用してこれを自分で達成できることがわかると思いますが、これはバックボーンの継承から人々が望む可能性のある一般的なことのようですが、それを行う標準的な方法はありますか?

4

4 に答える 4

3

プロトタイプチェーンを設定するバックボーンextend関数は、とりわけ汎用的であり、ビュー、ルーター、モデル、およびコレクションに使用されます。したがって、またはのような詳細については知らdefaultsevents、拡張タイプが親の値をオーバーライド またはマージするかどうかを判断できません。

前進する1つの方法は、実際の定義の外でこれを明示的に行うことです。

AdvancedPanel.prototype.defaults = _.extend({}, Panel.prototype.defaults, {
  label: 'Click me'
});

あなたはビューで同じようになります:

SomeExtendedView.prototype.events = _.extend({}, SomeBaseView.prototype.events, {
  'click button': 'onClick'
});

必要に応じて、実際には適切な場所にデフォルトをリストすることもできます。コンストラクター定義の外部でマージを行うだけです。

var Base = Backbone.Model.extend({
  defaults: {
    base: 123
  }
});

var Extended = Base.extend({
  defaults: {
    extended: 456
  }
});

Extended.prototype.defaults = _.extend({}, Base.prototype.defaults, Extended.prototype.defaults);

これには、Extended.defaultsインクルードとbaseextendedインスタンス化に渡される属性が含まれます。

console.log(JSON.stringify(new Extended({ test: 'Hey' }).toJSON()));
>> {"base":123,"extended":456,"test":"Hey"}
于 2012-10-01T13:58:30.713 に答える
2

これを取り上げて、 (この継承構造からの)advancedExtend行を置き換える簡単なメソッドを作成しました。

Panel.extend = Backbone.Model.extend;

と:

Panel.extend = advancedExtend;

私のadvancedExtend方法は次のようになります。

function advancedExtend(protoProps, classProps) {

    var delegate = this.render ? 
                        Backbone.View : (this.save ? 
                            Backbone.Model : (this.navigate ? 
                                Backbone.Router : Backbone.Collection)); 

    var child = delegate.extend.apply(this, [ protoProps, classProps ]);

    _.defaults(child.prototype.defaults, this.prototype.defaults);
    _.defaults(child.prototype.events, this.prototype.events);
    _.defaults(child.prototype.attributes, this.prototype.attributes);

    return child;
};

注意delegate:バックボーンのプロトタイプメソッドはすべて同じであるため、の定義は無意味であると思いextendますが、これは将来のバージョンではより堅牢になる可能性があると考えました。

ここでJSFiddleを参照してください。

それが非標準であることを考えると、バックボーンのベテランがこのアプローチについてどう思うか聞いてみたいと思います...

于 2012-10-08T09:12:12.480 に答える
1

問題は、JavaScriptには古典的な継承がないため、ここで何か特別なことをする必要があるということです。

_.extendリスト内で拡張するオブジェクトの「右」に最も近いオブジェクトを使用すると、名前の衝突で「勝ち」ます。

これらのケースを処理するためにextendの定義をオーバーライドするか、defaultsハッシュに次のような名前を付けてメソッドlocal_defaultsにマージする必要があります。initialization

    initialize: function(options){
        var attrs = _.extend({}, this.defaults, this.local_defaults);
        this.set(attrs, {silent: true});
    },

そんな感じ。属性ハッシュをデフォルトのセットに設定する必要があります。通常、これはモデルのコンストラクターで発生しますが、モデルはその時点でのデフォルトについてのみ認識します。

もちろん、local_defaultsでデフォルトを再定義した場合でも上書きされるため、extendの上書きを検討することになります。(ここで作業中のいくつかの特定のケースに対して行ったので、必要に応じて喜んでお手伝いします。)

于 2012-10-01T12:40:52.543 に答える
1

これを行うにはいくつかの方法がありますが、私のアプリケーションで推奨される方法は、モデルの「デフォルト」を関数として定義することです。これにより、次のように実行できます。

var Panel = Backbone.Model.extend({
    defaults : {
        name : 'my-panel'
    }
});

拡張モデルを次のように定義しました。

var AdvancedPanel = Panel.extend({
    defaults: function() {
        var d = _.result(Panel.prototype, 'defaults'); // doing this as top level might be a function as well
        return _.extend({}, d, {
            label : 'Click to edit' 
        });
    }
});

次に、コンソールで名前の正しい値を取得する必要があります

var advancedPanel = new AdvancedPanelModel();
console.log('advancedPanel', advancedPanel.get('name'));

そしてそれはトリックをする必要があります

于 2012-10-01T12:50:27.460 に答える