Introduction to Stimulus

23-03-2020 | Karn | 4 minutes
Stimulus HTML

สำหรับ 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() ซึ่งจะถูกเรียกเมื่อมีการเชื่อมต่อกับ DOM
  • disconnect() ซึ่งจะถูกเรียกเมื่อหยุดการเชื่อมต่อกับ DOM

การจะเลือกใช้ Framework อะไรก็ขึ้นอยู่กับงาน และความถนัดของผู้ใช้งาน ซึ่งในบทความนี้ได้ยกตัวอย่างขึ้นมาแสดงเพียงเล็กน้อยเท่านั้น หวังว่าในคราวน่าจะได้แชร์ประสบการณ์การนำ Stimulus มาให้ทุกคนอีกเพื่อให้เข้าใจมากขึ้น See ya!

References