关于vue3的 组件封装中computed和v-model 的一些使用

867 阅读1分钟

<script setup lang="ts">
import { ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'

const searchData = ref({
  keyword: '1',
  optionList: ['1','2','3'],
  value: ''
})
</script>

<template>
  {{ searchData.value }}
  <HelloWorld v-model="searchData"  />
</template>

<style scoped>

<script setup lang="ts">
import { computed } from 'vue'
const props = withDefaults(
    defineProps<{
      modelValue: any,
      name: string
    }>(),
    {
      name: '张珊',
      modelValue: ()=> {
        keyword: ''
        optionList: []
        value: ''
      }
    }
)

const emit = defineEmits(['update:modeValue'])
const model = computed({
  get(){
    return new Proxy(props.modelValue,{
      set(obj,name,val){
        emit('update:modeValue',{
          ...obj,
          [name]: val
        })
        return true
      }
    })
  },
  set(val){
    emit('update:modeValue', val)
  }
})

</script>

<template>
    <div>
      <select v-model="modelValue.keyword" style="width: 50px;">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select>
      <input type="text" v-model="modelValue.value" >
    </div>
</template>


继续拆分

// useModel.ts
import { computed } from 'vue'
export function useModel(props:any, propName:string, emit:any){
    return computed({
        get(){
          return new Proxy(props[propName],{
            set(obj,name,val){
              emit('update:'+propName,{
                ...obj,
                [name]: val
              })
              return true
            }
          })
        },
        set(val){
          emit('update:'+propName, val)
        }
      })
}

而后简化

<script setup lang="ts">
import { useModel } from './useModel'
const props = withDefaults(
    defineProps<{
      modelValue: any,
      name: string
    }>(),
    {
      name: '张珊',
      modelValue: ()=> {
        keyword: ''
        optionList: []
        value: ''
      }
    }
)

const emit = defineEmits(['update:modeValue'])
const model = useModel(props, 'modeValue', emit)

</script>

<template>
    <div>
      <select v-model="modelValue.keyword" style="width: 50px;">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select>
      <input type="text" v-model="modelValue.value" >
    </div>
</template>

<style scoped>
.read-the-docs {
  color: #888;
}
</style>