Backbone: التنقل () مع وجود مسافة في عنوان URL يؤدي إلى تشغيل المسار حتى عند تشغيل {trigger: false} في Firefox

تم إنشاؤها على ٢٧ نوفمبر ٢٠١٤  ·  8تعليقات  ·  مصدر: jashkenas/backbone

ضع في اعتبارك هذا المثال:

$(function(){
var AppRouter = Backbone.Router.extend({

    routes: {
        '(count/:count)': 'home',
    },

    home: function(currCount) {
        var counter = 0;
        var thisObj = this;

        $("body").html($("<p>Click me</p>").on('click', function() {
            console.log("clicked "+counter);
            counter++;
            thisObj.navigate('count/'+counter, {trigger:false, replace: true});
        }));

        console.log('home route: '+currCount);    
    },
});

window.app = new AppRouter();
Backbone.history.start();
});

يجب أن يسجل هذا "مسار المنزل: فارغ" ثم تابع تسجيل "انقر فوق #" لكل نقرة على "انقر فوقي".

الآن ، قم بإجراء تعديل صغير. أضف مسافة إلى عنوان url في التنقل ():

thisObj.navigate('count/ '+counter, {trigger:false, replace: true});

حاول مرة أخرى وستجد أن "مسار المنزل: #" سيبدأ أيضًا في التسجيل ، وسيعاد ضبط العداد _ اثنان من كل ثلاث نقرات_.

هذا موجود في الإصدار 1.1.2 وأنا أختبر على أحدث إصدار من Firefox 33.1. لا أواجه هذه المشكلة في Chrome - قد يكون ذلك بسبب أن Chrome ربما يفعل شيئًا لتشفير المسافات في عنوان URL. لست متأكدا بالرغم من ذلك.

أدرك أن حرف المسافة يجب ألا يكون في عنوان URL في المقام الأول ، ولكن هذا السلوك غريب ويجب على الأقل توثيقه. (على سبيل المثال ، "قد لا يعمل التنقل () بالشكل المتوقع مع عناوين URL التي تحتوي على مسافات (أو غيرها من الأحرف غير الآمنة ؟؟).")

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

invalid

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

هذا ما اكتشفته. في Firefox ، إذا قمت بفحص المتغير "this.location.href" ، فسيتم ترميز أي مسافات بيضاء في المتغير إلى٪ 20. Chrome (ويفترض IE) يتركهم كمسافات بيضاء. هذه مشكلة في Backbone ، لأنه عندما تذهب للتنقل ، تجري "checkUrl ()" مقارنة بين "this.fragment" مع القيمة التي تم إرجاعها لـ "this.getFragment ()" لتحديد ما إذا كنت تريد استدعاء "هذا أم لا. loadUrl () "، إذا لم تتطابق. تعرض this.getFragment () قيمة this.location.href ، مع استبدال٪ 20 بأي مسافات في Firefox (أو أي ترميز لهذه المسألة). تُرجع this.fragment مكافئًا مفككًا. يبقى this.fragment مفككًا ، بغض النظر عما إذا كنت تستخدم encodeURI () على عنوان URL الخاص بك ، لأنه في وظيفة "navigate ()" ، يتم تعيين this.fragment عن طريق استدعاء "this.decodeFragment ()" على عنوان URL الذي تم تمريره في ، وإزالة أي محاولات لفرض التشفير.

لذلك ، إذا كان this.fragment دائمًا عنوان URL تم فك ترميزه بسبب استخدام this.decodeFragment () ، وكان عنوان URL يحتوي على أي أحرف من شأنها أن تتغير بتشفيرURI () (في هذه الحالة المسافات) ، فلن يتطابق أبدًا مع القيمة التي تم إرجاعها من هذا .getFragment () في Firefox ، نظرًا لأن Firefox يشفر قيمة this.location.href ، في حين أن المتصفحات الأخرى لا تفعل ذلك. نظرًا لعدم تطابق هاتين القيمتين ، يتم استدعاء this.loadUrl () في checkUrl () ، بغض النظر عما إذا كانت معلمة المشغل في router.navigate صحيحة أم لا.

سيكون الإصلاح الأولي (الاختبار المسبق) هو تغيير القيمة المرجعة لطريقة "getHash ()" ليصبح نصها كما يلي:

return match ? this.decodeFragment(match[1].replace(pathStripper, '')) : '';

ال 8 كومينتر

مرحباchaimpeck! شكرا على الإبلاغ عن هذا.

لسوء الحظ ، لم أتمكن من إعادة إنتاجه باستخدام الكود أعلاه. لقد جربت أحدث إصدار من Chrome و Firefox مع كل من الفرع الرئيسي وإصدار 1.1.2. هل تمانع في نشر مثال عملي في جوهر / بن / كمان يمكنني إلقاء نظرة عليه؟

