1. vue 子组件修改 props 值
在 Vue 中,props
应被视为只读的,这是为了确保组件之间的数据独立性和可预测性。
直接修改 props
会导致难以追踪的 bug,并且违反了单向数据流的原则。
然而,有时候确实需要在子组件中基于 props
的值进行一些操作。
以下是几种常见的处理方式:
1.1. 使用局部状态
在子组件中创建一个局部状态来存储 prop
的值,并在需要时更新这个局部状态。
<template> <div> <p>{{ localTitle }}</p> <button @click="updateLocalTitle">Update Title</button> </div> </template> <script setup> import { ref, watch } 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>
1.2. 使用 $emit
发送事件
如果需要将子组件中的更改通知给父组件,可以使用 $emit
发送事件,让父组件来更新数据。
1.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>
1.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>
1.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>
1.4. 使用 v-model
或自定义模型
Vue 3 支持 v-model
的自定义修饰符,可以更方便地实现双向绑定。
1.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>
1.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>
1.5. 总结
局部状态:在子组件中创建一个局部状态来存储
prop
的值,并在需要时更新这个局部状态。发送事件:使用
$emit
发送事件,让父组件来更新数据。计算属性:基于
props
的值进行计算,使用计算属性来实现。自定义模型:使用
v-model
或自定义模型实现双向绑定。
通过这些方法,可以在不直接修改 props
的情况下,实现所需的功能,同时保持组件的可维护性和可预测性。