Vue3 computed拦截vModel

115 阅读1分钟

Vue2 vModel

  • value
  • input/change/select

Vue3 vModel 默认

  • modelValue
  • update:modelValue

常见的封装组件 通过v-model V2

<Demo v-model="test" :changeTest="changeTest" />

Demo.vlue
props:{test}
emit('changeTest')

V3

const data = ref({
  name:"",
  age:"",
})
<HelloWorld v-model="data" />


//Hellow.vue
<script setup>
import { ref, defineProps } from "vue";

const props = defineProps({
  modelValue: {
    type: Object,
    default:()=> {}
  }
})
</script>

<template>
  <input type="text" v-model="props.modelValue.name" placeholder="姓名" />
  <input type="text" v-model="props.modelValue.age" placeholder="年龄" />
</template>

看似V3这样可以实现 但是破坏了单向数据流 可以在computed中拦截

<FormModel v-model="data" />

useModel.js

import { computed } from 'vue';

export function useModel(props,propName,emit){
    const model = computed({
        get: () => {
            return new Proxy(props[propName], {
                get(target, key) {
                    console.log("get");
                    return Reflect.get(target, key)
                },
                set(target, key, value) {
                    emit('update:'+propName, {
                        ...target,
                        [key]: value
                    })
                    return true
                }
            })
        },
        set: (val) => {
            emit('update:'+propName,val)
            return true
        }
    })
    return model
}
<script setup>
import { ref, defineProps, computed,toRefs } from "vue";
import { useModel } from './../hooks/useModel';

const props = defineProps({
    modelValue: {
        type: Object,
        default: () => { }
    }
})

const emit = defineEmits(['update:modelValue'])
const model = useModel(props,"modelValue",emit)
</script>
<template>
    <input type="text" v-model="model.name" placeholder="姓名" />
    <input type="text" v-model="model.age" placeholder="年龄" />
</template>
<style scoped></style>

这也是VueUse中的 useVModels的实现原理