无法在 Vue.js 中将对象 属性 设置为反应式

Can't set object property as reactive in Vue.js

我有一个文件 vue 组件和一个 属性 'todo-item' 这种结构

{
  id:1,
  text:'Buy tickets',
  isDone: false,
  person:'Boss',
  location:'Boryspil',
  childTask:null,
},

并且我计算了属性:

computed:{ 
  hasLocation(){
      return this.todoItem.location;
  },
  hasPerson(){
      return this.todoItem.person;
  },
  hasChildTask(){
      return this.todoItem.childTask;
  },
  hasParentTask(){
      return true;
  },
}

而且我想让所有对象属性都具有反应性,但是当我在方法中更改属性时:

deletePerson(){
  this.$set(this.todoItem, 'person', null);
  console.log(this.hasPerson);
  console.log(this.todoItem.person);
},

todoItem.person 仍然没有反应,this.hasPerson 有旧值,this.todoItemPerson 显示空值。 我试图让它们对 created 方法有反应,但它仍然没有反应。

这是按组件整体js代码,没有模板,简称css:

    <script>
    import HoveredChip from "@/components/HoveredChip";
    import {mapMutations} from 'vuex';
    export default {
        name: "TodoItem",
        components: {HoveredChip},
        props:['todo-item'],
        data() {
            return{
                isActive : true,
            }
        },
        computed:{

            hasLocation(){
                return this.todoItem.location;
            },
            hasPerson(){
                return this.todoItem.person;
            },
            hasChildTask(){
                return this.todoItem.childTask;
            },
            hasParentTask(){
                return true;
            },
            people(){
                return [
                    "dad",
                    "Ann",
                    "boss",
                    "prostitute"
                ]
            },
            places(){
                return []
            }
        },
        methods:{
            ...mapMutations(['addPersonMutation'],{

            }),
            moveToPerson(){

            },
            moveToLocation(){

            },
            moveToPatentTask(){

            },
            addLocation(){

            },
            addPerson(val){
                this.addPersonMutation(val);
                this.$set(this.todoItem,'person',val);
                console.log(this.hasPerson);
                console.log(this.todoItem.person);
            },

            addChildTask(){

            },
            deletePerson(){
                this.$set(this.todoItem, 'person', null);
                console.log(this.hasPerson);
                console.log(this.todoItem.person);
            },
            deleteLocation(){

            },
            deleteChildTask(){

            },
            editLocation(){

            },
            savePerson(){

            },
            editChildTask(){

            }

        },
        created(){
            // this.$set(this.todoItem, 'person', 'undefined');
            // this.$set(this.todoItem, 'location', '????');
            // this.$set(this.todoItem, 'isDone', "....");
        }
    }
</script>

问题出在您的 属性 名字上。将数据部分中的 'todo-item' 更改为 todoItem.

这个有效

<template>
    <div>
        <button @click.prevent="printPerson">Print Person</button>
        <br />
        <button @click.prevent="deletePerson">Delete Person</button>
    </div>
</template>

<script>
    export default {
        data: () => ({
            todoItem: {
                id: 1,
                text: 'Buy tickets',
                isDone: false,
                person: 'Boss',
                location: 'Boryspil',
                childTask: null,
            },

        }),
        computed: {
            hasLocation() {
                return this.todoItem.location;
            },
            hasPerson() {
                return this.todoItem.person;
            },
            hasChildTask() {
                return this.todoItem.childTask;
            },
            hasParentTask() {
                return true;
            },
        },

        methods: {
            deletePerson() {
                this.$set(this.todoItem, 'person', null);
                // this.todoItem.person = "null"
                console.log(this.hasPerson);
                console.log(this.todoItem.person);
            },
            printPerson() {
                console.log(this.hasPerson);
                console.log(this.todoItem.person);
            }
        }
    }
</script>

此外,使用“this.todoItem.person = null”也有效。

如果仍然不适合您,请编辑您的问题并添加完整的组件代码,我们可以提供帮助。

我的问题出在 props 上,我从父元素中获取了 todoItem,但我无法做到响应式,但是通过深入观察,所有对象属性都变成了响应式。 我解决了我的问题,只是将 watch 属性 添加到我的组件中:

现在,当我更改人(或任何其他人)时,我的 todoItem 属性 也会更改计算属性中的更新。

    watch:{
        todoItem:{
            deep: true,
            handler(){
                this.saveTodoAction(this.todoItem);
            }
        }
    },

这是完整的代码:

import HoveredChip from "@/components/HoveredChip";
import {mapMutations, mapActions} from 'vuex';
export default {
    name: "TodoItem",
    components: {HoveredChip},
    props:['todo-item'],
    data() {
        return{
            isActive : true,
        }
    },
    computed:{

        hasLocation(){
            return this.todoItem.location;
        },
        hasPerson(){
            return this.todoItem.person;
        },
        hasChildTask(){
            return this.todoItem.childTask;
        },
        hasParentTask(){
            return true;
        },
        people(){
            return [
                "Dad",
                "Ann",
                "Boss",
                "Prostitute"
            ]
        },
        places(){
            return []
        }
    },
    methods:{
        ...mapMutations(['addPersonMutation'],{

        }),
        ...mapActions(['saveTodoAction']),
        moveToPerson(){

        },
        moveToLocation(){

        },
        moveToPatentTask(){

        },
        addLocation(){

        },
        addPerson(val){
            this.addPersonMutation(val);
        },

        addChildTask(){

        },
        deletePerson(){
            this.todoItem.person = null;
        },
        deleteLocation(){

        },
        deleteChildTask(){

        },
        editLocation(){

        },
        savePerson(){

        },
        editChildTask(){

        },

    },
    watch:{
        todoItem:{
            deep: true,
            handler(){
                this.saveTodoAction(this.todoItem);
            }
        }
    },
    created(){
    }
}