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

Frontend Interview: SPA रूट बदलने के बाद आप फ़ोकस को कैसे मैनेज करते हैं?

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

प्रश्न

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

समस्या और उपयोग के मामले

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

इस नीति में पाँच अलग-अलग ट्रांज़िशन शामिल होने चाहिए: प्रारंभिक लोड, उपयोगकर्ता द्वारा शुरू किया गया रूट परिवर्तन, इन-प्लेस फ़िल्टर या सॉर्ट, बदला गया या रद्द किया गया नेविगेशन, और ब्राउज़र बैक/फ़ॉरवर्ड। इसे संवाद (dialogs) जैसे घटक-स्वामित्व वाले व्यवहार के साथ भी सह-अस्तित्व में होना चाहिए। लक्ष्य प्रेडिक्टेबल संदर्भ प्रदान करना है, न कि प्रत्येक URL म्यूटेशन के बाद फ़ोकस को स्थानांतरित करना।

साक्षात्कारकर्ता क्या मूल्यांकन कर रहा है

साक्षात्कारकर्ता एक सिमेंटिक निर्णय मॉडल की तलाश कर रहा है। "हर रूट परिवर्तन पर हेडिंग पर फ़ोकस करें" सुलभ लगता है लेकिन फ़िल्टर, हैश परिवर्तन, प्रारंभिक हाइड्रेशन और हिस्ट्री रिस्टोरेशन को तोड़ देता है। एक मजबूत उत्तर पहले यह तय करता है कि क्या उपयोगकर्ता का कार्य बदल गया है।

वे ब्राउज़र ज्ञान की भी अपेक्षा करते हैं: एक हेडिंग क्रमिक Tab क्रम में शामिल हुए बिना tabIndex={-1} के साथ प्रोग्रामेटिक फ़ोकस प्राप्त कर सकती है; focus() सामान्य रूप से तत्व को स्क्रॉल करता है; preventScroll फ़ोकस रिस्टोरेशन को स्क्रॉल रिस्टोरेशन से अलग करता है; और धनात्मक tabindex मान नाजुक फ़ोकस क्रम बनाते हैं।

अंत में, उत्तर को समवर्तीता (concurrency) को संभालना चाहिए। यदि रूट B, रूट C के बाद हल होता है, तो B को शीर्षक अपडेट नहीं करना चाहिए या फ़ोकस नहीं छीनना चाहिए। स्वचालित जांच सक्रिय तत्व, शीर्षक और क्रम को साबित कर सकती हैं, लेकिन यह साबित नहीं कर सकती हैं कि प्रत्येक ब्राउज़र और सहायक-तकनीक जोड़ी क्या घोषणा करती है।

उत्तर देने से पहले स्पष्ट करने वाले प्रश्न

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

30-सेकंड उत्तर फ़्रेमवर्क

"मैं फ़ोकस स्थानांतरित करने से पहले नेविगेशन को वर्गीकृत करता हूँ। प्रारंभिक लोड कुछ नहीं करता है। एक कमिट किया गया उपयोगकर्ता-आरंभिक कार्य परिवर्तन दस्तावेज़ शीर्षक को अपडेट करता है और नए वर्णनात्मक H1 पर फ़ोकस करता है, जिसे tabIndex=-1 के साथ प्रोग्रामेटिक रूप से फ़ोकस करने योग्य बनाया गया है। समान-कार्य फ़िल्टर नियंत्रण को सुरक्षित रखते हैं और एक स्थायी विनम्र (polite) स्थिति क्षेत्र के माध्यम से पूर्ण परिणामों की रिपोर्ट करते हैं। प्रत्येक नेविगेशन में एक टोकन होता है, इसलिए केवल नवीनतम कमिट किया गया रूट ही शीर्षक और फ़ोकस लागू कर सकता है। बैक/फ़ॉरवर्ड पर मैं उस हिस्ट्री प्रविष्टि के लिए सहेजे गए एक मान्य सिमेंटिक लक्ष्य को पुनर्स्थापित करता हूँ, अन्यथा मैं स्क्रॉल रिस्टोरेशन के साथ फ़ोकस का समन्वय करते हुए H1 का उपयोग करता हूँ। मैं प्रारंभिक लोड, तेज़ नेविगेशन, त्रुटियों, फ़िल्टर, हिस्ट्री, कीबोर्ड क्रम, दृश्यमान फ़ोकस और वास्तविक स्क्रीन पाठकों का परीक्षण करता हूँ।"

