Vue3 SFC 和 TSX 方式自定義組件實(shí)現(xiàn) v-model的詳細(xì)過程
1 v-model
1.1 理解 v-model
v-model 是 vue3 中的一個(gè)內(nèi)置指令,很多表單元素都可以使用這個(gè)屬性,如 input、checkbox 等,咱可以在自定義組件中實(shí)現(xiàn) v-model。v-model 本質(zhì)上是一個(gè)語法糖:
- 綁定父組件傳遞過來的 modelValue 屬性;
- 值改變時(shí)向父組件發(fā)出事件 update:modelValue。
1.2 案例描述
理解了 v-model 的本質(zhì),咱可以分別使用 SFC(.vue 文件)和 TSX(.tsx)方式定義一個(gè)組件 person-name ,使該組件可以使用 v-model。
person-name 包括兩個(gè)輸入框,分別是“姓”(familyName)和“名”(firstName)兩個(gè)字段,v-model 傳遞的數(shù)據(jù)格式為:
{ familyName: '張', firstName: '三' }
首先定義該類型 person-name-type.ts:
export interface PersonName { /** 姓 */ familyName?: string; /** 名 */ firstName?: string; }
1.3 編寫樣式
編寫 person-name.scss 樣式文件,后面再兩個(gè)組件中分別引入:
.person-name { .el-form-item { width: 200px; } }
2 編寫組件
2.1 實(shí)現(xiàn)思路
person-name 組件實(shí)現(xiàn)邏輯比較簡單:
- template 中放置兩個(gè)輸入框 el-input,分別對應(yīng) 姓 和 名 兩個(gè)字段;
- 定義兩個(gè)變量 innerFamilyName 和 innerFirstName 綁定兩個(gè)輸入框的值;
- 在 props 定義 modeValue 屬性,接收父組件傳遞過來的 PersonName 類型的對象;
- 使用 watch 深度監(jiān)聽 modelValue,當(dāng)其屬性值有變化時(shí),重新賦值給上面綁定輸入框的兩個(gè)變量;
- 當(dāng)兩個(gè)輸入框觸發(fā) input 事件時(shí),通過 update:modelValue 事件通知父組件,從而實(shí)現(xiàn) v-model。
2.2 SFC(.vue)中的實(shí)現(xiàn)
創(chuàng)建組件文件 person-name-sfc.vue:
<template> <div class="person-name"> <el-form-item label="姓"> <el-input v-model="innerFamilyName" @input="onInput"></el-input> </el-form-item> <el-form-item label="名"> <el-input v-model="innerFirstName" @input="onInput"></el-input> </el-form-item> </div> </template> <script lang="ts" setup name="person-name-sfc"> import { PropType, ref, watch } from 'vue' import { PersonName } from './person-name-type' const props = defineProps({ modelValue: { type: Object as PropType<PersonName>, required: true, default: () => ({}) } }) const emits = defineEmits(['update:modelValue']) const innerFamilyName = ref('') const innerFirstName = ref('') watch(() => props.modelValue, (newVal) => { innerFamilyName.value = newVal?.familyName || '' innerFirstName.value = newVal?.firstName || '' }, { deep: true, immediate: true }) const onInput = () => { emits('update:modelValue', { familyName: innerFamilyName.value, firstName: innerFirstName.value }) } </script> <style scoped lang="scss"> @import "./person-name"; </style>
2.3 TSX(.tsx)中的實(shí)現(xiàn)
創(chuàng)建組件文件 person-name-tsx.tsx:
import { defineComponent, PropType, ref, watch } from 'vue' import { PersonName } from './person-name-type' import './person-name.scss' export default defineComponent({ name: 'person-name-tsx', props: { modelValue: { type: Object as PropType<PersonName>, required: true, default: () => ({}) } }, emits: ['update:modelValue'], setup (props, context) { const innerFamilyName = ref(props.modelValue.familyName) const innerFirstName = ref(props.modelValue.firstName) const onInput = () => { context.emit('update:modelValue', { familyName: innerFamilyName.value, firstName: innerFirstName.value }) } watch(() => props.modelValue, (newVal) => { innerFamilyName.value = newVal?.familyName || '' innerFirstName.value = newVal?.firstName || '' }, { deep: true, immediate: true }) return () => ( <div class="person-name"> <el-form-item label="姓"> <el-input vModel={innerFamilyName.value} onInput={onInput}/> </el-form-item> <el-form-item label="名"> <el-input vModel={innerFirstName.value} onInput={onInput}/> </el-form-item> </div> ) } })
3 使用組件
創(chuàng)建父組件 demo-v-model.vue,在里面使用上面定義的兩個(gè)組件:
<template> <div> <person-name-sfc v-model="personName1"></person-name-sfc> <el-button @click="onResetClick1">reset</el-button> <div>{{personName1}}</div> </div> <el-divider /> <div> <person-name-tsx v-model="personName2"></person-name-tsx> <el-button @click="onResetClick2">reset</el-button> <div>{{personName2}}</div> </div> </template> <script lang="ts" setup> import PersonNameSfc from '@/components/model/person-name-sfc.vue' import { ref } from 'vue' import { PersonName } from '@/components/model/person-name-type' import PersonNameTsx from '@/components/model/person-name-tsx' const defaultPersonName = { familyName: '張', firstName: '三' } const personName1 = ref<PersonName>({ ...defaultPersonName }) const personName2 = ref<PersonName>({ ...defaultPersonName }) const onResetClick1 = () => { personName1.value = { ...defaultPersonName } } const onResetClick2 = () => { personName2.value = { ...defaultPersonName } } </script>
運(yùn)行效果如下:
上面部分使用 .vue 編寫的組件,下面部分使用 .tsx 編寫的組件,兩者獨(dú)立綁定 v-model,運(yùn)行效果完全一致。
- 子組件可以接收到父組件傳遞的初始值;
- 子組件值改變時(shí)會通知到父組件;
- 父組件改變值時(shí),子組件會響應(yīng)變更。
到此這篇關(guān)于Vue3 SFC 和 TSX 方式自定義組件實(shí)現(xiàn) v-model的文章就介紹到這了,更多相關(guān)Vue3 自定義組件v-model內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項(xiàng)目中如何將當(dāng)前頁面生成圖片
這篇文章主要介紹了vue項(xiàng)目中如何將當(dāng)前頁面生成圖片問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10vue中v-text / v-html使用實(shí)例代碼詳解
這篇文章主要介紹了vue中v-text / v-html使用實(shí)例代碼詳解,非常不錯(cuò),代碼簡單易懂,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04vue2中的el-select組件數(shù)據(jù)太多,如何實(shí)現(xiàn)滾動加載數(shù)據(jù)效果
這篇文章主要介紹了vue2中的el-select組件數(shù)據(jù)太多,如何實(shí)現(xiàn)滾動加載數(shù)據(jù)效果,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04Vue數(shù)據(jù)驅(qū)動表單渲染,輕松搞定form表單
這篇文章主要介紹了Vue數(shù)據(jù)驅(qū)動表單渲染,輕松搞定form表單,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07