Vu3.x如何給v-for循環出來的輸入框綁定v-mode的值,以及實現父子組件傳值、雙向綁定
- 2022 年 10 月 10 日
- 筆記
觀前須知:本人演示使用的input是自己手敲的,如果使用的是element-ui等表單組建的input框請選擇性參考,不保證我的方法對你們也完全有效。
父組件程式碼:
這裡我的MiniInput是以組件形式引入的父頁面 (這裡只貼關鍵程式碼)
<template>
<div>
<MiniInput
v-for="item in titleArray"
:key="item.id"
>
<template #miniTitle> {{ item.name }} </template>
</MiniInput>
</div>
</template>
<script setup lang="ts">
import { Ref, ref } from 'vue'
import MiniInput from '../components/MiniInput.vue'
//用ref包裹數組,方便後期實現雙向綁定
const titleArray: Ref<Array<TitleArray>> = ref([
{
name: 'Exclude content',
id: 1231,
textVal: ''
},
{
name: 'Federated content',
id: 1232,
textVal: ''
},
{
name: 'Optional retrieval',
id: 1233,
textVal: ''
},
])
</script>
子組件程式碼:
<template>
<div class="from__input__mini">
<span class="mini-title">
<slot name="miniTitle"></slot>
</span>
<input class="mini-input" type="text" />
</div>
</template>
<script setup lang="ts">
</script>
上述程式碼可以得到以下介面效果,這是我們只完成了表面工作(請忽略樣式)

下面開始正題:
首先,我們要打通父子組件的隔閡,先將父組件的textVal傳遞給子組件,這裡我們需要使用到v-mode語法,將我們先前定義好的數組內的textVal屬性傳遞過去。
<!-- 下面新增了一行 v-mode -->
<MiniInput
v-model:textVal="item.textVal"
v-for="item in titleArray"
:key="item.id"
>
<template #miniTitle> {{ item.name }} </template>
</MiniInput>
隨後我們來到子組件,為接收父組件傳遞過來的值做準備
<script setup lang="ts">
// defineProps 用於接收父組件傳遞過來的參數
defineProps<{
textVal: string
}>()
</script>
此時我們就可以給子組件綁定父組件傳遞過來的參數了
<template>
<div class="from__input__mini">
<span class="mini-title">
<slot name="miniTitle"></slot>
</span>
<input :value="textVal" class="mini-input" type="text" />
</div>
</template>
<script setup lang="ts">
// defineProps 用於接收父組件傳遞過來的參數
defineProps<{
textVal: string
}>()
</script>
實現雙向綁定
但是此時我們會發現,到目前為止我們也僅僅只是接受了父組件傳遞過來的參數,此時我們去輸入框改變內容時,並不會同時改變父組件中的值,那麼此時我們就要想辦法實現數據流的 雙向綁定
要實現雙向數據響應,首先子組件要使用 defineEmits 接受父組件傳遞過來的 textVal 的 update 函數,隨後我們給輸入框添加一個input事件,目的是監聽輸入內容隨後改變父組件中的對應屬性。
<template>
<div class="from__input__mini">
<span class="mini-title">
<slot name="miniTitle"></slot>
</span>
<input :value="textVal" @input="changeText" class="mini-input" type="text" />
</div>
</template>
<script setup lang="ts">
// defineProps 用於接收父組件傳遞過來的參數
defineProps<{
textVal: string
}>()
// 要實現雙向數據響應要使用 defineEmits 接受父組件傳遞過來的 textVal 的 update函數
const emit = defineEmits(['update:textVal'])
// 輸入框input事件
const changeText = (e: Event) => {
// 這裡因為ts自動類型推斷會把變數推斷為EventTarget,導致沒辦法讀取到.value屬性,所以要進行一個類型斷言
const target = e.target as HTMLInputElement
emit('update:textVal', target.value)
}
</script>
這時我們就可以回到父組件中,為父組件的數組添加一個監聽事件:
// 這裡是父組件的script
<script setup lang="ts">
import { Ref, ref, watch } from 'vue'
...
...
...
// 監聽數組
watch
titleArray,
() => {
console.log('數組變化了')
},
{
deep: true
}
)
</script>
隨後進行測試

可以看到,雖然是通過循環生成的三個子組件(input),但是它們各自都實現了雙向數據綁定以及數據監聽,至此,效果實現,本部落格僅用於開發過程中的記錄以及復盤,僅供參考!
