لقد كنت أكتب تطبيق Svelte يحتاج إلى التثبيت الذاتي في كل صفحة. اكتشفت كيفية إضافة ملف JS الخاص بي إلى قسم الرأس وجعله يتم تحميله عند تحميل الصفحة الأولى. ومع ذلك، مع تجربتي، أدركت أن discourse يجلب محتوى جديدًا عبر XHR ويستبدل أقسامًا معينة، وبالتالي لم يتم إعادة تهيئة تطبيقي عند تحميل صفحة جديدة.
لقد لعبت بمحاولات مختلفة للحصول على إشعار عند تغيير الصفحة، ولكن لا يبدو أن Ember يوفر الخطافات، ولم أتمكن من العثور على أي أحداث مخصصة يمكنني الاستماع إليها.
يبدو أن إحدى الطرق هي إضافة مراقب طفرة إلى DOM ومراقبة التغييرات. وجدت أن "موضوع # يبدو أنه هو الذي يتم إعادة تحميله (وتتغير السمات بحيث يمكنك فقط مراقبة تغييرات السمات). لقد قمت بإعداد مراقب طفرة هناك (مراقبو الطفرة هم الطريقة الجديدة والأكثر أداءً لمراقبة تغييرات DOM). الطريقة التي تعمل بها هي مراقبة التغييرات، وعندما تحدث، تشغيل رد اتصال لإعادة تحميل تطبيق Svelte الخاص بي لتلك الصفحة.
أنا معجب بهذا النهج، وأود الحصول على ملاحظات.
سؤال واحد: هل يجب علي بدلاً من ذلك مراقبة التغييرات في عنوان URL؟ هل هذه فكرة أفضل لتسجيل مستمع لـ popstate؟
لاستخدامه، قم بشيء مثل هذا في السمة / الرأس الخاص بك:
<script src="https://files.extrastatic.dev/community/on-discourse.js"></script>
<script src="https://files.extrastatic.dev/community/index.js"></script>
<link rel="stylesheet" type="text/css" href="https://files.extrastatic.dev/community/index.css">
بعد ذلك، داخل مكتبتك يمكنك استدعاء on-discourse على هذا النحو:
function log(...msg) {
console.log('svelte', ...msg);
}
// هذا هو كود تثبيت Svelte
function setup() {
try {
const ID = 'my-special-target-id';
log('Inside setup()');
const el = document.getElementById(ID);
if (el) {
log('Removed existing element', ID);
el.remove();
}
const target = document.createElement("div");
target.setAttribute("id", ID);
log('Created target');
document.body.appendChild(target);
log('Appended child to body');
const app = new App({
// eslint-disable-next-line no-undef
target
});
log('Created app and installed');
} catch(err) {
console.error('Unable to complete setup()', err.toString() );
}
}
(function start() {
log('Starting custom Svelte app');
// إعادة التثبيت عند حدوث تغييرات
window.onDiscourse && window.onDiscourse( setup );
// تحميل التطبيق عند تحميل الصفحة الأولى
window.addEventListener('load', () => {
setup();
});
log('Finished custom Svelte app);
})();
بشكل أساسي، ما عليك سوى استدعاء window.onDiscourse(callback) مع رد الاتصال الخاص بك (ويمكنك تشغيله عدة مرات لتثبيت ردود اتصال متعددة)، وعندما يحدث طفرة، يتم تشغيل رد الاتصال هذا لتهيئة تطبيقك.
هنا الكود الكامل لـ on-discourse.js. (تعديل: قمت بتحديث هذا لاستخدام #topic، والذي يبدو أنه شيء جيد لمراقبته، لأن السمات تتغير عند تحميل الصفحة، ثم يحتاج الطفرة فقط إلى مراقبة تغييرات السمات، بدلاً من البحث في شجرة DOM بأكملها عن #main-outlet)
let mutationObservers = [];
function log(...msg) {
console.log("on-discourse", ...msg);
}
function observeMainOutlet() {
log('Observing main outlet');
// حدد العقدة التي سيتم مراقبتها للطفرات
const targetNode = document.getElementById("topic");
if (targetNode) {
// خيارات للمراقب (الطفرات التي سيتم مراقبتها)
const config = { attributes: true };
// إنشاء مثيل مراقب لإعادة التعيين عند تغيير childList
const observer = new MutationObserver(function(mutations) {
let reset = false;
mutations.forEach(function(mutation) {
if (mutation.type === 'attributes') {
log('Found main-outlet mutation, running callbacks');
mutationObservers.forEach( (s,i) => {
try {
log(`Running div callback ${i+1}`);
s();
log(`Finished div callback ${i+1}`);
} catch( err ) {
log(`Div callback error (${i+1})`, err );
}
});
}
});
});
// ابدأ مراقبة العقدة المستهدفة للطفرات المكونة
observer.observe(targetNode, config);
// لاحقًا، يمكنك إيقاف المراقبة
// observer.disconnect();
log('Done with outlet observer');
} else {
console.error('on-discourse FATAL ERROR: Unable to find main-outlet');
}
}
window.addDiscourseDivMutationObserver = (cb) => {
log('Adding on-discourse div mutation callback');
mutationObservers.push(cb);
log('Added on-discourse div mutation callback');
}
window.addEventListener("load", () => {
log('Setting up topic observer');
if (mutationObservers.length > 0) {
observeMainOutlet();
}
log('Created topic observer');
});
log('Completed setup of on-discourse.js');