สำหรับ JavaScript Framework แล้วคงไม่มีใครไม่รู้จัก React, Vue หรือ Angular และแน่นอนว่า 3 ตัวถือเป็น Framework ระดับต้นๆ ที่นิยมใช้กันอย่างแพร่หลาย ในบทความนี้เราจะมาทำความรู้จักกับ Framework ที่ถือได้ว่าเรียบง่ายที่สุด (Modest JavaScript Framework) นั้นก็คือ StimulusJS ซึ่งสามารถนำไปใช้งานร่วมกับ HTML เดิมที่มีอยู่แล้ว แต่ทำการเชื่อมต่อระหว่าง DOM และ JavaScript ผ่าน data-* attributes เพียงเท่านั้น
Playing with Stimulus
ได้อ่านมาถึงตรงนี้ คงแปลกใจว่ามันเรียบง่ายขนาดนั้นแล้วความสามารถของ Framework จะทำอะไรได้บ้าง อย่ามัวเสียเวลากันเลยมาทดลองใช้งาน StimulusJS กันเลย
คอมโพเนนต์ตัวอย่าง
ถ้าคุณได้ทดลองเล่นกับคอมโพเนนต์ด้านบนเรียบร้อยแล้ว ก็ดูเหมือนว่ามันเป็นคอมโพเนนต์ธรรมดาๆ ที่แสดงข้อความตามข้อความที่ได้กรอกใส่ช่อง และลบข้อความทิ้งเท่านั้น แต่ถ้าเราลองเปรียบเทียบการเขียนคอมโพเนนต์ธรรมดาแบบนี้กับการใช้ Framework อื่นๆ ดูหละก็จะเห็นภาพได้ทันทีว่าถ้าพัฒนาด้วย Stimulus นั้นง่ายกว่ากันมาก
HTML
1
2
3
4
5
6
7
8
9
10
11
12
<div data-controller="hello">
<label>ใส่ชื่อของคุณในช่อง..</label>
<input data-target="hello.name" type="text" />
<button data-action="click->hello#greet">
กดที่ฉันดูสิ !!!
</button>
<button data-action="click->hello#clear">ลบข้อความ</button>
<span data-target="hello.output"></span>
</div>
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/controllers/hello_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ "name", "output" ]
clear() {
this.outputTarget.textContent = ""
}
day() {
const dayNames = ["อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัสบดี", "ศุกร์", "เสาร์"]
const monthNames = ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."]
const now = new Date()
return `${dayNames[now.getDay()]}ที่ ${now.getDate()} ${monthNames[now.getMonth() + 1]} ${now.getFullYear() + 543}`
}
greet() {
this.outputTarget.textContent =
`ยินดีต้อนรับ คุณ ${this.nameTarget.value} ในวัน${this.day()}`
}
}
Install Stimulus
วิธีการติดติั้ง Stimulus กับโปรแกรมนั้นรองรับหลากหลายรูปแบบไม่ว่าจะเป็นการใช้ npm หรือโหลดผ่าน <script> ในหน้าเว็บ ซึ่งสามารถดูรายละเดียดได้จาก ที่นี่
Magic Happened
- เริ่มต้นจาก HTML ถ้าย้อนกลับไปก่อนที่จะใส่ Stimulus เข้าไปในโค้ด จะพบว่า HTML ของเราเป็นเพียง HTML ธรรมดาที่ประกอบไปด้วย
div,label,input,buttonและspanเพียงเท่านั้น แม้กระทั่งจะกดปุ่มให้มีผลลัพท์เกิดขึ้นก็ยังทำไม่ได้
1
2
3
4
5
6
7
8
9
10
<div>
<label>ใส่ชื่อของคุณในช่อง..</label>
<input type="text" />
<button>กดที่ฉันดูสิ !!!</button>
<button>ลบข้อความ</button>
<span></span>
</div>
- สร้าง controller เพื่อจะใช้เชื่อมต่อและควบคุม behavior ที่จะเกิดขึ้น
1
2
3
4
// src/controllers/hello_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
}
- เชื่อมต่อ controller กับ DOM ผ่าน
data-controllerโดยการใส่ค่าเป็นhelloจะต้องตรงกับชื่อของ controller
1
2
3
<div data-controller="hello">
...
</div>
สามารถดูรายละเอียดเพิ่มเติมได้ที่ Controller
- กำหนด action เพื่อตอบสนองต่อเหตุการณ์ใน HTML ผ่าน
data-actionโดยการใส่ค่าเป็นclick->hello#greetซึ่งค่าที่ใส่นี้เรียกว่า action descriptor โดยแต่ละส่วนมีหน้าทีดังนี้- click ใช้ระบุเหตุการณ์ที่จะเกิดขึ้น ในกรณีของปุ่มนี้จะหมายถึงเหตุการณ์ที่ผู้ใช้นำเมาส์ไปคลิก
- hello ใช้ระบุชื่อของ controller ที่จะถูกใช้งานร่วมกัน
- greet ใช้ระบุชื่อฟังก์ชันที่ถูกเรียกเมื่อมีการกดปุ่ม
สำหรับค่าที่กำหนดให้ใน
data-actionจะเห็นว่าระหว่าง controller และ action จะถูกคั่นด้วยเครื่องหมาย#
1
2
3
<div data-controller="hello">
<button data-action="click->hello#greet">กดที่ฉันดูสิ !!!</button>
</div>
โดยปกติแล้ว element แต่ละตัวใน HTML จะมี default behavior อยู่แล้ว ยกตัวอย่างเช่น ถ้าเป็นปุ่มก็คือ click ถ้าเป็นฟอร์มก็คือก sumbit ถ้าเป็นช่องใส่ข้อมูลก็คือ change เป็นต้น ซึ่งทำให้เราสามารถละการเขียนโค้ดที่ยาวให้สั่นลงได้
1
2
3
<button data-action="hello#greet">กดที่ฉันดูสิ !!!</button>
...
<select data-action="box#size">Change Size</button>
สามารถดูรายละเอียดเพิ่มเติมได้ที่ Action
- สำหรับในส่วนสุดท้ายคือการอ้างอิง element ใน controller ซึ่งสามารถทำได้ผ่าน
data-targetโดยการใส่ค่าเป็นhello.nameและhello.output
1
2
3
4
5
<div data-controller="hello">
<input data-target="hello.name" type="text" />
...
<span data-target="hello.output"></span>
</div>
สำหรับค่าที่กำหนดให้ใน data-target จะเห็นว่าระหว่าง controller และ target จะถูกคั่นด้วยเครื่องหมาย .
ภายใน controller จะต้องกำหนด target ผ่าน Array โดยให้ชื่อตรงกับใน HTML
1
2
3
4
export default class extends Controller {
static targets = [ "name", "output" ]
...
}
ในส่วนของ target จะมีความพิเศษอยู่ตรงที่ค่าที่ถูกกำหนดอยู่ใน Array ข้างต้น Stimulus จะทำการเพิ่ม property ให้กับ controller ขึ้นโดยอัตโนมัติ โดยมีด้วยกัน 3 รูปแบบคือ
- Singular: จะอ้างอิงผ่าน
this.[name]Target - Plural: จะอ้างอิงผ่าน
this.[name]Targets - Existential: จะอ้างอิงผ่าน
this.has[Name]Target
1
2
3
4
greet() {
this.outputTarget.textContent =
`ยินดีต้อนรับ คุณ ${this.nameTarget.value} ในวัน${this.day()}`
}
สามารถดูรายละเอียดเพิ่มเติมได้ที่ Target
- เมื่อเพิ่มโค้ดครบทุกส่วนก็จะเห็นว่าโค้ดของเราสามารถทำงานได้ดังตัวอย่างคอมโพเนนต์ข้างต้น
วงจรชีวิต (Lifecycle)
ฟังก์ชัน callback เพื่อไว้ใช้สำหรับตอบสนองเหตุการณ์ที่ controller ทำการเชื่อมต่อหรือหยุดการเชื่อมต่อกับ DOM มีอยู่ด้วยกัน 3 ฟังก์ชัน คือ
initalize()ซึ่งจะถูกเรืยกเพียงครั้งเดียว เมื่อถูกสร้างขึ้นconnect()ซึ่งจะถูกเรียกเมื่อมีการเชื่อมต่อกับ DOMdisconnect()ซึ่งจะถูกเรียกเมื่อหยุดการเชื่อมต่อกับ DOM
การจะเลือกใช้ Framework อะไรก็ขึ้นอยู่กับงาน และความถนัดของผู้ใช้งาน ซึ่งในบทความนี้ได้ยกตัวอย่างขึ้นมาแสดงเพียงเล็กน้อยเท่านั้น หวังว่าในคราวน่าจะได้แชร์ประสบการณ์การนำ Stimulus มาให้ทุกคนอีกเพื่อให้เข้าใจมากขึ้น See ya!