web-dev-qa-db-ja.com

配列である属性のBackbone.js処理

私はバックボーンが本当に好きですが、単純なことのように見えることをするのに最も苦労しています。次の例で助けていただければ幸いです。

UIにいくつかのアイテムの状態を保存するために使用したいモデルCriteriaがあります。いくつかの単純な属性と、ユーザーがUIで選択したタグのIDを格納するために使用されるIDの配列である1つの属性があります。

そこで、新しいインスタンスを作成します。タグ配列にいくつかのアイテムを追加します。次に、新たに開始して、同じ変数に割り当てられた新しいインスタンスを作成します。しかし、私のタグ配列は、Criteriaの最初のインスタンスの一部として追加した情報を保持し続けます。

以下のテストケースを文書化しました。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Test</title>
    <script src="Scripts/Libraries/jquery-1.6.1.js" type="text/javascript"></script>
    <script src="Scripts/Libraries/underscore.js" type="text/javascript"></script>
    <script src="Scripts/Libraries/backbone.js" type="text/javascript"></script>

    <script language="javascript" type="text/javascript">

        $(function () {

            // Simple model to hold some state about my UI.
            var Criteria = Backbone.Model.extend({

                defaults: {
                    "status": "Normal",
                    "priority": "Normal",
                    "tags": new Array()
                }

            });

            // Create new criteria.
            window.criteria = new Criteria();

            // The length of the tags array should be 0. PASSES
            console.log("Expect 0: Actual " + window.criteria.get("tags").length);

            // Add a tag id to the tags array.
            window.criteria.get("tags").Push(5); // Tag with ID of 5.

            // The length of the tags array should be 1. PASSES
            console.log("Expect 1: Actual " + window.criteria.get("tags").length);

            // Create a new instance of criteria.
            window.criteria = new Criteria();

            // The length of the tags array should be 0. FAILS
            // CONFUSED. I thought this is now a new instance with a new set of attributes.
            // Why does the tags collection still have an item in it.
            console.log("Expect 0: Actual " + window.criteria.get("tags").length);

            // OK. So, I will call the clear method on the model. This is supposed to remove all attributes
            // from the model.
            // Then, I will create it again.
            window.criteria.clear();
            window.criteria = new Criteria();

            // The length of the tags array should be 0. FAILS. Still 1.
            console.log("Expect 0: Actual " + window.criteria.get("tags").length);

            // ARGH!
            console.log("HELP!");

        });

    </script>

</head>
<body>
    <h1>Test</h1>
    <p>Backbone test page.</p>
</body>
</html>

私はここでマークから外れていますか?バックボーンを意図していないものに使用しようとしていますか?または、javascript OOプログラミングでより一般的なものが欠けていますか?

P.S.私は元々はタグのバックボーンコレクションを使用していましたが、複数のコレクションでタグモデルを参照すること、およびコレクションからアイテムが削除されたときにバックボーンのremoveメソッドが「コレクション」参照の設定を解除する方法に関して、まったく異なる一連の問題が発生しました。別の日、別の問題。

35
Kevin

Thom Blakeは、配列に対して同じ値を保持している理由について正しいです。これを解決するための1つのオプションは、イニシャライザーでデフォルト値を設定することです。

        var Criteria = Backbone.Model.extend({

            defaults: {
                "status": "Normal",
                "priority": "Normal"
            },

            initialize: function(){
              if( !this.get('tags') ){ 
                this.set({tags: new Array()});
              }
            }

        });
34
Derick Bailey

「デフォルト」も関数にすることができます。

var Criteria = Backbone.Model.extend({
    defaults: function () {
        return {
            "status": "Normal",
            "priority": "Normal",
            "tags": new Array()
        }
    }
});

これにより、新しい基準がインスタンス化されたときに新しい配列が作成されます。参照: http://backbonejs.org/#Model-defaults

70
btford

「defaults」の下に「tags」を定義するときは、新しい配列を作成し、それをそのクラスのデフォルト値に設定します。次に、新しいインスタンスを作成すると、同じ配列参照があり、プッシュしたものがまだ含まれています。

タグのデフォルト値を設定するのではなく、初めて使用する前に[]に設定できるはずです。

window.criteria = new Criteria()
window.criteria.set({'tags', []})  //you can use new Array() if you want
window.criteria.get('tags').Push(5)

window.criteria = new Criteria()
console.log(window.criteria.get('tags'))   //should be undefined
window.criteria.set({'tags', []})
13
Tamzin Blake

明確にするために、MaksymH。によって提供された最後のオプションは問題を解決しません。 defaultsプロパティは、設定されたすべての値が不変であると想定して提供されます。ただし、配列は変更可能です。つまり、その値を変更できます(たとえば、tags [0] = "hello"はtags [0] = "hi there"で変更できます)。

Btfordの回答を使用すると、可変オブジェクト/プロパティの新しいインスタンスがモデルのすべての新しいインスタンスで作成されるように強制されます。オブジェクトは関数スコープの変数で作成されるため、共有されることはありません。

同様に、Derick Baileyの答えは正解で、defaultsメソッドの代わりにinitializeメソッドを使用するだけです。

3
Chris M