Backbone.js नेस्टेड ऑब्जेक्ट विशेषता प्राप्त और सेट करते हैं


105

मैं एक साधारण 'Backbone.js के बारे में सवाल है प्राप्त और सेट कार्य करता है।

1) नीचे दिए गए कोड के साथ, मैं सीधे'j 'या' सेट 'कैसे प्राप्त कर सकता हूं?

एक और प्रश्न:

2) मॉडल में, डिफॉल्ट्स ऑब्जेक्ट से अलग , मुझे अपने मॉडल की अन्य विशेषताओं की घोषणा कहां से करनी चाहिए, जैसे कि उन्हें बैकबोन के गेट और सेट विधियों के माध्यम से एक्सेस किया जा सकता है?

var MyModel = Backbone.Model.extend({
    defaults: {
        obj1 : {
            "myAttribute1" : false,
            "myAttribute2" : true,
        }
    }
})

var MyView = Backbone.View.extend({
    myFunc: function(){
        console.log(this.model.get("obj1"));
        //returns the obj1 object
        //but how do I get obj1.myAttribute1 directly so that it returns false?
    }
});

मुझे पता है मैं कर सकता हूँ:

this.model.get("obj1").myAttribute1;

लेकिन क्या यह अच्छा अभ्यास है?


3
हालांकि यह इस सवाल का जवाब नहीं है: जब भी ( defaultsइस मामले में obj1 ) किसी ऑब्जेक्ट (संदर्भ में पारित कुछ) को निर्दिष्ट किया जाता है , तो उसी ऑब्जेक्ट को मॉडल के सभी उदाहरणों में साझा किया जाएगा। वर्तमान अभ्यास defaultsको एक फ़ंक्शन के रूप में परिभाषित करना है जो एक वस्तु को चूक के रूप में उपयोग करने के लिए देता है। backbonejs.org/#Model-defaults (इटैलिक नोट देखें)
जोनाथन एफ

1
@JonathanF टिप्पणियाँ उत्तर के लिए नहीं हैं, इसलिए आपको कभी घोषणा की आवश्यकता नहीं है :)
TJ

जवाबों:


144

हालांकि this.model.get("obj1").myAttribute1यह ठीक है, यह थोड़ा समस्याग्रस्त है क्योंकि तब आपको सेट के लिए एक ही प्रकार का काम करने के लिए लुभाया जा सकता है, अर्थात

this.model.get("obj1").myAttribute1 = true;

लेकिन अगर आप ऐसा करते हैं, तो आपको बैकबोन मॉडल का लाभ नहीं मिलेगा myAttribute1, जैसे कि परिवर्तन की घटना या सत्यापन।

एक बेहतर समाधान यह होगा कि अपने मॉडल में POJSO ("सादे पुराने जावास्क्रिप्ट ऑब्जेक्ट") को कभी न घोंसले में रखें, और इसके बजाय घोंसले के कस्टम मॉडल कक्षाएं। तो यह कुछ इस तरह दिखेगा:

var Obj = Backbone.Model.extend({
    defaults: {
        myAttribute1: false,
        myAttribute2: true
    }
});

var MyModel = Backbone.Model.extend({
    initialize: function () {
        this.set("obj1", new Obj());
    }
});

तब एक्सेस कोड होगा

var x = this.model.get("obj1").get("myAttribute1");

लेकिन इससे भी महत्वपूर्ण बात यह है कि सेटिंग कोड होगा

this.model.get("obj1").set({ myAttribute1: true });

जो उचित परिवर्तन की घटनाओं और इस तरह आग लगाएगा। यहाँ काम कर उदाहरण: http://jsfiddle.net/g3U7j/


24
इस उत्तर के लिए, मैं यह सलाह दूंगा कि यह समाधान लोकतंत्र के उल्लंघन के व्यापक कानून पर आधारित है। मैं उन सुविधा विधियों को जोड़ने पर विचार करूंगा जो नेविगेशन को नेस्टेड ऑब्जेक्ट में छिपाते हैं। असल में, आपके कॉलर्स को मॉडल की आंतरिक संरचना को जानने की आवश्यकता नहीं है; आखिरकार, यह बदल सकता है और कॉल करने वाला कोई भी समझदार नहीं होना चाहिए।
बिल आइजनहाउर

7
यह मेरे लिए काम करने के लिए नहीं मिल सकता है। थ्रो एरर:Uncaught TypeError: Object #<Object> has no method 'set'
विल्सनपेज

1
@ChristianNunciato, pagewil, Benno: आपको लगता है कि पोस्ट के बिंदु से चूक गए हैं, जो बैकबोन मॉडल के अंदर बैकबोन मॉडल को घोंसला बनाना है। बैकबोन मॉडल के अंदर सादे वस्तुओं को घोंसला न दें। यहाँ काम करने का उदाहरण: jsfiddle.net/g3U7j
Domenic

