前言
通常來講,我們在開發時往往會很需要還原初始值,因此這一篇就來分享一下小技巧,而這個小技巧基本上不論是 Vue2 還是 Vue3 都是通用的。
情境
我們其實很常需要與遠端伺服器做 AJAX 溝通,那麼當使用者溝通完畢後,總是會有一種狀況存在,就是使用者輸入的原始資料依然保留在 Vue Data 中,這時候可能會有一些很麻煩的問題發生,所以我這邊寫了一段程式碼模擬了使用者輸入之後點連結觸發 AJAX 的行為(並不是真的觸發,只是用 setTimeout 語法模擬而已)。
1 2 3 4 5 6 7
| <div id="app"> 請輸入你的姓名: <input type="text" v-model="myName"> <div>我的名字是:{{ myName }}</div> <br> <a href="#" @click.prevent="ajax">點我觸發 AJAX</a> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Vue.createApp({ data() { return { myName: '' } }, methods: { ajax() { setTimeout(() => { console.log('新增成功!'); console.log('但是原始資料依然存在:', this.myName); }, 1500); } } }).mount('#app');
|
你可以試著點以下 Codepen 試試看
Reset Options API Data
那麼為了達到這個需求,通常我們可能這樣做,在 AJAX 之後重新賦予空值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Vue.createApp({ data() { return { myName: '' } }, methods: { ajax() { setTimeout(() => { console.log('新增成功!'); this.myName = ''; }, 1500); } } }).mount('#app');
|
但這種做法其實是會有一些問題存在,當如果你是一個物件時,你就必須重新寫一樣的物件屬性,當有 10 個屬性你就要寫 10 次,其實這樣格外麻煩且可能維護上會有一些問題。
那該如何解決才會比較好呢?其實非常簡單,你只需要這樣寫就好了
在 Vue 官方文件中其實有提到這個 物件 屬性,以下擷取官方文件說明:
用于当前组件实例的初始化选项。

看起來文謅謅吧?簡單來講就是…
當你 Vue 準備完畢時,它會將你初始化的 data 資料拷貝一份到 this.$options 底下,data 本身是一個函式,所以你必須使用呼叫的方式,因此你就可以將上方改寫成以下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Vue.createApp({ data() { return { myName: '' } }, methods: { ajax() { console.log(this); setTimeout(() => { console.log('新增成功!'); this.myName = this.$options.data().myName console.log('資料變成初始了:', this.myName); }, 1500); } } }).mount('#app');
|
這樣子在做還原初始值是一個比較安全且保險的方式,畢竟你在第一次渲染時都會盡可能的定義初始值,那麼要還原初始值的話,反而會建議使用 this.$options.data() 會較穩定(避免你粗手指漏寫)
雖然上面是使用 Vue3 去做範例,但是 Vue2 本身就是 Options API 因此其實兩者都是通用的。
Reset Composition API Data
那麼問題來了,因為 Vue3 本身是支援 Options API,所以可以透過 this 呼叫 $options,但是在 Vue3 的 Composition API 中並沒有辦法使用 this,那這樣子該怎麼辦呢?
剛好在官方 issues 中就有人提出解決方式
因此我們就知道可以透過 Object.assign 來做到類似重設的效果,透過上面討論的話我們可以改成以下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| Vue.createApp({ setup() { const initialData = { myName: '', } const data = Vue.reactive({ ...initialData }); const ajax = () => { setTimeout(() => { console.log('新增成功!'); Object.assign(data, initialData); console.log('資料變成初始了:', data.myName); }, 1500); }
return { data, ajax } } }).mount('#app');
|
See the Pen
Vue3 reactive toRef by Ray (@hsiangfeng)
on CodePen.
而另一種寫法則是像這樣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| Vue.createApp({ setup() { const initialData = () => { return { myName: '', } } const data = Vue.reactive(initialData()); const ajax = () => { setTimeout(() => { console.log('新增成功!'); Object.assign(data, initialData()); console.log('資料變成初始了:', data.myName); }, 1500); }
return { data, ajax } } }).mount('#app');
|
那這時候你可能會問 ref 呢?通常來講 ref 並不會拿來一次放許多物件屬性,因此比較不會遇到需要 reset 的問題,如果真的需要 reset 也是直接重新賦予值就好了,畢竟 ref 就只是一個單一型別的值。
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
Advertisement