vue3个人最佳实践记录(2)- useVModels/defineModel 助力单项数据流更丝滑

673 阅读3分钟

为什么需要单项数据流

现在不管是使用vue,react这类数据驱动的框架,我们操作的最小元就是组件,组件间通过props传递参数。 我们为了方便排查解决项目中的bug,务必要做的就是单项数据流

什么是单项数据流?

"单向数据流"是一种数据流动模式,通常在前端框架(如React、Vue等)中使用。它指的是数据在应用程序中的流动方向是单向的,即从父组件流向子组件,但不会反向流动。 在单向数据流模式中,数据通常由父组件传递给子组件,子组件可以通过props属性接收数据,然后子组件可以修改自己的状态,但无法直接修改父组件的状态。这种模式有助于保持应用程序的状态清晰和可控,减少了数据流动的复杂性,使得应用程序更容易调试和维护。

单向数据流模式的优点包括:

  1. 易于理解和维护: 数据的流动方向是单向的,使得代码的逻辑更加清晰和可预测。
  2. 数据流动的可控性: 数据只能从父组件流向子组件,避免了数据流动的混乱和不可预测性。
  3. 更容易调试: 由于数据流动的方向明确,使得在调试过程中更容易定位和解决问题。
  4. 提高了组件的可复用性: 父组件通过props属性向子组件传递数据,使得子组件更加独立和可复用。

总的来说,单向数据流模式是一种简单而有效的数据流动模式,有助于提高应用程序的可维护性和可扩展性,同时也使得代码更加清晰和易于理解。

单项数据流的注意事项与优势

  1. 简单理解单项数据流就是A组件提供的数据我只在A组件去变更
  2. 如果需要我们刻意的保持单向数据流的思维可以,但是代码组织方式的变更短时间内是一个心智负担,useVModels这个工具给予了我们全面的支持,很润!

下面是代码实现的对比

<script setup>
import HelloWorld from '@/components/HelloWorld.vue'
import { ref } from 'vue'
const user = ref({
  name: 'wangxuan',
  age: 18
})
</script>

<template>
  <HelloWorld v-model:user="user"></HelloWorld>
</template>


<script setup>
import {
  Form,
  FormItem,
  Input,
} from 'ant-design-vue'
import { toRefs } from 'vue'

const props = defineProps({
  user: {
    type: Object,
    required: true,
  },
})
const { user } = toRefs(props)

const emit = defineEmits(['update:user'])

const emitUser = (data) => {
  emit('update:user', {...user.value, ...data})
}
</script>

<template>
  <Form>
    <FormItem label="姓名">
      <Input :value="user.name" @change="(e)=> emitUser({name: e.target.value})" />
    </FormItem>
    <FormItem label="年龄">
      <Input :value="user.age" @change="(e)=> emitUser({age: e.target.value})" />
    </FormItem>
  </Form>
</template>

useVModels

<script setup>
import HelloWorld from '@/components/HelloWorld.vue'
import { ref } from 'vue'
const user = ref({
  name: 'wangxuan',
  age: 18
})
</script>

<template>
  <HelloWorld v-model:user="user"></HelloWorld>
</template>

<script setup>
import { useVModels } from '@vueuse/core'
import {
  Form,
  FormItem,
  Input,
} from 'ant-design-vue'

const props = defineProps({
  user: {
    type: Object,
    required: true,
  },
})

const emit = defineEmits(['update:user'])
const { user } = useVModels(props, emit)
</script>

<template>
  <Form>
    <FormItem label="姓名">
      <Input v-model:value="user.name" />
    </FormItem>
    <FormItem label="年龄">
      <Input v-model:value="user.age" />
    </FormItem>
  </Form>
</template>

defineModel vue3.14版本

<script setup>
import HelloWorld from '@/components/HelloWorld.vue'
import { ref } from 'vue'
const user = ref({
  name: 'wangxuan',
  age: 18
})
</script>

<template>
  <HelloWorld v-model:user="user"></HelloWorld>
</template>

<script setup>
import {
  Form,
  FormItem,
  Input,
} from 'ant-design-vue'

const user = defineModel('user')
</script>

<template>
  <Form>
    <FormItem label="姓名">
      <Input v-model:value="user.name" />
    </FormItem>
    <FormItem label="年龄">
      <Input v-model:value="user.age" />
    </FormItem>
  </Form>
</template>

父组件没有变化,子组件减少了一部分代码。useVModels的实现方式就是返回一个被proxy劫持过的对象,当触发set操作时,派发对应的数据变更,保证了单向数据流

后续会陆续分享vue3个人觉得最佳实践