1
मैंने बैकबोन.जेएस कोड का निरीक्षण नहीं किया, लेकिन मेरे परीक्षण से, यदि आपके पास एक नेस्टेड कस्टम मॉडल है और सेट () के साथ इसकी एक संपत्ति को बदलते हैं, तो इसका मूल मॉडल स्वयं एक 'परिवर्तन' घटना को आग नहीं देगा; मुझे खुद ही इस घटना की आग बुझानी पड़ी। मुझे वास्तव में सिर्फ कोड का निरीक्षण करना चाहिए, लेकिन क्या यह आपकी समझ है?
टॉम

2
@tom जो सही है। जब मॉडल के गुण उदाहरण हैं Backbone.Modelऔर तब जादुई ईवेंट बुबलिंग करना शुरू करते हैं, तो बैकबोन विशेष-मामला नहीं करता है ।
डोमिनिक

74

मैंने इसके लिए बैकबोन-डीप-मॉडल तैयार किया - बैकबोन के बजाय बैकबोन.जीपीमॉडल का विस्तार करें। फिर नेस्टेड मॉडल विशेषताएँ प्राप्त / सेट करने के लिए पथ का उपयोग कर सकते हैं। यह परिवर्तन की घटनाओं को भी बनाए रखता है।

model.bind('change:user.name.first', function(){...});
model.set({'user.name.first': 'Eric'});
model.get('user.name.first'); //Eric

1
हाँ यह होता है, अगर आप को देखो एपीआई की तरह एक उदाहरण है//You can use index notation to fetch from arrays console.log(model.get('otherSpies.0.name')) //'Lana'
tawheed

बहुत अच्छा काम करता है! लेकिन क्या आपके उदाहरण में पंक्ति 2 को अल्पविराम के बजाय बृहदान्त्र की आवश्यकता है?
मारीचि 23

16

Domenic का समाधान हालांकि काम करेगा प्रत्येक नया MyModel Obj के समान उदाहरण को इंगित करेगा। इससे बचने के लिए, MyModel को दिखना चाहिए:

var MyModel = Backbone.Model.extend({
  initialize: function() {
     myDefaults = {
       obj1: new Obj()
     } 
     this.set(myDefaults);
  }
});

पूर्ण विवरण के लिए c3rin का उत्तर @ https://stackoverflow.com/a/6364480/1072653 देखें ।


1
भविष्य के पाठकों के लिए, मेरे जवाब को रस्टी के सर्वश्रेष्ठ के उत्तर को शामिल करने के लिए अद्यतन किया गया है।
डोमिनिक

2
प्रश्नकर्ता को स्वीकृत उत्तर के रूप में इसे चिह्नित करना चाहिए। डोमिनिक की एक शानदार शुरुआत है, लेकिन यह इसके साथ एक मुद्दे को हल करता है।
जॉन रासच

5

मैं इस दृष्टिकोण का उपयोग करता हूं।

यदि आपके पास इस तरह एक बैकबोन मॉडल है:

var nestedAttrModel = new Backbone.Model({
    a: {b: 1, c: 2}
});

आप विशेषता "ab" को इसके साथ सेट कर सकते हैं:

var _a = _.omit(nestedAttrModel.get('a')); // from underscore.js
_a.b = 3;
nestedAttrModel.set('a', _a);

अब आपके मॉडल में विशेषताएं होंगी:

{a: {b: 3, c: 2}}

"परिवर्तन" घटना के साथ निकाल दिया गया।


