สำหรับ this.$refs นั้นก็เป็นอีก 1 ฟีเจอร์สำหรับเรียกใช้ DOM เมื่อวันที่ 12/07/60 ผมได้อ่านบทความของพี่คนนึงเขียนเรื่องนี้ไว้ครับ
**[Vue.js] ใช้ ref เรียก DOM แทน jQuery แบบเดิม
วันนี้เลยขอเขียนเพิ่มเติม this.$refs ในกรณีใช้ plugin หรือ lib ต่างๆด้วยเลยก่อนจะเริ่มก็ขอปูพื้นกันก่อนถ้าใครเข้าใจตรงนี้ หรือ อ่านบทความด้านบนแล้วข้ามไปได้เลยฮ่ะ ><
ในการ access DOM ของ HTML นั้นใน javascript เราทำแบบนี้
<input type="text" name="first_name" class="input_name" id="input_name">
// js
document.getElementsByClassName('input_name')[0].focus(); // เรียกผ่าน class
document.getElementById('input_name').focus(); // เรียกผ่าน id
แต่สำหรับใน vuejs แล้วมีสิ่งนึงที่มาแทนที่ class, id เดิมนั่นคือ ref=”Your Element Name” มีวิธีการใช้งานตามนี้ครับ
<input type="text" class="input-name" ref="input_name">
// js
this.$refs.input_name.focus() // ในกรณีใช้ CLI ช่วยสร้าง project
vm.$refs.input_name.focus()
ง่ายๆตาม style Vue.js แต่มันไม่ได้มีประโยชน์แค่นั้นเมื่อ Vue.js เค้าบอกว่ามันเร็วกว่าการ access ของ javascript ธรรมดานะในเมื่อเราเป็นสาวกของ Vue.js ก็ตามน้ำดีก็ดี(^^) แต่สิ่งหนึ่งที่จะมาแก้ไขปัญหาที่เกิดขึ้นเมื่อเราใช้ lib ต่างๆแล้วจะ access DOM ตัว Vue.js เนี่ยก็มีปัญหา lib ไม่ติด Render หน้าใหม่แล้วแตกวันนี้เลยขอเสนอฟีเจอร์(เสียงสูง…) อีก 1 ตัว
this.$nextTick( [callback] )
มันมาแก้ปัญหาตอนที่ DOM มันกำลัง update, render ใหม่, v-if ไว้, หรือ เกิดขึ้นเมื่อกดปุ่มบางอย่าง ทำให้เราไม่สามารถ access มันได้หรือตัว javascript, Jquery ไม่สามารถหา class หรือ id นี้ได้ก็เพราะมันยัง update DOM ไม่เสร็จฟังก์ชั่นนี้ก็จะทำหน้าที่เมื่อ DOM ถูก update แล้วจะเรียกให้ callback ทำงานในฟังก์ชั่นเอาไปใส่ใน Lifecycle Hooks หรือ Methods แบบนี้ครับ
mounted() {
this.$nextTick(() => { // ES6 arrow function
this.$refs.input_name.focus()
})
}
หลายคนสงสัยว่าไอ้เจ้า Methods mounted() เค้าก็บอกอยู่ว่ามันคือการที่ DOM สร้างเสร็จแล้วนะแล้วทำไมต้องใช้ nextTick ก็เพราะตัว mounted() ไม่ได้การันตีว่ามันเสร็จแล้วจริงๆครับมันเสร็จบางส่วนที่พร้อมทำงานได้แต่ไม่ทั้งหมด…ใครที่ใช้ mounted() แล้วมันทำงานปกติก็โชคดีไปครับแต่ถ้าเมื่อไหร่ที่มันยังไม่เสร็จละก็อาจจะเกิด error ทั้งแผงเลยผมเคยเจอมาแล้วกับ Select2 ขอยกตัวอย่างดังนี้ครับ
// html
<select ref="lists">
<option value="AL">Alabama</option>
<option value="WY">Wyoming</option>
</select>
// js
mounted() {
this.$refs.lists.select2()
$(this.$refs.lists).select2() // หรือแบบ jquery
}
แบบนี้ใช้งานได้ปกติเลยครับแต่เมื่อไหร่ที่เรา update ตัว option ใน select หรือ get api ไปใส่ตัว Select2 แล้วมันยัง update ไม่เสร็จละก็มีโอกาศ error แน่นอน (เจอมากับตัว T T)ทางที่ดีเราควรใช้ nextTick เพื่อป้องกันปัญหาเหล่านี้ครับ
// html
<select ref="lists">
<option value="AL">Alabama</option>
<option value="WY">Wyoming</option>
</select>
// js
mounted() {
this.$nextTick(() => { // ES6 arrow function
this.$refs.lists.select2()
$(this.$refs.lists).select2() // หรือแบบ jquery
})
}
ให้ดีที่สุดคือเราใส่ไอ้เจ้าตัว nextTick ทุกครั้งที่ html เรามีการอัพเดท หรือ element นั้นๆต้องมีการ v-if ซ่อน แสดงผล บ่อยๆควรใช้ nextTick เพื่อยืนยันอีกครั้งว่ามันโหลดเสร็จแล้วจริงๆนะ..