Skip to content

Vue3 中 v-model 的背后逻辑

vue3v-model 会被编译成什么呢?是否可以不使用 v-model 呢?

我最近在写一些 TSX 组件的时候遇到了这个问题,看了一下 naive-ui 的代码,发现他们都是用 tsx 编写 vue3 组件的,详情看 这里

208 行的时候,有 2call 的方法,分别考虑了

  • 使用 v-model:height="ref" 和使用 :height="ref" & :on-update-height="e => ref = e" 的情况

  • 对应到 TSX 里就是 v-model={ref.value} 以及 height={ref.value} & on-update-height={e => ref.value = e}

列子

vue
<script setup>
import { ref } from 'vue'
import Comp from './Input.tsx'

const value1 = ref('')
const value2 = ref('')
</script>

<template>
  <h3>使用 v-model:value: {{ value2 }}</h3>
  <Comp v-model:value="value2" />

  <br />

  <h3>不使用: {{ value1 }}</h3>
  <Comp :value="value1" :on-update-value="(e) => (value1 = e)" />
</template>
tsx
import { defineComponent, type PropType } from 'vue'

type Props = {
  value?: string
  onUpdateValue?: (e: string) => void
  ['onUpdate:value']?: (e: string) => void
}

const props = {
  value: {
    type: String as PropType<Props['value']>,
    default: '',
  },
  onUpdateValue: {
    type: Function as PropType<Props['onUpdateValue']>,
    default: () => () => {},
  },
  ['onUpdate:value']: {
    type: Function as PropType<Props['onUpdate:value']>,
    default: () => () => {},
  },
}

export default defineComponent<Props>({
  name: 'Input',
  props,
  setup: (props) => {
    const handleInput: HTMLInputElement['oninput'] = (e) => {
      const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props

      if (e.target instanceof HTMLInputElement) {
        onUpdateValue && onUpdateValue(e.target.value)
        _onUpdateValue && _onUpdateValue(e.target.value)
      }
    }

    return () => <input value={props.value} onInput={handleInput} />
  },
})