2024-02-20
【React-Vue】輸入欄位的資料綁定 (v-model)

原文發表於 Medium。

若網頁有使用者須輸入的欄位,則時常需要資料綁定的技術
我們時常需要依照輸入的內容更改網頁狀態(State)(如變換文字內容或背景顏色等)。在React中,若要綁定使用者輸入欄位的資料到狀態值上,我們可以這樣寫:
import React, { useState } from 'react'
const App = () => {
const [name, setName] = useState("比利")
function onChangeHandler(e){
setName(e.target.value)
}
return (
<>
<h1>你的名字是<span style={{color:"blue"}}>{name}</span></h1>
<input value={name} onChange={onChangeHandler}/>
</>
)
}
export default App

效果如上方GIF所示。只要改變<input>的內容,就會讓顯示出來的名字不同。
在這個非常簡單的程式碼中,可以很容易發現到,在<input>中有兩個屬性:value跟onChange,前者是將<input>的值跟name綁在一起;後者則是讓<input>輸入時觸發onChangeHandler函數,之後在函數內將輸入的event值設定為name的狀態值。
這就是React的「雙向綁定」(two-way binding)。
另外一個前端大咖Vue.js大笑三聲說道:「太嫩了,我內建雙向綁定!才不需要寫這麼多東西呢!」
另外一個前端大咖Vue.js大笑三聲說道:「太嫩了,我內建雙向綁定!才不需要寫這麼多東西呢!」
且看Vue.js怎麼寫出相同的效果:
<template> <div> <h1>你的名字是 <span style="color: blue">{{ name }}</span></h1> <input v-model="name" /> </div> </template><script setup>
import { ref } from 'vue';
const name = ref('比利');
</script>
天啊!確實是很簡潔有力的寫法!input裡面居然只有一個屬性v-model !然後在<script>中居然不需要任何handler函數來幫忙改變狀態值!!真的太方便了!
其實,v-model是個語法糖,為的是方便Vue的使用者進行資料綁定,在不使用它的時候 ,vue寫法也沒有高明到哪裡去:
<input
:value="name"
@input="event => name = event.target.value" />
{/*補充,上面的寫法已經是簡寫了,下面是不使用簡寫的情況
<input
v-bind:value="name"
v-on:input="event => name = event.target.value" />
*/}
從不斷簡化語法這件事情上,看得出來Vue框架的開發者真的非常貼心,讓開發方式更加平易近人,這樣的態度很值得React借鏡。
但建議Vue的學習者在過程中還是不要太貪快,隨時對程式碼的底層邏輯保持好奇心,因為不使用語法糖的原始寫法,有時可以應付一些特殊狀況,例如我也可以設定input不要雙向綁定:
<script setup>
import { ref } from 'vue';
const name = ref('比利');
</script>
我把原本input中的value屬性刪掉,然後在下方加了一個可以把name值清空的按鈕,整個網頁的運行狀況如下:

在按下清除按鈕後,標題的名字清除了,輸入欄位中的文字並沒有跟著清除,然後隨著新一波的鍵盤輸入,標題的欄位又會馬上重新呈現輸入欄位的內容。
你可能會說這是Bug,大部分時候這是對的,但萬一你的客戶就是要這樣的功能呢?又或者這個狀況就是你的前一手造成的,你不知道底層原理要怎麼修呢?下面是我們把:value屬性還給input之後的效果:

我們的清除按鈕總算有比較接近一般經驗中的功能了。
總結以上,由於Vue有v-model這個神器,因此它可以簡單地實現資料的雙向綁定,而不須像React一樣需要手動綁住value值跟輸入事件的觸發動作。但無論是使用哪個框架技術,我們都要理解資料綁定狀態的基礎邏輯與概念。這樣跨框架跟跳槽比較方便啦!(誤。
最後,其實v-model還不只這樣的用法,它還可以用作類似React Props的方式,來達成跨元件的資料傳輸。但因為篇幅的關係,期待在下一篇中跟大家好好討論一下。
如果覺得我的文章不錯的話,還請給我幾個掌聲,你的支持是我繼續寫下去的動力!!