चरण-दर-चरण गहन विश्लेषण

एक ट्रांज़िशन तालिका के साथ शुरुआत करें:

ट्रांज़िशनफ़ोकस क्रियाघोषणा
प्रारंभिक लोड या हाइड्रेशनफ़ोकस को बाध्य न करेंमूल दस्तावेज़/शीर्षक व्यवहार
नए कार्य के लिए PUSHकमिट किए गए रूट H1 पर फ़ोकस करेंअद्यतन शीर्षक प्लस फ़ोकस की गई हेडिंग
समान-कार्य फ़िल्टर, सॉर्ट, या पेजिनेशनआरंभ करने वाले नियंत्रण को सुरक्षित रखेंयदि उपयोगी हो तो विनम्र परिणाम/स्थिति अपडेट
बैक/फ़ॉरवर्ड से POPमान्य सहेजे गए लक्ष्य को पुनर्स्थापित करें; अन्यथा H1पुनर्स्थापित संदर्भ या फ़ोकस की गई हेडिंग
रीडायरेक्ट या त्रुटि रूटउस रूट के कमिट किए गए H1 पर फ़ोकस करेंइसका अंतिम शीर्षक और हेडिंग
संवाद खोलना/बंद करनासंवाद अनुबंध पर छोड़ेंसंवाद लेबल और वापसी लक्ष्य

रूट अनुबंध एक अंतिम शीर्षक, एक वर्णनात्मक H1 संदर्भ (ref), और एक सिमेंटिक रूट कुंजी की आपूर्ति करता है। H1 को tabIndex={-1} दें। यह सामान्य Tab क्रम से बाहर रहता है, लेकिन कोड इसे फ़ोकस कर सकता है। एक दृश्यमान फ़ोकस संकेतक बनाए रखें। एक स्किप लिंक पहला कीबोर्ड-फ़ोकस करने योग्य नियंत्रण बना रहता है और main को लक्षित करता है; यह बार-बार नेविगेशन बाईपास को हल करता है और रूट फ़ोकस प्रबंधित होने पर भी इसका मूल्य होता है।

फ़ोकस कमिट सीमा से संबंधित है। प्रत्येक प्रयास किए गए नेविगेशन के लिए एक मोनोटोनिक रूप से बढ़ता हुआ टोकन असाइन करें। जब किसी रूट के लिए डेटा और UI समाप्त हो जाएं, तो केवल तभी प्रभाव लागू करें जब उसका टोकन अभी भी वर्तमान हो और H1 माउंट हो। एक निश्चित टाइमआउट का उपयोग न करें: नेटवर्क की गति और रेंडरिंग कार्य इसे अविश्वसनीय बनाते हैं।

text
beginNavigation(kind):
  token = nextToken()
  rememberCurrentFocus(historyEntryKey)

commitRoute(token, kind, title, heading):
  if token != currentToken or heading is not connected:
    return
  document.title = title
  if kind is PUSH or semantic-task REPLACE:
    heading.focus()
  else if kind is POP:
    focus(validSavedTarget(historyEntryKey) or heading)

उत्पन्न CSS पथ के बजाय एक स्थिर रूट-स्थानीय फ़ोकस ID सहेजें। POP पर, इसे केवल तभी पुनर्स्थापित करें यदि तत्व अभी भी मौजूद है, दृश्यमान है, सक्षम है, और पुनर्स्थापित स्थिति में सार्थक है। अन्यथा H1 का उपयोग करें। यदि राउटर स्क्रॉल को स्वतंत्र रूप से पुनर्स्थापित करता है, तो focus({ preventScroll: true }) का उपयोग करें और फिर एक बार स्क्रॉल पुनर्स्थापित करें; एक सामान्य PUSH के लिए, फ़ोकस को H1 प्रकट करने की अनुमति देना आमतौर पर अधिक स्पष्ट होता है।

