Backbone: فصول العمود الفقري و ES6

تم إنشاؤها على ٧ أبريل ٢٠١٥  ·  63تعليقات  ·  مصدر: jashkenas/backbone

مع التغييرات النهائية على مواصفات فئة ES6 (التفاصيل هنا ) ، لم يعد من الممكن استخدام فئات ES6 مع Backbone دون تقديم تنازلات كبيرة من حيث البنية. لقد كتبت وصفًا كاملاً للموقف هنا (تأكد من النقر للوصول إلى التعليقات في الجزء السفلي للحصول على خيار تخفيف إضافي) ، ولكن بشكل أساسي لا توجد طريقة لإضافة خصائص إلى مثيل من فئة فرعية قبل الفئات الفرعية للآباء يجري تشغيل المُنشئ.

إذا هذا:

class DocumentRow extends Backbone.View {

    constructor() {
        this.tagName =  "li";
        this.className = "document-row";
        this.events = {
            "click .icon":          "open",
            "click .button.edit":   "openEditDialog",
            "click .button.delete": "destroy"
        };
        super();
    }

    initialize() {
        this.listenTo(this.model, "change", this.render);
    }

    render() {
        //...
    }
}

لم يعد صالحًا في مواصفات ES6 النهائية. بدلاً من ذلك ، لديك 3 خيارات (ليست جذابة جدًا) بشكل فعال إذا كنت ترغب في محاولة جعل هذا يعمل:

إرفاق جميع الخصائص كوظائف

يسمح العمود الفقري بهذا ، ولكن من الغباء كتابة شيء مثل هذا:

class DocumentRow extends Backbone.View {

    tagName() { return "li"; }

    className() { return "document-row";}

    events() {
        return {
            "click .icon":          "open",
            "click .button.edit":   "openEditDialog",
            "click .button.delete": "destroy"
        };
    }

    initialize() {
        this.listenTo(this.model, "change", this.render);
    }

    render() {
        //...
    }
}

بالمقارنة مع بناء الجملة الحالي يمتد

قم بتشغيل المنشئ مرتين

لا أعتبر هذا خيارًا حقيقيًا نظرًا للمشكلات التي قد يتسبب فيها تشغيل التهيئة مرة ثانية باستخدام cids مختلفة ، وما إلى ذلك.

قم بتمرير جميع الخصائص كخيارات افتراضية إلى مُنشئ الطبقة الفائقة

تم اقتراح هذا من قبل أحد المعلقين في مدونتي وربما يكون الخيار الحالي الأكثر عملية. يبدو شيئًا كالتالي:

class MyView extends Backbone.View {
  constructor(options) {
    _.defaults(options, {
      // These options are assigned to the instance by Backbone
      tagName: 'li',
      className: 'document-row',
      events: {
        "click .icon": "open",
        "click .button.edit": "openEditDialog",
        "click .button.delete": "destroy"
      },
      // This option I'll have to assign to the instance myself
      foo: 'bar'
    });


    super(options);


    this.foo = options.foo;
  }
}

نظرًا لأن كل هذه الخيارات الحالية تتضمن تنازلات واضحة بالنسبة إلى العمود الفقري الحالي الذي يمتد إلى بناء الجملة ، فسيكون من الرائع أن يتم تطوير حل أفضل. لست متأكدًا تمامًا من الشكل الذي يجب أن يبدو عليه هذا ، ولكن إحدى الأفكار التي خطرت ببالي أثناء قيامي بالكتابة لمدونتي كانت إضافة وظيفة "خصائص" من شأنها إخراج تجزئة للخصائص. يمكن للمُنشئ بعد ذلك تشغيل هذه الوظيفة وإضافتها إلى المثيل قبل المعالجة الأخرى التي يقوم بها المُنشئ.

change

التعليق الأكثر فائدة

من خلال القراءة من خلال هذا أجد https://github.com/epicmiller/es2015-default-class-properties نهجًا جيدًا. عند المحاولة ، أدركت أن العمود الفقري لديه دعم مدمج لهذا. على سبيل المثال:

class MyModel extends Backbone.Model.extend({
   idAttribute: 'id'
}) {
   // ...
};

سيقوم الكود أعلاه بتعيين MyModel.prototype.idAttribute بشكل صحيح. ملاحظة ، بالنسبة إلى TypeScript ، يحتاج ملف الإعلان إلى تعديل طفيف لإرجاع واجهة دالة مُنشئ ، ولكن هذه تفاصيل لا صلة لها بمستخدمي ES6 ...

ال 63 كومينتر

نعم هذا بالتأكيد المشكله شكرا لقيامك بالعمل الشاق.

أعتقد أن الأمر الأخلاقي في القصة هو عدم استخدام فصول ES6 مع العمود الفقري ، على الأقل حتى وصول دعم الملكية الثابتة إلى الأرض. من بين الخيارات الاحتياطية التي اقترحتها ، فإن الحل المفضل لدي هو تحديد السلاسل / الكائنات كقيم إرجاع. يتمثل جزء أساسي من تصميم Backbone's API في هذه السلاسل والكائنات المشتركة في النموذج الأولي ، وقد يؤدي ذلك إلى تلطخ واجهة برمجة التطبيقات لتطلب من المطورين تعيين كل خاصية إلى المثيل في المُنشئ (ناهيك عن إهدار الذاكرة).

بصرف النظر عن التناسق ، هل هناك أي سبب لاستخدام الكلمة الأساسية للفصل مع العمود الفقري أكثر من extend ؟

