Vue 子组件修改 Props 值常见的错误写法,你学会了吗?

开发 前端
在 Vue 中,props 应被视为只读的,直接修改 props 会导致难以追踪的 bug,并且违反了单向数据流的原则。

图片图片

Vue 子组件修改props值常见的错误写法

在 Vue 中,props 应被视为只读的,直接修改 props 会导致难以追踪的 bug,并且违反了单向数据流的原则。

以下是一些常见的错误写法及其解释,以及正确的处理方法。

1. 常见错误写法

1.1. 直接修改 props

直接修改 props 是最常见的错误之一。

这种做法会导致 Vue 控制台输出警告,并且可能会导致不可预测的行为。

<template>
  <div>
    <p>{{ title }}</p>
    <button @click="updateTitle">Update Title</button>
  </div>
</template>

<script setup>
import { defineProps } from 'vue';

const props = defineProps({
  title: String
});

const updateTitle = () => {
  props.title = 'New Title'; // 错误:直接修改 props
};
</script>

1.2. 使用 v-model 但未正确处理

虽然 v-model 可以实现双向绑定,但如果使用不当,仍然会导致问题。

<template>
  <div>
    <p>{{ title }}</p>
    <input v-model="title"> <!-- 错误:直接绑定到 props -->
  </div>
</template>

<script setup>
import { defineProps } from 'vue';

const props = defineProps({
  title: String
});
</script>

1.3. 在 data 中直接使用 props

在 data 中直接使用 props 会导致数据的重复和不一致。

<template>
  <div>
    <p>{{ localTitle }}</p>
    <button @click="updateTitle">Update Title</button>
  </div>
</template>

<script setup>
import { ref, defineProps } from 'vue';

const props = defineProps({
  title: String
});

const localTitle = ref(props.title); // 错误:未处理 props 的变化

const updateTitle = () => {
  localTitle.value = 'New Title';
};
</script>

2. 正确的处理方法

2.1. 使用局部状态

在子组件中创建一个局部状态来存储 prop 的值,并在需要时更新这个局部状态。

使用 watch 来监听 prop 的变化。

<template>
  <div>
    <p>{{ localTitle }}</p>
    <button @click="updateLocalTitle">Update Title</button>
  </div>
</template>

<script setup>
import { ref, watch, defineProps } from 'vue';

const props = defineProps({
  title: String
});

const localTitle = ref(props.title);

watch(() => props.title, (newVal) => {
  localTitle.value = newVal;
});

const updateLocalTitle = () => {
  localTitle.value = 'New Title';
};
</script>

2.2. 使用 $emit 发送事件

如果需要将子组件中的更改通知给父组件,可以使用 $emit 发送事件,让父组件来更新数据。

2.2.1. 子组件
<template>
  <div>
    <p>{{ title }}</p>
    <button @click="updateTitle">Update Title</button>
  </div>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
  title: String
});

const emit = defineEmits(['update:title']);

const updateTitle = () => {
  emit('update:title', 'New Title');
};
</script>
2.2.2. 父组件
<template>
  <ChildComponent :title="title" @update:title="updateTitle" />
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const title = ref('Initial Title');

const updateTitle = (newTitle) => {
  title.value = newTitle;
};
</script>

2.3. 使用计算属性

如果需要基于 props 的值进行一些计算,可以使用计算属性来实现。

<template>
  <div>
    <p>{{ computedTitle }}</p>
  </div>
</template>

<script setup>
import { defineProps, computed } from 'vue';

const props = defineProps({
  title: String
});

const computedTitle = computed(() => {
  return `Modified: ${props.title}`;
});
</script>

2.4. 使用 v-model 或自定义模型

Vue 3 支持 v-model 的自定义修饰符,可以更方便地实现双向绑定。

2.4.1. 子组件
<template>
  <div>
    <p>{{ title }}</p>
    <input v-model="localTitle" @input="onInput">
  </div>
</template>

<script setup>
import { defineProps, defineEmits, computed } from 'vue';

const props = defineProps({
  modelValue: String
});

const emit = defineEmits(['update:modelValue']);

const localTitle = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
});

const onInput = (event) => {
  emit('update:modelValue', event.target.value);
};
</script>
2.4.2. 父组件
<template>
  <ChildComponent v-model:title="title" />
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const title = ref('Initial Title');
</script>

3. 总结

  • 直接修改 props:会导致 Vue 控制台警告和不可预测的行为。
  • 使用 v-model 但未正确处理:可能导致数据绑定错误。
  • 在 data 中直接使用 props:导致数据的重复和不一致。

通过使用局部状态、发送事件、计算属性或自定义模型,可以在不直接修改 props 的情况下,实现所需的功能,同时保持组件的可维护性和可预测性。

责任编辑:武晓燕 来源: 前端爱好者
相关推荐

2023-06-27 07:21:51

前端开发坑点

2022-12-09 09:21:10

分库分表算法

2023-12-26 10:12:19

虚拟DOM数据

2024-08-30 14:34:00

2024-11-27 11:07:20

vue计算属性

2022-07-08 09:27:48

CSSIFC模型

2024-10-14 09:34:39

vue3通信emit

2024-02-04 00:00:00

Effect数据组件

2024-01-19 08:25:38

死锁Java通信

2023-01-10 08:43:15

定义DDD架构

2023-07-26 13:11:21

ChatGPT平台工具

2024-02-02 11:03:11

React数据Ref

2023-08-01 12:51:18

WebGPT机器学习模型

2024-01-02 12:05:26

Java并发编程

2023-10-30 11:40:36

OOM线程池单线程

2024-07-31 08:39:45

Git命令暂存区

2023-01-30 09:01:54

图表指南图形化

2024-08-06 09:47:57

2024-05-06 00:00:00

InnoDBView隔离

2023-10-10 11:04:11

Rust难点内存
点赞
收藏

51CTO技术栈公众号