प्रतिनिधि इंटरव्यू विषय

फ्रंटएंड इंटरव्यू: एक कस्टम साइडबार डिवाइस-नेटिव क्लोज़ रिक्वेस्ट्स पर कैसे प्रतिक्रिया देगा?

फ्रंटएंडकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक ड्रैगेबल मोबाइल साइडबार डिज़ाइन करें जो डेस्कटॉप पर Escape और Android पर बैक जेस्चर से बंद हो, साथ ही एक अनसेव्ड फ़ॉर्म की सुरक्षा करे। CloseWatcher, फ़ॉलबैक, और फ़ोकस व्यवहार को स्पष्ट करें।

प्रॉम्प्ट और संदर्भ

एक ड्रैगेबल मोबाइल साइडबार डिज़ाइन करें। डेस्कटॉप उपयोगकर्ताओं को उम्मीद होती है कि Escape इसे बंद कर देगा, Android उपयोगकर्ताओं को बैक जेस्चर या बटन की उम्मीद होती है, और एक अनसेव्ड फ़ॉर्म के लिए पुष्टिकरण (confirmation) की आवश्यकता होनी चाहिए। एक क्लोज़ फ़्लो के लिए CloseWatcher का उपयोग करें और cancel, close, requestClose(), destroy(), फ़ोकस, मल्टीपल वॉचर्स, असमर्थित ब्राउज़र्स, और हिस्ट्री सीमाओं को समझाएं।

MDN, CloseWatcher को कस्टम कंपोनेंट्स को डिवाइस-विशिष्ट क्लोज़ क्रियाओं पर प्रतिक्रिया देने योग्य बनाने वाले इंटरफ़ेस के रूप में वर्णित करता है। HTML Standard भी क्लोज़-वॉचर ग्रुपिंग और हिस्ट्री क्रियाओं के दुरुपयोग से जुड़ी सुरक्षा को परिभाषित करता है। यह लेख सार्वजनिक सामग्री का संश्लेषण करता है और किसी कंपनी-विशिष्ट इंटरव्यू प्रश्न होने का दावा नहीं करता है।

इंटरव्यूअर क्या जांच रहा है

इंटरव्यूअर यह देखना चाहता है कि क्या आप क्लोज़ रिक्वेस्ट और तत्काल क्लोज़र (closure) के बीच अंतर करते हैं, cancel चरण के दौरान क्लोज़र को रोकते हैं, और UI क्लीनअप के लिए एक ही close हैंडलर को ज़िम्मेदार रखते हैं। एक मजबूत उत्तर में यूज़र एक्टिवेशन, मल्टीपल-वॉचर ग्रुपिंग, AbortSignal लाइफ़टाइम, फ़ोकस रिटर्न, और एक स्पष्ट-बटन फ़ॉलबैक का उल्लेख होता है; एक कमजोर उत्तर केवल keydown को सुनता है।

पहले स्पष्ट करने योग्य प्रश्न

  • क्या साइडबार मोडल है, नॉन-मोडल है, या किसी हिस्ट्री नेविगेशन स्टेट से जुड़ा है?
  • क्या अनसेव्ड सामग्री को हर क्लोज़ रिक्वेस्ट को ब्लॉक करना चाहिए या केवल तभी जब विशेष फ़ील्ड्स डर्टी (dirty) हों?
  • क्या बैक जेस्चर को कंपोनेंट को बंद करना चाहिए या पिछली हिस्ट्री प्रविष्टि पर नेविगेट करना चाहिए?
  • क्या लक्षित ब्राउज़र CloseWatcher का समर्थन करते हैं, और क्या यह सुविधा एक स्पष्ट क्लोज़ बटन में डिग्रेड हो सकती है?

30-सेकंड का उत्तर