مشاركة مدونة رائعة. كنت أتساءل كيف ستلعب فصول ES6 و Backbone معًا. أما بالنسبة لك الحلول:

  1. إرفاق جميع الخصائص كوظائف : أنا لست معارضًا بشدة لهذا. إنه ليس نظيفًا مثل إعداد الكائن مباشرة على النموذج الأولي ، لكنني رأيت الكثير من التعليمات البرمجية تتعثر على كائنات النموذج الأولي. هذه الطريقة محصنة ، ولهذا أعتقد أن ES6 اختار عدم تضمين خصائص الطبقة.
  2. مرر كل الخصائص كخيارات افتراضية : أليست هذه هي الطريقة التي تفعل بها شيئًا بلغة كلاسيكية؟ أشعر أن هذا حل أقل نظافة مما سبق.
  3. قم بتشغيل المنشئ مرتين : Ick.

أعتقد أن الأمر الأخلاقي في القصة هو عدم استخدام فصول ES6 مع العمود الفقري ، على الأقل حتى وصول دعم الملكية الثابتة إلى الأرض.

حتى خصائص الفصل تأتي بعد المكالمة super() . :خائب الامل:

بصرف النظر عن التناسق ، هل هناك أي سبب لاستخدام الكلمة الأساسية للفصل مع العمود الفقري على الامتداد؟

لقد تناولت هذا في منشور المدونة. عمليا؟ لا. من الناحية النظرية ، سيسمح لـ Backbone على المدى الطويل بتقليل الكود والمفاهيم الإضافية ، ولكن من الناحية الواقعية ، سوف يستغرق الأمر بضع سنوات على الأقل قبل أن يتم دعم فئات ES6 على نطاق واسع على جميع المتصفحات ذات الصلة دون نقل البيانات ، وسيكون تقليل الكود هو التالي لا شيء.

لكن لا تقلل من شأن جانب الاتساق. إذا أصبحت هذه "طريقة" القيام بالبرمجة الموجهة للكائنات في JavaScript (يبدو أنه من المحتمل أن يتم وضع المعايير على هذا من Ember / Angular / React / Typescript / Aurelia ، إلخ) ، فإن عدم استخدام العمود الفقري سيكون بمثابة منحنى تعليمي إضافي للمكتبة بالنسبة إلى خيارات أخرى. خاصة للمطورين المبتدئين. لست متأكدًا من أن الأمر يستحق التغيير بالضرورة. لكن الأمر لا يتعلق فقط باتساق "هبجول العقول الصغيرة" المتحذلق.

أتفق مع @ akre54 و jridgewell على أن نهج "إرفاق جميع الخصائص

سيكون لدى ES7 خصائص فئة صحيحة ، أعتقد https://gist.github.com/jeffmo/054df782c05639da2adb

اقتراح ES7 هو مجرد اقتراح مبكر للغاية مدفوع من المجتمع. ليس من الواضح على الإطلاق أنه سيكون في الواقع جزءًا من المواصفات الرسمية. تؤدي عمليات التنفيذ الحالية إلى إضافة الخصائص إلى المثيل بعد تشغيل المُنشئ ، لذلك لا يساعد ذلك مع العمود الفقري. (انظر رابط jridgewell أعلاه أو جربه بنفسك مع Babel 5.0.0)

jridgewell كنت أشير إلى هذا الجزء من مشاركة benmccormick :

لاحظ مطورو React نفس المشكلات مع مُهيئ الخاصية التي يواجهها مستخدمو العمود الفقري. كجزء من الإصدار 0.13 من React ، فإنهم يدعمون صيغة تهيئة خاصية خاصة للفئات ، والتي قد يتم توحيدها في النهاية. هناك المزيد من المعلومات حول هذا الموضوع في

انظر على سبيل المثال قشور js-decorator الخاص بـ wycats أو اقتراح فئات الانسجام الأصلي (الذي تم استبداله).

قد أقترح أن نستخدم حروف مع خصائص الفصل:

class Row extends Backbone.View {
  get tagName() { return 'li'; }
}

كحل أخير مطلقًا ، يمكننا التحقق على سبيل المثال من الدعائم الثابتة باستخدام المساعد a la _.result :

_.instOrStaticVar = function(instance, property) {
  if (instance == null) return void 0;
  var value = instance[property] || instance.constructor[property];
  return _.isFunction(value) ? value.call(instance) : value;
}

نعم ، لكن:

لسوء الحظ ، يعرّف هذا الإصدار خصائص الفئة بأنه يتم إنشاء مثيل لها بعد تشغيل مُنشئ الطبقة الفائقة ، لذلك لا يحل هذا مشكلات Backbone هنا.

إذن ، ES5'd:

// ES6
class View extends Backbone.View {
  tagName = 'li';

  constructor() {
    // Do anything that doesn't touch `this`
    super();
    // Do anything that touches `this`
  }
}

// ES5
function View() {
  // Do anything that doesn't touch `this`
  Backbone.View.apply(this, arguments);

  // Add class properties
  this.tagName = 'li';

  // Do anything that touches `this`
}
View.prototype = _.create(Backbone.View.prototype, {
  constructor: View
});

سيظل عنصرنا مبنيًا قبل أن نحصل على تغيير لتعيين متغير الحالة.

شاهد على سبيل المثال سترومان js-decorators wycats ...

هل يمكن أن تشرح كيف سيطبق المصممون؟

