ব্যাকবোন.জেগুলি নেস্টেড অবজেক্ট অ্যাট্রিবিউটটি পেয়ে যায় এবং সেট করে


105

ব্যাকবোন.জেএস সম্পর্কে ফাংশন পেতে এবং সেট করা সম্পর্কে আমার একটি সাধারণ প্রশ্ন রয়েছে ।

1) নীচের কোড সহ আমি কীভাবে সরাসরি 'পেতে' বা 'সেট' করতে পারি?

আরেকটি প্রশ্ন:

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ক্ষেত্রে এই বিষয়টির মধ্যে 1 ) রেফারেন্স ( রেফারেন্স দ্বারা পাস করা) নির্দিষ্ট করা হয়, সেই একই জিনিসটি মডেলের সমস্ত দৃষ্টান্তে ভাগ করা হবে। বর্তমান অনুশীলনটি defaultsএকটি ফাংশন হিসাবে সংজ্ঞায়িত করা হয় যা কোনও বস্তুকে ডিফল্ট হিসাবে ব্যবহার করার জন্য ফেরত দেয়। backbonejs.org/# মডেল-ডেফাল্টস (সূক্ষ্ম দ্রষ্টব্য দেখুন)
জোনাথন এফ

1
@ জোনাথনএফ মন্তব্যগুলি উত্তরের জন্য নয় যাতে আপনার কখনই এই ঘোষণার দরকার পড়ে না :)
টিজে

উত্তর:


144

যদিও this.model.get("obj1").myAttribute1জরিমানা, এটি একটি বিট সমস্যাযুক্ত কারণ তারপর আপনি সেট জিনিস একই ধরনের কাজ করতে প্রলুব্ধ করা যেতে পারে, অর্থাত্

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

তবে আপনি যদি এটি করেন তবে myAttribute1পরিবর্তন ইভেন্ট বা বৈধকরণের মতো আপনি ব্যাকবোন মডেলগুলির সুবিধা পাবেন না ।

এর চেয়ে ভাল সমাধান হ'ল আপনার মডেলগুলিতে POJSOs ("প্লেইন পুরাতন জাভাস্ক্রিপ্ট অবজেক্টস") এবং এর পরিবর্তে নেস্ট কাস্টম মডেল ক্লাসগুলি বাসাতে হবে না। সুতরাং এটি কিছু দেখতে হবে:

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
@ ক্রিশ্চিয়াননুসিটাও, পেজওয়িল, বেনো: আপনি মনে করছেন পোস্টের যে বিন্দুটি ব্যাকবোন মডেলের অভ্যন্তরে ব্যাকবোন মডেলগুলিকে বাসা বাঁধবে তা আপনি মিস করেছেন। ব্যাকবোন মডেলগুলির ভিতরে প্লেইন অবজেক্টগুলি বাসাবেন না। এখানে কাজের উদাহরণ: jsfiddle.net/g3U7j
ডোমেনিক

1
আমি ব্যাকবোন.জেএস কোডটি পরিদর্শন করিনি, তবে আমার পরীক্ষা থেকে, যদি আপনার নেস্টেড কাস্টম মডেল থাকে এবং সেট () এর সাহায্যে এর কোনও সম্পত্তি পরিবর্তন করা হয় তবে এর প্যারেন্ট মডেল কোনও 'পরিবর্তন' ইভেন্ট নিজেই চালিত করবে না; আমাকে নিজেই ঘটনাটি ছড়িয়ে দিতে হয়েছিল। আমার আসলেই কোডটি পরীক্ষা করা উচিত, তবে এটি কি আপনার বোঝার?
টম

2
@ টম যে সঠিক। মডেলগুলির বৈশিষ্ট্য যখন উদাহরণস্বরূপ হয় তার জন্য ব্যাকবোন বিশেষ-কেস দেয় না 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'
তাওহীদ

দুর্দান্ত কাজ! তবে আপনার উদাহরণে লাইন 2 এর জন্য কমা পরিবর্তে কোলন প্রয়োজন?
মারিয়াচি

16

ডোমেনিকের সমাধানটি কাজ করবে তবে প্রতিটি নতুন মাইমোডেল ওবজের একই উদাহরণকে নির্দেশ করবে। এড়াতে, মাইমোডেলের মতো হওয়া উচিত:

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

পুরো ব্যাখ্যার জন্য সি 3 র উত্তর @ https://stackoverflow.com/a/6364480/1072653 দেখুন ।


1
ভবিষ্যতের পাঠকদের জন্য, আমার উত্তরটি রাস্টির উত্তরের সেরা অন্তর্ভুক্ত করার জন্য আপডেট করা হয়েছে।
ডোমেনিক