“मैं हर क्लोज़ एंट्री पॉइंट को एक क्लोज़ रिक्वेस्ट के रूप में सामान्यीकृत (normalize) करूँगा। जब साइडबार खुलता है, तो AbortSignal के साथ एक CloseWatcher बनाएं। cancel में, जांचें कि क्या फ़ॉर्म डर्टी है; जब यह हो तो रिक्वेस्ट को रोकें और पुष्टिकरण दिखाएं, अन्यथा इसकी अनुमति दें। close कंपोनेंट को छुपाता है, फ़ोकस को पुनर्स्थापित करता है, और संसाधनों को साफ़ करता है, और स्पष्ट क्लोज़ बटन उसी पथ का अनुसरण करता है। असमर्थित ब्राउज़र बटन और एक सीमित Escape फ़ॉलबैक बनाए रखते हैं; जब कोई बंद करने योग्य कंपोनेंट नहीं होता है तो ब्राउज़र या राउटर बैक नेविगेशन का स्वामित्व रखता है।”

चरण-दर-चरण समाधान

दोनों क्रियाओं को अलग करें। requestClose() एक डिवाइस क्लोज़ रिक्वेस्ट का अनुकरण करता है और cancel को फ़ायर करता है; यदि इसे रोका नहीं जाता है, तो close इसके बाद आता है। close() बिना cancel के तुरंत close को फ़ायर करता है, जबकि destroy() केवल वॉचर को निष्क्रिय करता है। सेव करने, अनमाउंट करने, या किसी रूट को छोड़ने के बाद, अर्थों को मिलाने के बजाय स्पष्ट रूप से एक क्लोज़ रिक्वेस्ट या फ़ोर्स्ड क्लीनअप चुनें।

js
function openDrawer() {
  const controller = new AbortController();
  const watcher = new CloseWatcher({ signal: controller.signal });

  watcher.addEventListener("cancel", (event) => {
    if (!formIsDirty()) return;
    event.preventDefault();
    showDiscardConfirmation(() => watcher.close());
  });

  watcher.addEventListener("close", () => {
    hideDrawer();
    restoreFocusToTrigger();
    controller.abort();
  });

  return { watcher, controller };
}

पुष्टिकरण डायलॉग को पुनरावर्ती (recursively) रूप से एक ऐसा वॉचर नहीं बनाना चाहिए जिसे बंद न किया जा सके। एक स्पष्ट डिस्कार्ड पुष्टिकरण के बाद, वर्तमान वॉचर के close() को कॉल करें; पुष्टिकरण रद्द करने पर साइडबार खुला रहता है। सेव करने के बाद, डर्टी स्टेट को साफ़ करें और requestClose() को कॉल करें ताकि वही क्लीनअप पथ चले।

फ़ोकस व्यवहार कंपोनेंट पर निर्भर करता है। एक मोडल साइडबार को फ़ोकस को एक समझने योग्य हेडिंग या पहले कंट्रोल पर ले जाना चाहिए और बंद होने पर इसे ट्रिगर पर वापस लौटाना चाहिए। एक नॉन-मोडल पैनल को फ़ोकस नहीं छीनना चाहिए, लेकिन फिर भी इसे एक पहुंच योग्य क्लोज़ बटन और दृश्यमान स्थिति की आवश्यकता होती है। एक क्लोज़ रिक्वेस्ट को केवल CSS टॉगल करने के बजाय एक्सेसिबल नाम, स्क्रिम, स्क्रॉल लॉकिंग, और कीबोर्ड क्रम को अपडेट करना चाहिए।

मल्टीपल वॉचर्स की एक विशेष सीमा होती है। यूज़र एक्टिवेशन के बिना, विनिर्देश वॉचर्स को समूहीकृत (grouped) करने की अनुमति देता है, इसलिए एक क्लोज़ रिक्वेस्ट उनमें से कई को बंद कर सकती है। प्रत्येक छोटे पैनल के लिए बिना शर्त वॉचर न बनाएं। वॉचर का स्वामित्व रखने वाले एक शीर्ष-स्तरीय क्लोज़ेबल कंपोनेंट को प्राथमिकता दें; चाइल्ड कंपोनेंट इवेंट्स के माध्यम से क्लोज़र का अनुरोध करते हैं, और अनमाउंटिंग destroy() को कॉल करता है या संबंधित सिग्नल को निरस्त (abort) करता है।