قد أقترح أن نستخدم حروف مع خصائص الفصل:

: +1 :. أرى أنه نفس القارب مثل إرفاق جميع الخصائص كوظائف . ليس نظيفًا مثل ما لدينا حاليًا ، ولكنه مقبول تمامًا ومقاوم للطفرات.

كملاذ أخير مطلقًا ، يمكننا التحقق على سبيل المثال أو الدعائم الثابتة مع النتيجة المساعدة a la _.

قد يكون ذلك ممتعًا ...

يمكنك أن تفعل:

class MyView extends Backbone.View {
  constructor() {
    super({ tagName: 'h1' });
    this.el.textContent = 'Hello World';
  }
}

thejameskyle هذا هو تمرير جميع الخصائص كخيارات افتراضية لخيار

بدلاً من الاعتماد على super() لإعداد الفصل ، يمكنك ببساطة الحصول على وظيفة init() أو شيء من هذا القبيل.

class DocumentRow extends Backbone.View {

    constructor() {
        super();
        this.tagName =  "li";
        this.className = "document-row";
        this.events = {
            "click .icon":          "open",
            "click .button.edit":   "openEditDialog",
            "click .button.delete": "destroy"
        };
        this.init();
    }

    initialize() {
        this.listenTo(this.model, "change", this.render);
    }

    render() {
        //...
    }
}

milesj همم ؟ سيؤدي ذلك إلى حدوث خطأ على الفور مع مواصفات فئة ES6 النهائية

في فئة مشتقة ، يجب عليك استدعاء super () قبل أن تتمكن من استخدام هذا

حتى لو نجح الأمر ، فأنت لا تتصل فعليًا بمُنشئ العمود الفقري ولن تحصل على كود التهيئة الخاص به.

شاهد هذا الرابط من مشاركتي الأولى: http://www.2ality.com/2015/02/es6-classes-final.html

milesj : الشيء هو ، عليك الاتصال بـ super() قبل تعيين this.tagName أو ما شابه. ونظرًا لأننا نضمن وجود عنصر في مُنشئ العرض ، فقد أنشأنا عنصرًا بالفعل قبل أن نقوم بتعيين this.tagName .

milesj لا يزال غير مسموح به عندما تقوم

jridgewell أوه آسف ، فاتني ذلك. يبدو أنه الخيار الأكثر طبيعية. لقد تحدثت إلى جيفمو وسيبك حول هذا الموضوع.

لإعطائك بعض الخلفية الدرامية يا رفاق ، فإن السبب هو أنه من أجل دعم الأنواع الأصلية الموسعة (مثل المصفوفة) لم يتم تحديد this حتى تقوم باستدعاء طريقة super() . وإلا ستواجه مشكلة في التهيئة في DOM (ويفترض في أماكن أخرى).

jridgewellthejameskyle ثم ببساطة الاتصال السوبر () أولا (على سبيل المثال تحديث). لا أرى المشكلة هنا حقًا لأنني فعلت نفس الشيء في فصول ES6. ما عليك سوى نقل منطق منشئ العروض إلى طريقة init() .

هذا كثير من التعليمات البرمجية باهظة الثمن لتشغيلها مرتين.

نعم ، لقد قرأتها ، وما زلت أشعر بالفضول لماذا هذا ليس حلاً. يستمر الجميع في الحديث عن مُنشئ الآراء الذي يجب أن يتم استدعاؤه ، لكن هذا ليس هو الحال بالضرورة. لماذا لا يعتبر شيء مثل التالي حلاً (وإن كان مفتعلًا قليلاً)؟

var View = Backbone.View = function(options) {
    this.cid = _.uniqueId('view');
    // extend()ing options is no longer needed if properties are set directly
};

View.prototype.setup = function() {
    this._ensureElement();
    this.initialize.call(this, arguments);
};

class DocumentRow extends Backbone.View {
    constructor() {
        super();
        this.tagName =  "li";
        this.className = "document-row";
        this.events = {
            "click .icon":          "open",
            "click .button.edit":   "openEditDialog",
            "click .button.delete": "destroy"
        };
        this.setup(...arguments);
    }
}

أظن ذلك بسبب التوافق مع الإصدارات السابقة مع غير ES6؟

عندئذٍ لن تعمل فئة View الافتراضية نظرًا لأن المُنشئ لا يستدعي أبدًا #setup . وإجبار مكالمة فئة فرعية على أي شيء بخلاف super() سيكون أمرًا مزعجًا للغاية.

هذه مشكلة يجب على جميع فئات ES6 التعامل معها ، وليس فقط العمود الفقري. لقد قمت بحلها شخصيًا باستخدام مواصفات خصائص فئة Babel ES7.

milesj كما هو مذكور قبل خصائص فئة ES7 لا تحل هذه المشكلة حيث لا يتم إنشاء مثيل لها حتى نهاية المنشئ.

لقد تحدثت إلى جيفمو وسيبك حول القيام بذلك:

class Root {
  rootProp = 'root';
  constructor() {
    console.log('Root', this.rootProp);
    console.log('Root', this.derivedProp);
  }
}

class Derived extends Root {
  derivedProp = 'derived';
  constructor() {
    super();
    console.log('Derived', this.rootProp);
    console.log('Derived', this.derivedProp);
  }
}

يقصد بـ:

function Root() {
  this.rootProp = 'root';
  console.log('Root', this.rootProp);
  console.log('Root', this.derivedProp);
}