2
প্রশ্নকর্তাকে গ্রহণযোগ্য উত্তর হিসাবে এটি পতাকাঙ্কিত করা উচিত। ডোমেনিক্স একটি দুর্দান্ত শুরু, তবে এটি এটির সাথে একটি সমস্যা সমাধান করে।
জন রাশ

5

আমি এই পদ্ধতির ব্যবহার।

আপনার যদি এমন একটি ব্যাকবোন মডেল থাকে:

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

আপনি "আব" বৈশিষ্ট্যটি এর সাথে সেট করতে পারেন:

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)। এটি আমার জন্য কোনও পরিবর্তন ইভেন্ট শুরু করে না :(
হাংরি কোডার

1
আমি যখন এট্রিবিউটটিকে পছন্দ করি তখন এটি কাজ করে _.clone(m.get('x'))। ধন্যবাদ
হাঙ্গেরি কোডার

ধন্যবাদ @ হাংরিকোডার ক্লোন করার সময় এটি আমার পক্ষেও কাজ করেছিল। ব্যাকবোন অবশ্যই আপনাকে নির্ধারিত অবজেক্টের settingসাথে যে বস্তুটি রয়েছে তা তুলনা করতে হবে getting। সুতরাং আপনি যদি ক্লোন না করেন তবে দুটি বস্তু, তারপরে দুটি বস্তুর তুলনা করা হ'ল নির্ধারিত সময়ে ঠিক একই।
ডেরেক ডাহার

মনে রাখবেন যে বস্তুগুলি রেফারেন্সের মাধ্যমে পাস হয়েছে এবং স্ট্রিং এবং সংখ্যার আদিমগুলির বিপরীতে পরিবর্তিত হয়। ব্যাকবোন এর সেট এবং কনস্ট্রাক্টর পদ্ধতিগুলি আর্গুমেন্ট হিসাবে পাস করা কোনও অবজেক্ট রেফারেন্সের অগভীর ক্লোনটি চেষ্টা করে। এই অবজেক্টটির বৈশিষ্ট্যগুলিতে অন্যান্য অবজেক্টের কোনও রেফারেন্স ক্লোন করা হয়নি। আপনি যখন এটি সেট করেন এবং পুনরুদ্ধার করেন তখন রেফারেন্সটি একই হয়, যার অর্থ আপনি কোনও পরিবর্তন পরিবর্তন না করে মডেলটিকে পরিবর্তন করতে পারেন।
নিয়ালাল ক্যাম্পবেল

3

এমন একটি সমাধান রয়েছে যা এখনও কেউ ভাবেন নি যা ব্যবহারের জন্য প্রচুর। আপনি প্রকৃতপক্ষে নেস্টেড বৈশিষ্ট্যগুলি সেট করতে পারবেন না, যদি না আপনি তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করেন যা আপনি সম্ভবত চান না। তবে আপনি যা করতে পারেন তা হল মূল অভিধানের একটি ক্লোন তৈরি করা, সেখানে নেস্টেড সম্পত্তি সেট করা এবং সেই পুরো অভিধানটি সেট করা set খুবই সহজ.

//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

আমার @ পেজওয়িল একই সমস্যা ছিল এবং @ বেনো @ ডোমেনিকের সমাধানটি নিয়েছিলেন। আমার উত্তরটি পরিবর্তে ব্যাকবোন.মোডেলের একটি সাধারণ উপ-শ্রেণীর লেখা ছিল যা সমস্যার সমাধান করে।

// 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}]
});

নেস্টেডমোডেল আপনার জন্য যা করে তা এগুলি কাজ করার অনুমতি দেয় (যা মাইমোডেল জেএসএন ডেটার মাধ্যমে সেট হয়ে গেলে ঘটে):

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

শুরুতে স্বয়ংক্রিয়ভাবে মডেলগুলির তালিকা তৈরি করা সহজ হবে, তবে এই সমাধানটি আমার পক্ষে যথেষ্ট ভাল ছিল।


2

ডোমেনিক দ্বারা প্রস্তাবিত সমাধানের কিছু ত্রুটি রয়েছে। বলুন আপনি 'পরিবর্তন' ইভেন্টটি শুনতে চান। সেক্ষেত্রে 'ইনিশিয়াল' পদ্ধতিটি বরখাস্ত করা হবে না এবং বৈশিষ্ট্যের জন্য আপনার কাস্টম মানটি সার্ভার থেকে জেসন অবজেক্টের সাথে প্রতিস্থাপিত হবে। আমার প্রকল্পে আমি এই সমস্যার মুখোমুখি হয়েছি। মডেলটির 'সেট' পদ্ধতিটিকে ওভাররাইড করার জন্য আমার সমাধান:

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 আপনাকে সাহায্য করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.