iT邦幫忙

2

v-model 續集 (feat. computed)

Pam 2024-05-18 20:38:17472 瀏覽
  • 分享至 

  • xImage
  •  

想不到對我來說,v-model還有續集...

在vue pre3.4之前,defineModel還沒出現之前,要怎麼處理組件間的雙向綁定?目前我知道的有兩種方式。

1. 自行定義prop & emit

這個文件上也有,在子組件裡自己定義v-bind & v-on,讓component的input值由prop去views那邊接資料,同時當input欄位有新的輸入時,發出emit並帶著輸入的值給views。

<script setup>
const props=defineProps({
  msg:{
    type: String,
    required: true,
    default:()=>''
  }
  })
const emits=defineEmits(['update:msg'])
</script>

<template>
  <span>My input</span> 
  <input :value="props.msg" @input="emits('update:msg',$event.target.value)">
</template>

2. 利用computed的特殊用法:getter & setter

基本上的想法就是用 "writable computed"來自己做類似defineModel的東西。
回想一下,v-model是由v-bind & v-on組成,如果是組件間的雙向綁定,v-bind要bind的是一個prop,v-on要on的是一個emit,所以defineModel幫我們做好了props & emit給views(父組件)來v-model,且它本身又回傳一個ref,給component(子組件)裡的v-model,讓使用者的input能與這個ref同步。

用computed實現變成下面這樣:

因為computed是一個ref,而它的內容是由getter & setter組成

  • views-> computed-> component input 由views同步component input
    computed這個ref的值如果要同步views那邊的ref,取值由getter負責,我們用一個名為msg的prop去拿。所以當views那邊的ref有更動時,component的prop也會收到,beforeDefineModel也會跟著變,再經由component自身的v-model進一步同步至input欄位的值。
  • component input-> computed-> views 由component input同步views
    當我們要操控這個ref的值時,由setter負責,setter裡會自動帶著一個argument,是我們要set進去的值,而這個值是由input欄位,使用者的輸入來的。拿著這個新值,我們發出一個emit給views並附帶著這個新值,請views那邊根據新值做對應的更新。於是可以做到由component的input去同步views的ref。
const props=defineProps({
  msg:{
    type: String,
    required: true,
    default:()=>''
  }
  })
const emits=defineEmits(['update:msg'])
const beforeDefineModel=computed({
  get(){
    return props.msg
  },
  set(newValue){
    emits('update:msg',newValue )
  }
})

參考資料

vue-v-model
vue-computed
Vue 3 — 在子元件中修改父層的狀態 feat. props、emit、computed


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言