दोहरी आवाज़ (duplicate speech) से बचें। शीर्षक अपडेट करने के बाद नए H1 पर फ़ोकस करना अक्सर पर्याप्त संदर्भ प्रदान करता है, हालांकि सटीक आवाज़ सहायक तकनीक के अनुसार भिन्न होती है। डिफ़ॉल्ट रूप से लाइव क्षेत्र में समान शीर्षक की घोषणा न करें। एक फ़िल्टर के लिए जो फ़ोकस रखता है, एक स्थायी role="status" या aria-live="polite" क्षेत्र पूर्ण परिणाम संख्या की घोषणा कर सकता है। वास्तविक रूप से जरूरी जानकारी के लिए मुखर (assertive) घोषणाएं आरक्षित रखें क्योंकि वे वर्तमान भाषण को बाधित कर सकती हैं।

परीक्षण ओरेकल नीति का पालन करता है। प्रारंभिक हाइड्रेशन पर, एप्लिकेशन को फ़ोकस नहीं चुराना चाहिए। PUSH पर, अंतिम कमिट के बाद, document.activeElement नया H1 है, शीर्षक अंतिम है, और अगला Tab पहले तार्किक इंटरैक्टिव तत्व तक पहुंचता है। फ़िल्टर परिवर्तन पर, ट्रिगर फ़ोकस बनाए रखता है और स्थिति पाठ एक बार अपडेट होता है। A→B→C रेस में जहाँ B अंतिम रूप से हल होता है, C शीर्षक और फ़ोकस रखता है। त्रुटि और रीडायरेक्ट रूट अपनी स्वयं की हेडिंग पर फ़ोकस करते हैं। POP एक मान्य सहेजे गए लक्ष्य को पुनर्स्थापित करता है या नियतात्मक रूप से फ़ॉलबैक करता है।

उन सभी मामलों के लिए स्वचालित DOM जांच चलाएं, जिसमें लक्ष्य अनमाउंट और कम-गति/ज़ूम लेआउट शामिल हैं। फिर समर्थित ब्राउज़र के साथ कीबोर्ड और VoiceOver/Safari और NVDA या JAWS जैसे समर्थित संयोजनों के साथ मैन्युअल रूप से जाँच करें। दृश्यमान फ़ोकस, तार्किक क्रम, कोई अप्रत्याशित स्क्रॉल नहीं, और समझने योग्य घोषणाओं को सत्यापित करें। ब्राउज़र और सहायक-तकनीक संस्करणों को रिकॉर्ड करें क्योंकि भाषण आउटपुट एक एकीकरण परिणाम है, न कि DOM गारंटी।

उच्च-गुणवत्ता नमूना उत्तर

"मैं फ़ोकस व्यवहार को राउटर के सिमेंटिक अनुबंध का हिस्सा बनाऊंगा। प्रत्येक रूट एक अंतिम दस्तावेज़ शीर्षक और एक वर्णनात्मक H1 संदर्भ प्रदर्शित करता है। मैं ट्रांज़िशन को वर्गीकृत करता हूँ: प्रारंभिक हाइड्रेशन फ़ोकस को स्थानांतरित नहीं करता है; उपयोगकर्ता द्वारा शुरू किया गया PUSH जो कार्य को बदलता है, कमिट के बाद अंतिम H1 पर फ़ोकस करता है; एक फ़िल्टर या सॉर्ट आरंभ करने वाले नियंत्रण को सुरक्षित रखता है; और POP H1 पर वापस जाने से पहले एक स्थिर सहेजे गए लक्ष्य को पुनर्स्थापित करने का प्रयास करता है।

H1 में tabIndex=-1 है, इसलिए यह अतिरिक्त Tab स्टॉप जोड़े बिना प्रोग्रामेटिक रूप से फ़ोकस करने योग्य है। मैं एक दृश्यमान फ़ोकस शैली को सुरक्षित रखता हूँ और main को लक्षित करने वाला एक स्किप लिंक रखता हूँ। जीतने वाले रूट के कमिट होने के बाद ही शीर्षक और फ़ोकस एक साथ बदलते हैं। प्रत्येक नेविगेशन को एक टोकन प्राप्त होता है, और पुराने एसिंक समापन को नजरअंदाज कर दिया जाता है, जो रद्द किए गए रूट को फ़ोकस चुराने से रोकता है।

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

