วันนี้ เมื่อพัฒนาเพจ H5 บนมือถือ ฉันพบปัญหาที่อินเทอร์เฟซไม่สามารถกลับสู่ตำแหน่งเดิมได้เมื่อหดแป้นพิมพ์บน IOS ปัญหาและอาการต่างๆ มีรายละเอียดดังนี้
โครงสร้างหน้าหน้าที่เป็นปัญหาคือโครงสร้างแบบฟอร์ม นั่นคือคล้ายกับโครงสร้างที่มีแบบฟอร์มป้อนข้อมูลสี่รูปแบบภายใต้ div เพื่อให้ผู้ใช้สามารถกรอกข้อมูลการส่งไปรษณีย์ได้ คล้ายกัน:
<div> <input type=text placeholder=กรุณากรอกจังหวัด เมือง และเทศมณฑล/> <input type=text placeholder=กรุณากรอกที่อยู่/> <input type=text placeholder=กรุณากรอกชื่อ/> < input type=text placeholder=กรุณากรอกที่อยู่/ หมายเลขติดต่อ/></div>
ภาพหน้าจอมีดังนี้:
หน้าจะเลื่อนขึ้นโดยอัตโนมัติเมื่อเปิดแป้นพิมพ์ขึ้นมาเมื่อผู้ใช้กรอกหมายเลขติดต่อบนโทรศัพท์มือถือ แป้นพิมพ์ iPhone จะปรากฏขึ้น ในเวลานี้ เพื่อให้ผู้ใช้เห็นกล่องป้อนข้อมูลโทรศัพท์ หน้าทั้งหมดจะถูกย้ายขึ้นไปบน iPhone (ไม่เช่นนั้นแป้นพิมพ์ จะบังช่องป้อนข้อมูลโทรศัพท์) ในขณะนี้ ด้านบนของหน้าเป็นส่วนหนึ่งของระยะห่างจากวิวพอร์ตของเรา (เราเห็นแถวของกล่องอินพุตหายไปจากอินเทอร์เฟซ)
ไม่สามารถคืนค่าเพจไปยังตำแหน่งเดิมได้เมื่อปิดแป้นพิมพ์อย่างไรก็ตาม เมื่อผู้ใช้ป้อนข้อมูลเสร็จสิ้นและปิดแป้นพิมพ์ แม้ว่าแป้นพิมพ์จะถูกเก็บออกไป ตำแหน่งหน้าจะไม่ถูกเรียกคืน
การวิเคราะห์ปัญหาที่จริงแล้ว กรณีนี้มีสาเหตุมาจากการที่ iOS ไม่สามารถป้องกันไม่ให้ส่วนหนึ่งของหน้าเลื่อนออกจากวิวพอร์ตล้มลงเมื่อหดแป้นพิมพ์ ในขณะนี้ผู้ใช้สามารถลากหน้ากลับด้วยนิ้วของเขาได้
แต่ประสบการณ์กลับไม่ดีเลย
เพื่อแก้ปัญหานี้ เราสามารถเรียก window.scrollTo(0, 0) เมื่อเคอร์เซอร์ผู้ใช้ออกจากกล่องอินพุตเพื่อเลื่อนหน้าเพื่อให้สอดคล้องกับด้านบนของวิวพอร์ต ดังนั้นจึงบรรลุผลหน้าแรกของหน้า
ตอนนี้ปัญหาคือการเพิ่มเหตุการณ์เบลอลงในกล่องอินพุตทั้งสี่กล่องในแบบฟอร์ม จากนั้นเรียก window.scrollTo ในตัวจัดการ อย่างไรก็ตาม ไม่ว่าจะเพิ่มผ่าน @blur ของ Vue หรือผ่านการดำเนินการ DOM จะต้องเพิ่ม Listener เหตุการณ์ 4 รายการ ซึ่งไม่สวยงามมากนัก โดยปกติแล้ว เราคิดถึงการใช้พร็อกซีของเหตุการณ์
นั่นคือเราวางตัวฟังเหตุการณ์ไว้ที่องค์ประกอบด้านบน จากนั้นกำหนดฟังก์ชัน inputBlur เพื่อรอการทริกเกอร์
<div @blur=inputBlur> <input type=text placeholder=กรุณากรอกจังหวัด เมือง และเคาน์ตี/> <input type=text placeholder=กรุณากรอกที่อยู่/> <input type=text placeholder=กรุณากรอก name/> <input type=text placeholder=กรุณากรอกหมายเลขติดต่อของคุณ/></div>
ด้วยเหตุนี้ เราพบว่า Listener กิจกรรมของเราล้มเหลวในการเริ่มทำงาน เหตุผลก็คือเหตุการณ์ blur ของกล่องอินพุตไม่สามารถทำให้เกิดฟองได้
หลังจากการสอบถาม พบว่าเหตุการณ์ DOM ทั้งสองเหตุการณ์ focus และ blur ไม่สามารถทำให้เกิดฟองในข้อกำหนดได้ ในทำนองเดียวกัน มีเหตุการณ์อื่นอีกสองเหตุการณ์ focusin และ focusout ที่สามารถทำให้เกิดฟองได้
บทความบางบทความบนอินเทอร์เน็ตระบุว่า focusin และ focusout เป็นเหตุการณ์ DOM ที่เบราว์เซอร์ IE รองรับเท่านั้น ที่จริงแล้ว เมื่อเราดูเอกสาร MDN เราพบว่าทั้งสองเหตุการณ์นี้ได้กลายเป็นมาตรฐานในข้อกำหนด DOM 3 และได้รับการสนับสนุนจากเบราว์เซอร์จำนวนมาก
ดังนั้น เพื่อแก้ไขปัญหาอย่างเด็ดขาดผ่านเหตุการณ์ทั้งสองนี้ เราจึงเปลี่ยน focusout
<div @focusout=inputBlur> <input type=text placeholder=กรุณากรอกจังหวัด เมือง และเคาน์ตี/> <input type=text placeholder=กรุณากรอกที่อยู่/> <input type=text placeholder=กรุณากรอก name/> <input type=text placeholder=กรุณากรอกหมายเลขติดต่อของคุณ/></div>
จากนั้นใช้ตัวจัดการเหตุการณ์ของเรา:
inputBlur(e) { // ก่อนอื่น ให้พิจารณาว่าองค์ประกอบเป้าหมายที่ทำให้เกิดเหตุการณ์นั้นเป็นกล่องอินพุตหรือไม่ เราเน้นเฉพาะพฤติกรรมของกล่องอินพุตเท่านั้น ถ้า (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'อินพุต') { window.scrollTo(0,0);ขณะนี้ปัญหาของเราได้รับการแก้ไขแล้ว เมื่อป้อนเนื้อหาจากช่องป้อนข้อมูลแล้วคลิกเสร็จสิ้นบนแป้นพิมพ์เพื่อปิดแป้นพิมพ์ ผลที่ได้จะเป็นไปตามความคาดหวังของเรา
อย่างไรก็ตาม หลังจากการทดสอบบนโทรศัพท์มือถือ เราพบว่าเมื่อเราเปลี่ยนจาก 电话输入框เป็น 姓名输入框โดยตรง หน้าเว็บจะกระวนกระวายใจ เรามาวิเคราะห์กันต่อ
ในความเป็นจริง สาเหตุที่กล่องอินพุตทั้งสองกระวนกระวายใจเมื่อเปลี่ยนก็ง่ายมากเช่นกัน เนื่องจากเมื่อเราสลับระหว่างกล่องอินพุตสองช่องด้านบน เพจจะทริกเกอร์เหตุการณ์ blur ของ 电话输入框ก่อน จากนั้นจึงทริกเกอร์เหตุการณ์ focus ของ 姓名输入框ในกรณีนี้ เมื่อเกิดภาพเบลอ window.scrollTo(0,0) ของเราจะถูกทริกเกอร์ ทำให้เพจเลื่อนลง จากนั้น 姓名输入框จะถูกโฟกัส ดังนั้นแป้นพิมพ์จะยังคงแสดงป๊อปอัปต่อไป---สิ่งนี้ จะทำให้เพจเลื่อนขึ้นอีกครั้ง
ที่จริงแล้ว เมื่อสลับระหว่างกล่องอินพุตสองกล่อง เราไม่จำเป็นต้องทริกเกอร์พฤติกรรม window.scrollTo เมื่อกล่องอินพุตแรกเบลอ ดังนั้นเรามาแก้ไขโค้ดของเราเพื่อที่ว่าเมื่อการดำเนินการสลับกล่องอินพุตเกิดขึ้น พฤติกรรมของกล่องอินพุตแรกสามารถถูกตัดออกได้ ที่นี่เราใช้ setTimeout เพื่อแก้ไข:
<div @focusout=inputBlur @focusin=inputFocus> <input type=text placeholder=กรุณากรอกจังหวัด เมือง และเทศมณฑล/> <input type=text placeholder=กรุณากรอกที่อยู่/> <input type=text placeholder= กรุณากรอกชื่อ/> < input type=text placeholder=กรุณากรอกหมายเลขติดต่อของคุณ/></div>
inputBlur(e) { // ก่อนอื่น ให้พิจารณาว่าองค์ประกอบเป้าหมายที่ทำให้เกิดเหตุการณ์นั้นเป็นกล่องอินพุตหรือไม่ เราเน้นเฉพาะพฤติกรรมของกล่องอินพุตเท่านั้น if (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'input') { // กล่องอินพุตสูญเสียโฟกัสและต้องผลักแป้นพิมพ์ IOS ออกจาก เลื่อนส่วนของหน้าเพื่อเรียกคืน เลื่อนหน้าไปที่ด้านบนของหน้าต่างและจัดตำแหน่ง console.log('set timer') this.timer = setTimeout(() => { console.log('timer trigger') window.scrollTo(0,0); }, 0) } }, inputFocus(e) { // หากโฟกัส ให้ลบตัวจับเวลาของกล่องอินพุตก่อนหน้าหาก (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'อินพุต') { clearTimeout(this.timer);ข้างต้นคือเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาของทุกคน ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network