點燈坊

失くすものさえない今が強くなるチャンスよ

使用 ref() 實現 JavaScript 與 HTML 連動

Sam Xiao's Avatar 2024-01-29

ref() 為 Reactivity API 最重要的 API,用來宣告 State。只要我們在 JavaScript 修改 state,HTML 就會 Reactive 地跟著改變;反之若我們在 HTML 修改 state,JavaScript 也會隨之改變。

Version

Vue 3.4

Composition API

<template>
  <button class="plus" @click="onClick">+</button>
  <div class="result">{{ count }}</div>
</template>

<script setup>
import { ref } from 'vue'

let count = ref(0)

let onClick = () => count.value++
</script>

<style scoped>
.plus {
  cursor: pointer;
}

.result {
  color: red;
}
</style>
  • Counter 可視為前端 的 Hello World,雖然簡單,卻有很多觀念在裡面
<template>
</template>

<script setup>
</script>

<style scoped>
</style>
  • Vue 分成 3 大區塊:
    • template:寫 HTML
    • script:寫 JavaScript
    • style:寫 CSS

剛好一個 component (.vue) 同時具備 HTML、JavaScript、CSS

  • template
    • Vue 3 解除 Vue 2 所有 HTML 必須在一個 root element 限制
  • script
    • setup:支援 Script Setup,所有代碼會被 Vite 放進 setup()
  • style
    • scoped:所有的 class 只在此 .vue 內有效,避免 side effect

Q:若有跨 page 需求的 CSS sytle 呢?

A:請將該需求抽成 component,而非使用 global CSS

Line 1

<template>
  <button class="plus" @click="onClick">+</button>
  <div class="result">{{ count }}</div>
</template>
  • @:原本應為 v-on:click="onClick",其中 v-on 可以縮寫成 @,表示指定 event handler
  • Text Interpolation:將 state 單向 顯示在 HTML,只要該 state 在 JavaScript 有變動,Vue 會自動 render HTML
  • class:指定 CSS class

<button> 是 inline element 不換行,<div> 是 block element 會換行

Line 6

<script setup>
import { ref } from 'vue'

let count = ref(0)

let onClick = () => count.value++
</script>
  • ref()
    • Vue 3 的 API 都是以 ESM 呈現,沒有所謂的 global function,所以要用什麼 function 都要手動 import,也有助於 Vite 運作與 Tree Shaking
    • 若要定義需與 HTML 連動 的 state,必須使用 ref() 宣告
    • 若只是 JavaScript 不同 function 的 共用變數不牽涉 與 HTML 連動,則 不必 使用 ref() 宣告
    • 使用 ref() 宣告過的變數,在 HTML 可直接讀寫,但在 JavaScript 必須透過 .value 才能讀寫
    • 可藉由有沒有 .value 分辨是與 HTML 連動 的變數,還是普通 JavaScript 變數
  • Method
    • 需與 HTML template 互動的 function
      • Event Handler (@click)
      • Directive (v-if)
    • Vue 3 的 method 只需以普通 function 定義即可
    • 由於 Vue 3 不必再以 this 存取 data,可大膽使用 arrow function

functionthis 因為可隨 context 而變,因此 Options API 可藉由改變 context 而指向 Vue instance,但 arrow function 的 this 不可變,永遠指向 function 自己,無法透過改變 context 而指向 Vue instance

Line 14

<style scoped>
.plus {
  cursor: pointer;
}

.result {
  color: red;
}
</style>
  • Style 區塊可如既往一樣寫 CSS

Options API

<template>
  <button @click="onClick">+</button>
  <div>{{ count }}</div>
</template>

<script>
export default {
  data: () => ({
    count: 0,
  }),
  methods: {
    onClick() {
      this.count++
    },
  },
}
</script>
  • 最後附上相同功能的 Options API 供參考
  • State 宣告在 data() function
  • Method 宣告在 methods Object

Conclusion

  • ref() 雖然很基本的 function,但卻非常實用,讓我們不必像 Vanilla.js 或 jQuery 一樣,不斷地讀取 HTML,不斷地寫入 HTML,JavaScript 只需專心處理 state 即可,HTML 由 Vue 負責處理
  • 很多人從 jQuery 改寫 Vue 時一直跨不過去的檻:總是想手動處理 HTML,雖然 Vue 也可以這樣寫,但這並非 Vue 設計的初衷
  • Vue 心法:處理 HTML 是 Vue 的事情,我們只要專心處理 state 即可