function Derived() {
  super();
  this.derivedProp = 'derived';
  console.log('Derived', this.rootProp);
  console.log('Derived', this.derivedProp);
}

لكن هذا لا يزال لا يحل المشكلة هنا ويؤدي إلى عدم الاتساق:

new Derived();
// >> 'Root' 'root'
// >> 'Root' undefined
// >> 'Derived' 'root'
// >> 'Derived' 'derived'

هذه مشكلة يجب على جميع فئات ES6 التعامل معها ، وليس فقط العمود الفقري.

حسنًا؟

لقد قمت بحلها شخصيًا باستخدام مواصفات خصائص فئة Babel ES7.

سيكون لديك الكثير من عناصر DIV بدون className s. راجع النقطة الأخيرة من https://github.com/jashkenas/backbone/issues/3560#issuecomment -90739676 ، https://github.com/jashkenas/backbone/issues/3560#issuecomment -91601515 و https: // github .com / jashkenas / backbone / Issues / 3560 # issuecomment -98827719.

أرى. في هذه الحالة ، أقترح استخدام الخيار "تمرير جميع الخصائص كخيارات افتراضية إلى مُنشئ الطبقة الفائقة" ، أو السطر الأخير حول إنشاء طريقة "خصائص" (والتي لا تمس المُنشئ).

class DocumentRow extends Backbone.View {
    loadProperties() {
        return {
            tagName: 'li',
            className: 'document-row',
            events: {
                "click .icon": "open",
                "click .button.edit": "openEditDialog",
                "click .button.delete": "destroy"
            },
            foo: 'bar'
        };
    }
}

// Contrived example
var View = Backbone.View = function(options) {
    this.cid = _.uniqueId('view');
    options || (options = {});
    _.extend(this, this.loadProperties(), _.pick(options, viewOptions));
    this._ensureElement();
    this.initialize.apply(this, arguments);
};

فعلت شيئًا مشابهًا في مجموعة الأدوات ، والتي يمكن رؤيتها هنا: https://github.com/titon/toolkit/issues/107

أهلا.

إذا فهمت المناقشة هنا بشكل صحيح - يناقش مطورو العمود الفقري الحلول وأفضل الممارسات ، لكن ليس لديهم نية لإجراء تغييرات فعلية على BB الأساسية للتعامل مع هذه المشكلة؟ (لا أقترح عليهم ذلك ، ولن يكون لدي أي فكرة عما يمكن أن تكون عليه هذه التغييرات). بمعنى آخر ، هل اقتراح استخدام كل الخصائص كوظائف أو الحصول على الكلمة الأخيرة في الموضوع؟ شكرا.

gotofritz نحن نناقش الحلول لأن حل ES6 لإجبار جميع الخصائص على العيش في حالات لا يتسع نطاقه. يقوم نظام الفصل في العمود الفقري بعمل الشيء الصحيح هنا.

هناك بعض النقاش حول إضافة خصائص النموذج الأولي الثابت إلى فئات ES7 ولكن لا يوجد شيء ملموس حتى الآن. في غضون ذلك ، أود أن أقول التمسك بـ Backbone extend .

شكرا. سأحاول فصول ES6 لفترة أطول قليلاً ... :-)

لصالح أي شخص آخر يتعثر في هذا الأمر ، أجد عمليًا أن "تمرير جميع الخصائص كخيارات افتراضية إلى مُنشئ الطبقة الفائقة" أفضل - على سبيل المثال ، يحتوي تطبيقنا على مسارات ديناميكية (مترجمة) يجب تمريرها في وقت إنشاء مثيل ، وامتلاك طريقة المسارات () فقط لا يعمل. في حين أن ما يلي يفعل

class Router extends Backbone.Router {

 constructor (localizedRoutes) {
    _.defaults(localizedRoutes, {
        "nonLocalizedRouteA/": "routeA"
        "*actions": "defaultRoute"
     });
 super({ routes: localizedRoutes });
}

لقد ألقيت نظرة على هذا للتو ، وأعتقد أن كلا الحلين لا يعملان مع الخاصية idAttribute التي يمتلكها النموذج. لن تعمل الطريقة لأن Backbone يستخدم model.idAttribute للوصول إلى الخاصية ؛ ولا يبدو أن مُنشئ النموذج يدعم إضافة الخصائص كخيارات تمامًا.

أعتقد أن كلا الحلين لا يعملان للخاصية idAttribute

صيد ممتاز ، سأعمل على العلاقات العامة لمعالجة هذا الأمر. في غضون ذلك ، يمكنك استخدام تدوين getter لتوفير idAttributecidPrefix ):

class Model extends Backbone.Model {
  get idAttribute() {
    return '_id';
  }

  get cidPrefix() {
    return '__c';
  }
}

لن تعمل الطريقة لأن Backbone يستخدم model.idAttribute للوصول إلى الخاصية

get idAttribute() { return '_id'; } هي طريقة getter ، يتم الوصول إليها تمامًا مثل الممتلكات العادية. this.idAttribute === '_id'; .

بدأ هذا يبدو وكأنه مطلوب إعادة كتابة كبيرة. ربما العمود الفقري v2؟

بدأ هذا يبدو وكأنه مطلوب إعادة كتابة كبيرة. ربما العمود الفقري v2؟

لا على الإطلاق ، نحن ندعم بالفعل فئة ES6 الفرعية (باستثناء النماذج ). أعتقد أنه سيكون من المثير للاهتمام أن يقوم شخص ما باستكشاف اقتراح الخاصية الثابتة @ akre54 ، ولكن حتى هذا ليس ضروريًا مع