एक बैक जेस्चर केवल एक क्लिक नहीं है। प्लेटफ़ॉर्म इसे हिस्ट्री ट्रैवर्सल या क्लोज़ रिक्वेस्ट के रूप में मान सकता है, और ब्राउज़र का क्लोज़-वॉचर मैनेजर लक्ष्य का चयन करता है। एप्लिकेशन को केवल तभी पुष्टि करनी चाहिए जब वह इंटरसेप्ट कर सके और कंपोनेंट खुला हो; बिना किसी क्लोज़ेबल कंपोनेंट के, सामान्य हिस्ट्री बैक जारी रहना चाहिए। एक स्थानीय फ़ॉर्म की सुरक्षा के लिए popstate या बैक जेस्चर को विश्व स्तर पर ब्लॉक न करें।

क्षमता का पता लगाना (capability detection) कोर पथ की सुरक्षा करता है। एक बनाने से पहले window.CloseWatcher की जांच करें। असमर्थित होने पर, स्पष्ट क्लोज़ बटन रखें, यदि आवश्यक हो तो एक सीमित Escape लिसनर जोड़ें, और मौजूदा राउटर को बैक व्यवहार का स्वामित्व लेने दें। यह दावा न करें कि कस्टम लिसनर्स पूरी तरह से Android बैक सेमेंटिक्स को पुनरुत्पादित करते हैं। समर्थन, ब्लॉक किए गए अनुरोधों, पोस्ट-कन्फर्मेशन डिस्कार्ड्स, और फ़ोकस-पुनर्स्थापना विफलताओं को मापें।

एक मजबूत उत्तर का उदाहरण

मैं साइडबार के हर क्लोज़ एंट्री को एक क्लोज़ रिक्वेस्ट के रूप में सामान्यीकृत करूँगा। खोलने पर, AbortSignal के साथ एक CloseWatcher बनाएं। cancel केवल अनसेव्ड स्थिति की जांच करता है: डर्टी होने पर, preventDefault() को कॉल करें और पुष्टिकरण दिखाएं; क्लीन होने पर, अनुरोध की अनुमति दें। डिस्कार्ड पुष्टिकरण के बाद, close() को कॉल करें; सेव करने के बाद, डर्टी स्टेट साफ़ करें और requestClose() को कॉल करें। close एकमात्र UI क्लीनअप पॉइंट है: पैनल छुपाएं, ट्रिगर पर फ़ोकस पुनर्स्थापित करें, स्क्रॉल लॉकिंग हटाएं, और वॉचर को समाप्त करें।

मैं वॉचर की संख्या को सीमित करूँगा ताकि अनएक्टिवेटेड इंस्टेंसेस गलती से समूहीकृत न हों; अनमाउंटिंग या रूट परिवर्तन उन्हें नष्ट कर देते हैं। मोडल और नॉन-मोडल कंपोनेंट्स को अलग-अलग फ़ोकस और स्क्रिम नियम मिलते हैं, और जब कोई कंपोनेंट खुला नहीं होता है तो बैक जेस्चर ब्राउज़र हिस्ट्री तक पहुँचते हैं। CloseWatcher के बिना ब्राउज़र कोर नेविगेशन को अवरुद्ध किए बिना एक स्पष्ट बटन और सीमित कीबोर्ड फ़ॉलबैक बनाए रखते हैं। मेट्रिक्स क्लोज़, पुष्टिकरण, और एक्सेसिबिलिटी व्यवहार को मान्य करते हैं।