मैं सक्रिय तत्व, शीर्षक, Tab क्रम, फ़िल्टर प्रतिधारण, तेज़ A→B→C नेविगेशन, रीडायरेक्ट, त्रुटियों और POP फ़ॉलबैक के लिए दावों (assertions) को स्वचालित करूंगा। फिर मैं समर्थित कीबोर्ड और स्क्रीन-रीडर मैट्रिक्स के साथ वास्तविक भाषण, दृश्यमान फ़ोकस और स्क्रॉलिंग का परीक्षण करूंगा। यह नियतात्मक DOM व्यवहार को सहायक-तकनीक व्यवहार से अलग करता है जिसे हमें देखना चाहिए।"

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

  • प्रत्येक URL परिवर्तन पर फ़ोकस करना → फ़िल्टर और हैश परिवर्तन कार्य को बाधित करते हैं → पहले सिमेंटिक ट्रांज़िशन को वर्गीकृत करें।
  • लिंक क्लिक होने पर फ़ोकस करना → गंतव्य मौजूद नहीं हो सकता है या रद्द किया जा सकता है → केवल जीतने वाले कमिट किए गए रूट पर फ़ोकस करें।
  • टाइमआउट का उपयोग करना → धीमे और तेज़ रेंडर अलग-अलग रेस करते हैं → रूट लाइफ़साइकिल और नेविगेशन टोकन का उपयोग करें।
  • body पर फ़ोकस करना या धनात्मक tabindex जोड़ना → संदर्भ और क्रम अस्पष्ट हो जाते हैं → tabIndex=-1 के साथ एक वर्णनात्मक H1 का उपयोग करें।
  • POP पर हमेशा H1 पर कूदना → बैक उपयोगकर्ता का स्थान खो देता है → एक नियतात्मक फ़ॉलबैक के साथ एक मान्य हिस्ट्री लक्ष्य को पुनर्स्थापित करें।
  • शीर्षक की दो बार घोषणा करना → उपयोगकर्ता अनावश्यक भाषण सुनते हैं → पहले फ़ोकस किए गए हेडिंग संदर्भ को चुनें और इन-प्लेस अपडेट के लिए लाइव स्थिति का उपयोग करें।
  • स्वचालित एक्सेसिबिलिटी स्कैन को प्रमाण मानना → यह वास्तविक बोले गए आउटपुट को मान्य नहीं कर सकता है → मैन्युअल कीबोर्ड और सहायक-तकनीक परीक्षण जोड़ें।

अनुवर्ती प्रश्न और उत्तर

अनुवर्ती 1: हमेशा main लैंडमार्क पर फ़ोकस क्यों नहीं करते?

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

अनुवर्ती 2: क्या माउस नेविगेशन को भी फ़ोकस स्थानांतरित करना चाहिए?

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

अनुवर्ती 3: क्या होगा यदि तेज़ नेविगेशन में B, C के बाद समाप्त होता है?

B का टोकन अब वर्तमान नेविगेशन से मेल नहीं खाता है, इसलिए इसका कमिट प्रभाव शीर्षक, फ़ोकस या स्थिति को बदले बिना वापस आ जाता है। B के अनुरोध को निरस्त करने से काम बचता है, लेकिन टोकन जांच अभी भी आवश्यक है क्योंकि रद्दीकरण में देरी हो सकती है या यह असमर्थित हो सकता है।

अनुवर्ती 4: फ़ोकस और स्क्रॉल रिस्टोरेशन कैसे इंटरैक्ट करते हैं?

सामान्य focus() लक्ष्य को दृश्य में स्क्रॉल कर सकता है। POP पर, यदि राउटर एक सहेजी गई स्क्रॉल स्थिति को अलग से पुनर्स्थापित करता है, तो preventScroll का उपयोग करें, सहेजे गए तत्व को मान्य और फ़ोकस करें, फिर एक स्क्रॉल रिस्टोरेशन करें। एक स्वामी को परिभाषित करें ताकि फ़ोकस और राउटर कोड आपस में न टकराएं।

अनुवर्ती 5: एक लाइव क्षेत्र कब मुखर (assertive) होना चाहिए?

केवल तभी जब सुनने में देरी से कोई गंभीर समस्या उत्पन्न हो, जैसे कि कोई जरूरी सत्र या सुरक्षा संदेश। सामान्य परिणाम संख्या और पूर्णता अपडेट विनम्र होने चाहिए। रूट संदर्भ सामान्य रूप से अंतिम शीर्षक और फ़ोकस की गई हेडिंग से आता है, जिससे दूसरी घोषणा से बचा जा सकता है।

अनुवर्ती 6: क्या यह अपने आप में WCAG अनुपालन है?

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

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

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