jridgewell ، شكرًا جزيلاً على الحل السريع!

تم ذكر الديكور أعلاه في هذا الموضوع (تحديدًا اقتراح يهودا كاتس ) ، ولم يتم حل ما إذا كان ذلك سيحل هذه المشكلة.

كنت ألعب معهم كما هو مقترح ، ويمكنك كتابة مصمم مثل هذا:

function props(value) {
    return function decorator(target) {
        _.extend(target.prototype, value);
    }
}

ومن ثم يمكن كتابة المثال الذي كنا نستخدمه بهذا الشكل

@props({
      tagName: 'li',
      className: 'document-row',
      events: {
        "click .icon": "open",
        "click .button.edit": "openEditDialog",
        "click .button.delete": "destroy"
      }
    })
class DocumentRow extends Backbone.View {

    initialize() {
        this.listenTo(this.model, "change", this.render);
    }

    render() {
        //...
    }
}

يبدو أن هذا يعمل بشكل جيد بالنسبة لي. يتم تطبيق المصمم على الفصل قبل تنفيذ مُنشئ الفئة. هذه مجرد نسخة توضيحية للقول

class DocumentRow extends Backbone.View {

    initialize() {
        this.listenTo(this.model, "change", this.render);
    }

    render() {
        //...
    }
}
_.extend(DocumentRow.prototype, {
      tagName: 'li',
      className: 'document-row',
      events: {
        "click .icon": "open",
        "click .button.edit": "openEditDialog",
        "click .button.delete": "destroy"
      }
})

في الواقع ، لم أقم باختباره ، لكن ربما يمكنك جعل وظيفة تمديد العمود الفقري بالكامل هي المصمم إذا كنت تريد الدعائم الثابتة والنموذج الأولي.

لسوء الحظ ، هذا مجرد اقتراح في الوقت الحالي ، لكن Babel يدعمه وراء علم تجريبي ، لذلك إذا كان الناس يشعرون بالمغامرة ، فهذا حل ممكن هنا.

benmccormick ، تقنية الديكور تعمل جيدًا بالنسبة لي. بخلاف كون هذا مجرد اقتراح في الوقت الحالي ، هل هناك مخاوف أخرى بشأن اتباع هذا النهج؟

andrewrota أنا أكتب حرفيًا

شاهد هذا الجوهر من https://gist.github.com/StevenLangbroek/6bd28d8201839434b843

إليك معاينة لمشاركة المتابعة التي أطرحها: http://benmccormick.org/2015/07/06/backbone-and-es6-classes-revisited/ تم التحديث برابط دائم الآن

سينتقل إلى عنوان url دائم في وقت مبكر من هذا الأسبوع في وقت ما. لكن الملخص الأساسي من هذا الموضوع وما تعلمته هو:

هناك 3 طرق لجعل خصائص العمود الفقري تعمل مع مواصفات فئات ES6 الحالية (أول 2 يحتاج # 3684 ليتم اعتباره مدعومًا بالكامل):

  1. تمرير جميع الخصائص إلى السوبر في المنشئ
  2. تعامل مع جميع الخصائص كطرق
  3. أضف الخصائص مباشرة إلى النموذج الأولي بعد التصريح عن الفئة

ما زلت أرى كل هذا على أنه تقييد للتعبير إلى حد ما أو آخر. لكني أعتقد أن المشكلة ستحل بشكل أو بآخر إذا أصبح المصممون مواصفة رسمية. مع الديكور هناك خياران آخران.

  1. أضف مصممًا للدعائم يأخذ الدعائم في الجزء العلوي من الفصل ويضيفها إلى النموذج الأولي
  2. قم بإنشاء العديد من أدوات الديكور ذات الأغراض الخاصة التي تسمح بواجهة أكثر تعبيراً / دقيقة.

لا أعتقد أن أيًا من هذه الحلول يتطلب أي تعديلات إضافية على العمود الفقري بخلاف # 3684 ، ولكن سيكون هناك دور مثير للاهتمام لمكتبة العمود الفقري للديكور إذا / عندما يصبح المصممون موحدون.

أود تلقي أي تعليقات على المنشور قبل أن أنشره يوم الاثنين / الثلاثاء.

benmccormick لقد

يمكننا استخدام نفس الصيغة لـ modelEvents و collectionEvents في Marionette ، ليس فقط للمشغلات. يمكن كشفها من خلال مصمم الفصل (مثل tagName والقالب في منشور المدونة الخاص بك) ، لكنني كنت أفكر: ألا يمكننا استخدام الخصائص الثابتة لهذا؟ أم أن هذا لا يعمل في العمود الفقري؟

أتفهم أن المصممين لا يزالون في المرحلة 0 ، لكنني أعتقد أنهم سيكونون ترقية رائعة للطريقة التي نكتب بها تطبيقات Backbone ، وخاصة أسلوب الديكور على تجزئة الأحداث ، إنه نوع من أسلوب البرمجة الذي يجعلني أفضل البلع على النخر أيضًا.

StevenLangbroek انظر أعلاه لمناقشة الخصائص الثابتة.

بناء الجملة كما هو محدد حاليًا ينشئ خاصية محلية في كل حالة بدلاً من إضافتها إلى النموذج الأولي. تتم إضافة هذه الخصائص بعد تشغيل المُنشئ الفائق.

benmccormick ، يبدو

هل يجب على مصمم الديكور benmccormick الاتصال بـ _#extend مع المُنشئ وليس النموذج الأولي ثم استخدام طريقة @ akre54 _.instOrStaticVar بدلاً من _#result ؟ أدرك أن هذا سيكون تغييرًا جذريًا ، لكن يبدو أنظف بهذه الطريقة IMHO. مثل @ akre54 أشار إلى أن الخصائص المحددة بهذه الطريقة هي سلاسل وكائنات مشتركة في

سأذهب إلى أبعد من ذلك وأجعل خصائص الطبقة العاملة بالطريقة التي نحتاجها. يمكن وضع تعليقات توضيحية على خصائص الفصل أيضًا ، ويمكننا إنشاء مصمم خاص يربط الخاصية المزخرفة بالنموذج الأولي.

class TodoView extends Backbone.View {
  <strong i="6">@protoprop</strong>
  static tagName = 'li';
}

function protoprop(target, name, descriptor) {
  target.prototype[name] = descriptor.initializer()
}

انظر بابل REPL مع مثال. إنه يعتمد على الأشياء التجريبية ، ولكنه يعمل.

@ just-boris كما تمت مناقشته في تعليقات مدونتي ، السلوك الذي تراه هناك تفاصيل تنفيذ لمعالجة Babel لخصائص الفصل ومواصفات الديكور. لم يتم تعريف سلوكه في أي اقتراح في الوقت الحالي. إذا كنت ترغب في القيام بأشياء بهذه الطريقة ، فستحتاج إلى إثارة المشكلات هنا و / أو هنا لجعل المصممين في خصائص الفصل سلوكًا موحدًا. وإلا فإن ما تفعله يمكن (وربما سينتهي) في أي وقت.

لدىbenmccormick wycats / javascript-decorators بالفعل تعريف إضافي بخصوص مُبدِّلات الخاصية .

الشاغل الرئيسي هناك هو أن مُهيئ الخاصية هو واصف معتاد ، بالإضافة إلى طرق الفصل ، حتى يتمكن المصممون من لفها أيضًا. لا أرى أسبابًا للقلق ، بينما تظل المواصفات في هذا القسم دون تغيير

آه رائع جدًا ، لم أر ذلك. شكرا لتوضيح ذلك.

يوم الإثنين 21 سبتمبر 2015 الساعة 11:29 صباحًا ، بوريس سيرديوك [email protected]
كتب:

benmccormick https://github.com/benmccormick
يحتوي https://github.com/wycats/javascript-decorators بالفعل على ملفات إضافية
تعريف بخصوص مُهيئ الخاصية
https://github.com/wycats/javascript-decorators/blob/master/INITIALIZER_INTEROP.md
.

الشاغل الرئيسي هناك هو أن مُهيئ الخاصية هو واصف معتاد ،
بالإضافة إلى طرق الفصل ، حتى يتمكن المصممون من لفها أيضًا. أنا لا أرى
أسباب تدعو للقلق ، بينما تظل المواصفات في هذا القسم دون تغيير

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/jashkenas/backbone/issues/3560#issuecomment -142015454
.

أردت فقط معرفة إيجابيات / سلبيات استخدام https://github.com/typhonjs/backbone-es6 مقابل تقنية الطريقة التي اقترحهاbenmccormick.

راجع للشغل ، شكرًا benmccormick على مشاركة المدونة الممتازة!

بالإضافة إلى طلب سحب الاقتراح (# 121) مرفق هنا properties طريقة العمل https://github.com/dsheiko/backbone-abstract/tree/master/demo-es6/src/Js
كما ذكر @ akre54 ، اقترح جاستن بالفعل حلاً مشابهًا (طريقة preInitialize ). أثناء استخدامه بالفعل في فرعي ، فإنه يحل المشكلة حقًا بالنسبة لي. يبدو أنه مفيد أيضًا في TypeScript على الرغم من أنها لا تحظر خصائص الفئة التعريفية.

يبدو PS preInitialize أكثر عمومية وبالتالي فهو أفضل في هذا السياق. على الرغم من أن الأمر يشبه preConstruct إذا أطلقنا على الطريقة قبل جميع وظائف المُنشئ

نتمنى حقًا أن نرى اقتراحًا جديدًا لخصائص الفئة يضعها في النموذج الأولي. يبدو أن العديد من المشاركين في الاقتراح قلقون بشأن الآثار المترتبة ، لكني أجد أنه من غير المتسق بشكل لا يصدق أن ترتبط أساليب الفصل مباشرة بالنموذج الأولي ، بينما يضعها اقتراح جيفمو في المُنشئ.

لو اختاروا إرفاق الخصائص مباشرة بالنموذج الأولي ، فستتمكن من ترحيل أي كود React / Backbone إلى حد كبير إلى فئات ES2015.

مشاركة مدونة رائعة benmccormick !! سأستخدم هؤلاء المصممين في مشروعي

benmccormick ، لقد https://github.com/epicmiller/es2015-default-class-properties

يتم تشغيله بشكل طبيعي في أي بيئة تدعم الأصناف بشكل أصلي ، وترجمة جيدة ، وتبدو أجمل من تعريفها في المنشئ أو بعد التصريح. مع تقديم مقترحات لمصممي الديكور وخصائص الفصل في ES2016 / ES2017 ، قد يكون هذا تمرينًا أكاديميًا أكثر من كونه حلًا طويل المدى للعمود الفقري ، ولكن شيئًا كهذا يعد بالتأكيد خيارًا قابلاً للتطبيق إذا كانت فترة 2-3 سنوات طويلة جدًا. انتظر.

حسنًا ، الشيء هو أن Class Properties لا تزال في المرحلة 1 في نظام مرحلة اقتراح Ecmascript. ليس لدي أي فكرة عن السبب ، لأنه يبدو وكأنه هدية من حيث "ما يحصل عليه المستخدم". بالطبع ، ليس لدي أي فكرة عن نوع الأشياء التي قد تنكسر تحت الغطاء من الناحية التركيبية ومن حيث التطبيقات المرجعية.

https://github.com/tc39/ecma262
https://github.com/jeffmo/es-class-fields-and-static-properties

من خلال القراءة من خلال هذا أجد https://github.com/epicmiller/es2015-default-class-properties نهجًا جيدًا. عند المحاولة ، أدركت أن العمود الفقري لديه دعم مدمج لهذا. على سبيل المثال:

class MyModel extends Backbone.Model.extend({
   idAttribute: 'id'
}) {
   // ...
};

سيقوم الكود أعلاه بتعيين MyModel.prototype.idAttribute بشكل صحيح. ملاحظة ، بالنسبة إلى TypeScript ، يحتاج ملف الإعلان إلى تعديل طفيف لإرجاع واجهة دالة مُنشئ ، ولكن هذه تفاصيل لا صلة لها بمستخدمي ES6 ...

@ t-beckmann هذا حل رائع للغاية - يبدو مقروءًا ويتطلب الحد الأدنى من التغييرات. شكرا!

أدركت أن هذا الموضوع يستمر لمدة عامين حتى الآن ، لكنه لا يزال أحد أفضل النتائج (وفقط) عند البحث عن فصول العمود الفقري و ES6 ، واعتقدت أنني سأشارك حلاً محتملاً باستخدام خصائص الفصل المذكورة عدة مرات هنا .

الآن بعد أن أصبحت خصائص الفصل في المرحلة 2 ومتاحة على نطاق واسع مع إعداد babel المسبق ، اعتقدت أنني سأعطيها نظرة أخرى. كما ذكرنا ، تكمن المشكلة في خصائص المثيل / العضو في عدم تطبيقها على النموذج الأولي حتى _after_ constructor() ، ولكن يتم استخدام العديد من الخصائص التي يلزم تعيينها داخل المُنشئ. يتم تطبيق الخصائص الثابتة على الفور ، ولكن (حسب التصميم) لا يتم نسخها إلى مثيلات الفئة.

ينسخ الرقاقة التالية الخصائص الثابتة من المُنشئ إلى المثيل قبل تشغيل المُنشئ (إنشاء مُنشئ جديد بشكل فعال ، وتطبيق الخصائص ، ثم تنفيذ المُنشئ الأصلي). على الرغم من أنه اختراق بالتأكيد ، إلا أنني مسرور جدًا بالنتيجة:

الرقاقة:

export default function StaticShim(Ctor) {
    const NewCtor = function shim(...args) {
       Object.keys(Ctor).forEach((key) => {
            if (this[key] === undefined) {
                this[key] = toApply[key];
            }
        });

        Object.assign(this, this.constructor);

        Ctor.apply(this, args);
    };

    NewCtor.prototype = Object.create(Ctor.prototype);
    NewCtor.prototype.constructor = NewCtor;

    Object.keys(Ctor).forEach((key) => {
        if (NewCtor[key] === undefined) {
            NewCtor[key] = Ctor[key];
        }
    });

    return NewCtor;
}

ثم في الاستخدام:

class TestModel extends StaticShim(Backbone.Model) {
    static idAttribute = '_id';
    static urlRoot = '/posts';

    initialize() {
        console.log(this.url()); // Correctly logs "/posts/{id}"
    }
}

أردت فقط تركه هنا في حال كان يساعد أي شخص آخر ، أو أي شخص لديه أي أفكار حول هذا الموضوع. شكرا!

إلزامي آسف لإحياء قضية قديمة.

هل من الممكن أو يستحق الأمر كتابة ملحق babel يحول إعلان فئة ES6 لاستخدام Backbone. *. extension ({...})؟

enzious بالتأكيد يبدو ممكنا. سواء كان الأمر يستحق الأمر متروك لك :)

يبدو حل @ t-beckmann هو

بالنسبة لي ، يبدو الأمر غير صحيح ، أليس من الأنسب أن يكون لديك طريقة تحدد السمة idAttribute؟

بالإضافة إلى ذلك ، سيكون من الرائع أن يكون هناك دعم Promise. وهو نهج أصلي أكثر من استخدام jquery Defirmed ، والذي أود شخصياً أن أراه مهملاً في Backbone.

لا تزال القصة هنا غير واضحة تمامًا لتحديث تطبيقات Backbone القديمة للاستفادة من الأدوات الحديثة وميزات اللغة. من المحبط بشكل خاص رؤية أشياء مثل Symbol.iterator مطبقة وغير متوفرة في إصدار الإنتاج.

لأولئك الذين ما زالوا يبحثون عن إجابات أوضح لهذا السؤال ، أقوم بإضافة TypeScript إلى تطبيق العمود الفقري ووجدت الحل من هذا التعليق مفيدًا للغاية.

حتى الآن ، تعمل بشكل جيد بما فيه الكفاية ، مع وجود عيب يتمثل في الاضطرار إلى وضع تعليق توضيحي على الخصائص التي يتم تمريرها من خلال مصمم الديكور بدلاً من الحصول على استدلال أجمل.

export function Props<T extends Function>(props: { [x:string]: any }) {
  return function decorator(ctor: T) {
    Object.assign(ctor.prototype, props);
  };
}

@Props({
  routes: {
    home: "home",
    about: "about",
    dashboard: "dashboard",
    blog: "blog",
    products: "products",
    accountSettings: "accountSettings",
    signOut: "signOut",
  },
})
export class Router extends Backbone.Router {
  home() {}
  about() {}
  // ...
}

@Props({
  model: CategoryModel,
  comparator: (item: CategoryModel) => item.display_value,
})
export class CategoryCollection extends Backbone.Collection<CategoryModel> {}

مثال على التعليق التوضيحي لخاصية الوضوح:

image

raffomania ، jridgewell & Co. ، لما تستحقه ، تمكن فريقي من التغلب على هذه المشكلة عن طريق إضافة idAttribute إلى النموذج الأولي خارج الفصل.

يمتد مثال فئة ParentExample {
// طرق الفصل وما إلى ذلك هنا
}

س مثال = مثال ؛

x.Example.prototype.idAttribute = 'customIdAttr' ،

kamsci فعلت الشيء نفسه في هذا الفرع حيث قمت بتحويل Backbone إلى ES6

يستخدم Backbone _configuration_ إلى أن تصبح كائنات التكوين _declarative_. هذا جميل لكنه لن يلعب دورًا لطيفًا مع الميراث. (استنساخ الفصل ، ثم قم بتكوينه. هذا ليس وراثة.)

إذا كنا سنكتب رمزًا جديدًا باستخدام العمود الفقري ، فلا بأس من التفكير بشكل مختلف. قص ولصق كود ES5 ثم جعله يبدو وكأنه ES6 لا يعمل. وماذا في ذلك؟

ليس لدي أي مشكلة على الإطلاق في تمرير كل شيء من خلال كائن التكوين. كيف نكشف محتويات هذا التكوين ، أو نجعل من السهل قراءته / التعامل معه ، هي مشكلة يجب حلها ، وليس البكاء.

لا أحد يريد تشغيل مُنشئ مرتين. هذا سخيف. لكن نمط

Foo = BackboneThing.extend ({LONG DECLARATIVE OBJECT LITERAL}) قبيح محب للأم أيضًا. لقد كنتم جميعًا تفعلون ذلك منذ فترة طويلة ولا ترون كم هو قبيح.

لمعلوماتك: لدي مشروع Marionette كبير ، وأردت استخدام بناء جملة ES6. لقد قمت بإنشاء محول jscodeshift يقوم بترجمة العمود الفقري للإعلانات إلى فئات ES6. إنه يقوم بالعديد من الافتراضات المبسطة ، ولكنه قد يظل مفيدًا للبعض منكم ، إذا كان ذلك فقط كنقطة بداية. يتبع بناء الجملة الذي اقترحه @ t-beckmann حيث واجهت مشكلات مع مصممي الديكور.
https://gist.github.com/maparent/83dfd65a37aaaabc4072b30b67d5a05d

بالنسبة لي يبدو أن هناك تسمية خاطئة غريبة في هذا الموضوع. "الخصائص الثابتة" لـ ES6 هي خصائص في المُنشئ موجودة في الفئة بدون إنشاء مثيل (Class.extend على سبيل المثال). في هذا الموضوع ، يبدو أن "الخصائص الثابتة" تشير إلى سمات مسماة في النموذج الأولي بقيمة "ثابتة" (وليس حروف أو وظائف). هل فهمت ذلك بشكل صحيح؟

بالنسبة لخصائص النموذج الأولي ذات القيمة الثابتة ، فإن الإعلان عن قيم التهيئة المسبقة للعمود الفقري كقيم لإرجاع الدالة يعد انتقالًا مباشرًا تمامًا ويعمل بشكل جيد مثل _. الجزء العلوي من وظيفة التهيئة كالمعتاد. يبدو أن هذه المشكلة تظهر فقط لأنه في فئات ES6 ، لا يمكنك تحديد خصائص النموذج الأولي بقيمة ثابتة في الوقت الحالي ، فقط القيم والمحددات والوظائف.

في كلتا الحالتين ، لا يتم توريث الخصائص الثابتة للمنشئ / الفئة (Class.extend) في العمود الفقري كما هو الحال في ES6. ينسخ العمود الفقري الخصائص الثابتة للفئة إلى الفئة / المُنشئ الجديد في كل مرة عند تنفيذ وظيفة الامتداد بدلاً من أن ترث هذه الخصائص كما يفعل ES6. لقد قمت بعمل علاقات عامة لإصلاح ذلك هنا https://github.com/jashkenas/backbone/pull/4235

سأكون ممتنًا لبعض التعليقات / التعليقات ، لست متأكدًا مما إذا كان سيؤدي إلى كسر أي شيء ، لقد اختبرت ذلك قليلاً ويبدو أنه يعمل بشكل جيد. ترث فئات العمود الفقري Class.extend بعد ذلك بدلاً من نسخ مرجع إلى كل مُنشئ جديد.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

alundiak picture alundiak  ·  7تعليقات

jamiebuilds picture jamiebuilds  ·  12تعليقات

etler picture etler  ·  13تعليقات

azizZaben picture azizZaben  ·  5تعليقات

miguelpayet picture miguelpayet  ·  9تعليقات