सामान्य गलतियाँ

  • लक्षण → हर एंट्री पॉइंट के लिए close() का उपयोग करना; यह क्यों विफल होता है → यह अनसेव्ड पुष्टिकरण चरण को छोड़ देता है; सुधार → यूज़र और प्लेटफ़ॉर्म का इरादा requestClose() का उपयोग करता है, जबकि फ़ोर्स्ड क्लीनअप close() का उपयोग करता है।
  • लक्षण → केवल Escape के लिए सुनना; यह क्यों विफल होता है → Android बैक और अन्य डिवाइस क्लोज़ क्रियाएं छूट जाती हैं; सुधार → CloseWatcher का उपयोग करें और एक स्पष्ट बटन रखें।
  • लक्षण → हर चाइल्ड पैनल के लिए एक वॉचर बनाना; यह क्यों विफल होता है → अनएक्टिवेटेड वॉचर्स समूहीकृत हो सकते हैं; सुधार → शीर्ष-स्तरीय क्लोज़ेबल कंपोनेंट को एक इंस्टेंस का स्वामी होने दें।
  • लक्षण → एक छिपे हुए नोड पर फ़ोकस छोड़ना; यह क्यों विफल होता है → कीबोर्ड और सहायक-तकनीक उपयोगकर्ता अपनी स्थिति खो देते हैं; सुधार → ट्रिगर को स्टोर करें और close में फ़ोकस पुनर्स्थापित करें।
  • लक्षण → बैक इवेंट्स को विश्व स्तर पर ब्लॉक करना; यह क्यों विफल होता है → जब कोई कंपोनेंट खुला नहीं होता है तो हिस्ट्री नेविगेशन टूट जाता है; सुधार → केवल तभी किसी खुले कंपोनेंट की क्लोज़ रिक्वेस्ट को ब्लॉक करें जब पुष्टिकरण आवश्यक हो।

फॉलो-अप प्रश्न और उत्तर

आपको requestClose() बनाम close() का उपयोग कब करना चाहिए?

यूज़र या प्लेटफ़ॉर्म के इरादे के लिए requestClose() का उपयोग करें क्योंकि यह cancel को क्लोज़र को रोकने का मौका देता है। स्पष्ट डिस्कार्ड पुष्टिकरण के बाद, अनमाउंट क्लीनअप के दौरान, या जब भी क्लोज़र तत्काल होना चाहिए, close() का उपयोग करें। दोनों को एक ही close क्लीनअप हैंडलर पर अभिसरण (converge) होना चाहिए।

क्या अनसेव्ड-पुष्टिकरण डायलॉग का अपना CloseWatcher होना चाहिए?

ज़रूरी नहीं। पैरेंट वॉचर के साथ पुनरावृत्ति या समूहीकृत क्लोज़र से बचने के लिए पुष्टिकरण डायलॉग को एक स्पष्ट क्लोज़ बटन और एक सुलभ फ़ोकस पथ दें। पैरेंट पुष्टिकरण के बाद close() को कॉल करता है; चाइल्ड को बंद करने से केवल पुष्टिकरण स्थिति बदलती है।

आप कई खुले पैनलों को कैसे संभालते हैं?

एक स्टैक या शीर्ष-स्तरीय स्वामित्व परिभाषित करें: एक अनुरोध केवल सबसे ऊपरी कंपोनेंट को बंद करता है जो वास्तव में बंद करने योग्य है, जबकि अन्य खुले रहते हैं। अपने व्यावसायिक स्टैक के रूप में अनएक्टिवेटेड वॉचर्स के अंतर्निहित समूहीकरण पर भरोसा न करें; एप्लिकेशन स्थिति में क्रम रिकॉर्ड करें और फ़ोकस लौटाएं।

जब CloseWatcher असमर्थित हो तो फ़ॉलबैक क्या है?

एक स्पष्ट क्लोज़ बटन और बुनियादी Escape हैंडलिंग रखें, उसी डर्टी-स्टेट पुष्टिकरण, फ़ोकस पुनर्स्थापना, और क्लीनअप फ़ंक्शन का पुन: उपयोग करें। बैक जेस्चर या हिस्ट्री को विश्व स्तर पर इंटरसेप्ट न करें। एन्हांसमेंट का विस्तार करने का निर्णय लेने से पहले डिग्रैडेड कोहोर्ट को मापें।

सार्वजनिक स्रोत

संबंधित प्रश्न