第一种解决方法
vue 的子组件 不是 不能直接更改父组件的值,需要将props 的值 给到子组件,后再修改,
否则:Unexpected mutation of “props” prop.
vue3提供了一个解决:toRefs:https://v3.cn.vuejs.org/api/refs-api.html#torefs
toRefs
非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行解构/展开
使用
const { foo, bar } = reactive({
foo: 1,
bar: 2
})
// 核心解决, 使用reactive接收不会响应时更新,需要使用toRefs
const props = defineProps({
drawerStatus: {
type: Boolean
}
})
const {drawerStatus} = toRefs(props)
使用toRefs进行解决
<template>
<el-drawer v-model="drawerStatus" title="设置部门助理" :before-close="handleClose">
<div class="drawer-footer">
<el-button>取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</div>
</el-drawer>
</template>
<script setup>
import {reactive, toRefs} from 'vue'
const props = defineProps({
drawerStatus: {
type: Boolean
}
})
const emits = defineEmits(['upDrawerStatus'])
const {drawerStatus} = toRefs(props)
console.log(33333333, drawerStatus)
// 新增角色数据
const formData = reactive({
})
const onSubmit = () => {
handleClose()
}
const handleClose = () => {
console.log('关闭抽屉')
emits('upDrawerStatus', false)
}
</script>
优化版
vue3.0 子组件修改父组件传递过来的值优化vue3 Unexpected mutation of “childFormData” prop
超级简单版,父组件只要传入el-form的对象,子组件接收父组件的props既可完成
父组件
父组件将 form表单的 popFormData传递给子组件
<!--el-form 父组件-->
<el-form
ref="ruleForm"
label-position="top"
label-width="110px"
:model="popFormData"
:rules="rules"
style="padding: 20px"
>
<!--封装的子组件-->
<business-module :child-form-data="popFormData" />
</el-form>
子组件
子组件定义一个 viewsData 对象接收父组件传过来的值:formData: props.childFormData,然后el-select中使用即可;
示例中的@change=“chooseBusinessHandle” 选择后为父组件添加值或者修改值并不会报错:(vue3 Unexpected mutation of “childFormData” prop vue3“childFormData”属性意外突变)
如果还想为子组件添加验证:为子组件添加 prop 属性和 rules 属性即可。
<template>
<el-form-item
label="业务模块"
:prop="'formData.' + '.businessModule'"
:rules="{
required: true,
message: '请选择业务模块',
trigger: ['blur', 'change'],
}"
>
<el-select
v-model="formData.businessModule"
class="filter"
clearable
filterable
@change="chooseBusinessHandle"
>
<el-option
v-for="item in businessList"
:key="item.id"
:label="item.businessName"
:value="item.id"
/>
</el-select>
{{ formData }}
</el-form-item>
</template>
<script>
import { reactive, toRefs } from 'vue'
export default defineComponent({
props: {
childFormData: {
type: Object,
default() {
return {}
},
},
},
setup(props) {
// 视图数据
const viewsData = reactive({
formData: props.childFormData,
})
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// 视图操作
const viewsOperate = {
chooseBusinessHandle() {
viewsData.formData.companyShortName = 666
},
}
return {
...toRefs(viewsData), // 视图数据
...toRefs(viewsOperate), //视图操作
}
},
})
</script>
<style lang="scss" scoped>
.filter {
width: 100%;
}
</style>
效果
父组件点击确认的时候子组件也会跟着验证(实现),不需要通过emit告诉父组件去验证了
子组件值改变的时候 子组件会修改父组件传递过来的值,提示代码也看到了值的变动