لقد واجهنا بالتأكيد مشكلات في ترميز / فك تشفير أحرف معينة في Firefox من قبل ولا أشك في وجود المزيد. : مبتسم:

لقد رأيت بالفعل هذه المشكلة نفسها بالضبط ، لكنني غير قادر على مشاركة الكود الخاص بي. سأرى ما إذا كان بإمكاني محاكاة بعض كود الاختبار لتكرار ذلك ، لكنني اكتشفت أن المشكلة بالتأكيد تعتمد على المتصفح. تعمل جميع الإصدارات الحديثة من IE و Chrome بشكل جيد ، ولكن على الأقل على Firefox v31.5.0 (لا تسأل ، أنا أكره البنية التحتية التي علقنا بها) ، فهي تعمل بالتأكيد دون إضافة خيار المشغل.

هذا ما اكتشفته. في Firefox ، إذا قمت بفحص المتغير "this.location.href" ، فسيتم ترميز أي مسافات بيضاء في المتغير إلى٪ 20. Chrome (ويفترض IE) يتركهم كمسافات بيضاء. هذه مشكلة في Backbone ، لأنه عندما تذهب للتنقل ، تجري "checkUrl ()" مقارنة بين "this.fragment" مع القيمة التي تم إرجاعها لـ "this.getFragment ()" لتحديد ما إذا كنت تريد استدعاء "هذا أم لا. loadUrl () "، إذا لم تتطابق. تعرض this.getFragment () قيمة this.location.href ، مع استبدال٪ 20 بأي مسافات في Firefox (أو أي ترميز لهذه المسألة). تُرجع this.fragment مكافئًا مفككًا. يبقى this.fragment مفككًا ، بغض النظر عما إذا كنت تستخدم encodeURI () على عنوان URL الخاص بك ، لأنه في وظيفة "navigate ()" ، يتم تعيين this.fragment عن طريق استدعاء "this.decodeFragment ()" على عنوان URL الذي تم تمريره في ، وإزالة أي محاولات لفرض التشفير.

لذلك ، إذا كان this.fragment دائمًا عنوان URL تم فك ترميزه بسبب استخدام this.decodeFragment () ، وكان عنوان URL يحتوي على أي أحرف من شأنها أن تتغير بتشفيرURI () (في هذه الحالة المسافات) ، فلن يتطابق أبدًا مع القيمة التي تم إرجاعها من هذا .getFragment () في Firefox ، نظرًا لأن Firefox يشفر قيمة this.location.href ، في حين أن المتصفحات الأخرى لا تفعل ذلك. نظرًا لعدم تطابق هاتين القيمتين ، يتم استدعاء this.loadUrl () في checkUrl () ، بغض النظر عما إذا كانت معلمة المشغل في router.navigate صحيحة أم لا.

سيكون الإصلاح الأولي (الاختبار المسبق) هو تغيير القيمة المرجعة لطريقة "getHash ()" ليصبح نصها كما يلي:

return match ? this.decodeFragment(match[1].replace(pathStripper, '')) : '';

لا تزال بحاجة مع الإصدار الأخير لذا شكرا لك!

لدي نفس المشكلة عند محاولة استخدام أحرف غير قياسية في عنوان URL ، في حالتي åäö (الأحرف الموجودة في الأبجدية السويدية). أحدث إصدار من Chrome و Backbone.

نجح حل sjmiller85 لي أيضًا. اشكرك كثيرا!

@ sjmiller85 ماذا كان الحل هنا؟ لا أفهم تمامًا ما الذي يجب استخدامه في "pathStripper". هل هذا هو regex؟
تحرير: هذا يعمل في موقعي. انظر https://github.com/jashkenas/backbone/pull/3955/files
getHash: function (t) { var e = (t || this).location.href.match(/#(.*)$/); return e ? e[1] : "" }

Aggror pathStripper ، وفقًا للوثائق ، عبارة عن regex مخزن مؤقتًا لتجريد عناوين url من التجزئة.

// Cached regex for stripping urls of hash.
var pathStripper = /#.*$/;

لذلك فهو مكافئ للحل الخاص بك ، فقط أكثر دقة وفعالية :)

تجنب إضافة نفس التجزئة المتزامنة إلى جهاز التوجيه الخاص بك وكذلك اعتني بالحالة الأولية ، وسأعرض لك رمزًا
(لمعالجة الحالة الأولية) (لمنع إضافة نفس المسارات في وقت واحد)
إذا (route.length === 1 || المسارات [route.length-1] === getHash ()) {
عودة كاذبة؛
}
آخر{
route.push (getHash ())
} ؛

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