ทำ Custom Component เพื่อไปใช้ กับ HTML ธรรมดาๆ ด้วย Vue.js กัน

หลายๆครั้งเราก็อยากจะเปลี่ยน Application ของเราเป็น Vue.js แต่ด้วย stack ที่มีอยู่มาตั้งแต่นานนม จะให้ล้างทั้งหมดแล้วทำใหม่ก็คงไม่ต้องทำอะไรกินพอดี ทางที่ดีทางนึงคือการค่อยๆทยอยเปลี่ยน component บนหน้าของเราให้กลายเป็น Vue.js ไปทีละอันๆ และเมื่อทำจนใกล้ครบก็ค่อยเปลี่ยนทั้ง App แต่ปัญหามันจะเกิดตรงที่ อยู่ดีๆเราจะเอา component ของ Vue มาใช้เลยไม่ได้ เราต้องทำ ให้ component ที่เราสร้างมาสามารถใช้ บน stack ปกติได้ก่อน ซึ่งนั่นคือเราต้องทำให้ Vue component ของเรากลายเป็น CustomElement ตามมาตรฐาน HTML ก่อน ซึ่งน้องโบน (Napon Mekavuthikul) น้องในทีมที่ ThothZocial ไปเจอวิธีการทำมา ผมเลยเอามาลองเล่นดู ว่ามันใช้งานยังไง….. ก็ขอให้ Credit น้องโบนไว้ตรงนี้ครับ :)
Vue Custom Element
ก่อนจะทำให้มันใช้บน HTML ปกติได้ เราต้องแปลงให้ component ของเราไปอยู่ตามมาตรฐานของ CustomElementV1 ก่อน ซึ่งสำหรับ Vue เราไม่ต้องทำอะไรมากเพราะมีคนทำไว้ให้แล้ว โดยใช้ component ที่ชื่อว่า Vue Custom Element ซึ่งเรียกใช้เป็น plugin บน component ได้เลย แล้วก็ Build หลังจากนั้นเราก็จะได้ ไฟล์ JS ที่สามารถเอาไปใช้งานได้เลย
ใช้ Builder Tools ช่วยน่าจะง่ายขึ้น
เพื่อการใช้งานที่ง่ายขึ้นหน่อย ก็มีคน สร้าง builder tools เอาไว้ให้เรา แล้ว หรือใครบอกว่าไม่ชอบอยากเขียน Webpack เองก็ ลุยได้เลย แต่ถ้าใครอยากใช้ builder tools ที่ผมบอก ก็ไปโหลดมาได้ที่ vue-customelement-bundler วิธีการใช้งานก็ เอาไฟล์ไปวางใน /src แก้ชื่อ component ใน main.js แล้ว ก็ รัน คำสั่ง webpack ได้เลยตัวไฟล์ที่ build แล้วจะอยู่ใน folder ./dist
ป.ล. แต่เท่าที่ลองตัวนี้จะมี bug นิดหน่อยกับ uglify ซึ่งแก้ได้ด้วยการสร้างไฟล์ .bablerc ขึ้นมาก็จะไม่มี error เลย
วิธีการเอาไปใช้งาน
เราสามารถเรียก script เหมือน Javascript อื่นๆ แล้วก็ใช้ tag ที่เรากำหนดเอาไว้แบบตัวอย่างได้เลย และยังสามารถ set props ได้ตามปกติแบบนี้ด้วย
<script src="./myElement.js"></script>
<my-element show=”false”></my-element>ส่วนตัว props เองเราก็สามารถ เรียกดู props หรือ set props ด้วย Javascript method ปกติได้เลย
document.querySelector('my-element')[0].show
document.querySelector('my-element')[0].show = true การใช้งานในโหมด Shadow DOM
ถ้าเราลองไปไล่ดูใน Doc จะเห็นได้ว่า ถ้าจะใช้งาน เป็น ShadowDOM เราจะต้อง enable ก่อนด้วยการใส่ options shadow เข้าไปแบบนี้
Vue.customElement('my-element', MyElement, {shadow: true})แต่…… ไม่ใช่ enabled แล้วจะจบ เพราะถ้าใครลองทำดูจะเจอว่า CSS ที่เราสร้างเอาไว้ใน component ใช้ไม่ได้ แม้กระทั่ง JS ที่เคยเรียกดูค่าต่างๆใน component ได้ กลับทำงานไม่ได้ใน mode ซึ่งมันถูกแล้วครับ เพราะว่า Shadow DOM จะทำงานอยู่ใน scope ของตัวเอง และเราไม่สามารถแก้ไขหรือปรับอะไรของมันได้ตรงๆ สำหรับในกรณีของ CSS นั้นเราสามารถที่จะส่งค่าเข้าไปใน component ผ่าน options shadowCss ได้แบบนี้
Vue.customElement('my-element', MyElement, {shadow: true, shadowCss: 'a { background-color: blue; }'})แต่สำหรับ JS เราคงต้องสร้าง method ไว้ใน component แล้วจัดการผ่าน props เท่านั้นแต่ข้อดีของ ShadowDOM คือ เมื่อมีการเปลี่ยนแปลงค่าหรือ โคตรสร้างของ DOM ใน ShadowDOM ก็จะไม่มีการ reflow ใหม่ตลอดเวลา
ทำงานยังไงแล้วมันจะเร็วมั้ย

ตัว Plugin ได้อธิบายการทำงานไว้ว่า ตัว Plugin เองได้สร้าง Proxy ระหว่างตัว CustomElement กับตัว Vue Component เอาไว้แทนการแปลงตรงๆซึ่งการทำแบบนี้ทำให้ เราสามารถใช้ความสามารถแทบทุกอย่างจาก VueJs ได้ บน CustomElement
ตัวผมเองได้แค่ลองเอามาเทสเล่นๆดูเท่านั้นครับเพราะว่ากำลังหาอะไรแบบนี้มาทำกับ Application เก่าอยู่ ถ้าใครลองบน production แล้ว เจออะไรแปลกๆก็มา comment กันไว้ได้ครับ