1
क्या तुम इसके बारे में निश्चित हो? यह मेरे लिए काम नहीं करता है। meta2= m.get('x'); meta2.id=110; m.set('x', meta2)। यह मेरे लिए किसी भी परिवर्तन की घटना को ट्रिगर नहीं करता है :(
HungryCoder

1
मुझे लगता है कि जब मैं इस विशेषता को क्लोन करता हूं तो यह काम करता है _.clone(m.get('x'))। धन्यवाद
HungryCoder

धन्यवाद @HungryCoder यह मेरे लिए भी काम किया जब क्लोन। बैकबोन आपको उस ऑब्जेक्ट की तुलना करना चाहिए जो आप उस वस्तु के settingसाथ हैं जो आप gettingनिर्धारित समय पर हैं। इसलिए यदि आप क्लोन नहीं करते हैं तो दो ऑब्जेक्ट, फिर तुलना की जा रही दो ऑब्जेक्ट बिल्कुल निर्धारित समय पर समान हैं।
डेरेक दाहर

याद रखें कि वस्तुओं को संदर्भ द्वारा पारित किया जाता है और स्ट्रिंग और संख्या आदिम के विपरीत, परिवर्तनशील होते हैं। बैकबोन के सेट और कंस्ट्रक्टर विधियां तर्क के रूप में पारित किसी भी वस्तु संदर्भ के उथले क्लोन का प्रयास करती हैं। उस वस्तु के गुणों में अन्य वस्तुओं का कोई संदर्भ क्लोन नहीं किया जाता है। जब आप इसे सेट करते हैं और इसे पुनः प्राप्त करते हैं तो संदर्भ समान होता है, जिसका अर्थ है कि आप परिवर्तन को ट्रिगर किए बिना मॉडल को म्यूट कर सकते हैं।
niall.campbell

3

एक समाधान है जो किसी ने अभी तक सोचा नहीं है जो बहुत उपयोग करना है। आप वास्तव में नेस्टेड विशेषताओं को सीधे सेट नहीं कर सकते हैं, जब तक कि आप तीसरे पक्ष के पुस्तकालय का उपयोग नहीं करते हैं जो आप शायद नहीं चाहते हैं। हालाँकि आप जो कर सकते हैं वह मूल शब्दकोश का एक क्लोन बना सकता है, नेस्टेड संपत्ति को वहां सेट करें और उस पूरे शब्दकोश को सेट करें। केक का टुकड़ा।

//How model.obj1 looks like
obj1: {
    myAttribute1: false,
    myAttribute2: true,
    anotherNestedDict: {
        myAttribute3: false
    }
}

//Make a clone of it
var cloneOfObject1 = JSON.parse(JSON.stringify(this.model.get('obj1')));

//Let's day we want to change myAttribute1 to false and myAttribute3 to true
cloneOfObject1.myAttribute2 = false;
cloneOfObject1.anotherNestedDict.myAttribute3 = true;

//And now we set the whole dictionary
this.model.set('obj1', cloneOfObject1);

//Job done, happy birthday

2

मुझे वही समस्या थी @pagewil और @Benno को @ डॉमिक के समाधान के साथ। इसके बजाय मेरा जवाब बैकबोन की एक साधारण उप-श्रेणी लिखना था।

// Special model implementation that allows you to easily nest Backbone models as properties.
Backbone.NestedModel = Backbone.Model.extend({
    // Define Backbone models that are present in properties
    // Expected Format:
    // [{key: 'courses', model: Course}]
    models: [],

    set: function(key, value, options) {
        var attrs, attr, val;

        if (_.isObject(key) || key == null) {
            attrs = key;
            options = value;
        } else {
            attrs = {};
            attrs[key] = value;
        }

        _.each(this.models, function(item){
            if (_.isObject(attrs[item.key])) {
                attrs[item.key] = new item.model(attrs[item.key]);
            }
        },this);

        return Backbone.Model.prototype.set.call(this, attrs, options);
    }
});

var Obj = Backbone.Model.extend({
    defaults: {
        myAttribute1: false,
        myAttribute2: true
    }
});

var MyModel = Backbone.NestedModel.extend({
    defaults: {
        obj1: new Obj()
    },

    models: [{key: 'obj1', model: Obj}]
});

आपके लिए NestedModel क्या काम करता है (जो तब होता है जब MyModel JSON डेटा के माध्यम से सेट हो जाता है):

var myModel = new MyModel();
myModel.set({ obj1: { myAttribute1: 'abc', myAttribute2: 'xyz' } });
myModel.set('obj1', { myAttribute1: 123, myAttribute2: 456 });

प्रारंभिक रूप से मॉडल सूची को स्वचालित रूप से उत्पन्न करना आसान होगा, लेकिन यह समाधान मेरे लिए काफी अच्छा था।


2

डोमिनिक द्वारा प्रस्तावित समाधान में कुछ कमियां हैं। कहते हैं कि आप 'परिवर्तन' घटना सुनना चाहते हैं। उस स्थिति में 'इनिशियलाइज़' पद्धति को निकाल नहीं दिया जाएगा और विशेषता के लिए आपके कस्टम मान को सर्वर से json ऑब्जेक्ट से बदल दिया जाएगा। अपने प्रोजेक्ट में मैंने इस समस्या का सामना किया। मॉडल के 'सेट' विधि को ओवरराइड करने का मेरा समाधान:

set: function(key, val, options) {
    if (typeof key === 'object') {
        var attrs = key;
        attrs.content = new module.BaseItem(attrs.content || {});
        attrs.children = new module.MenuItems(attrs.children || []);
    }

    return Backbone.Model.prototype.set.call(this, key, val, options);
}, 

0

जबकि नेस्टेड ऑब्जेक्ट विशेषताओं के बजाय बैकबोन मॉडल का उपयोग करने वाले कुछ मामलों में डॉमेनिक के रूप में उल्लेख किया गया है, सरल मामलों में आप मॉडल में एक सेटर फ़ंक्शन बना सकते हैं:

var MyModel = Backbone.Model.extend({
    defaults: {
        obj1 : {
            "myAttribute1" : false,
            "myAttribute2" : true,
        }
    },
    setObj1Attribute: function(name, value) {
        var obj1 = this.get('obj1');
        obj1[name] = value;
        this.set('obj1', obj1);
    }
})

0

यदि आप बैकएंड के साथ बातचीत करते हैं, जिसमें नेस्टिंग संरचना के साथ ऑब्जेक्ट की आवश्यकता होती है। लेकिन रैखिक संरचना के साथ काम करने के लिए रीढ़ की हड्डी में अधिक आसान है।

backbone.linear आपकी मदद कर सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.