解决方法避免直接更改道具,因为值将被覆盖

时间:2020-05-25 19:59:47

标签: vue.js

我看到了很多问题和答案,但是它们并不能解决我的问题,我只是想显示/隐藏,当我单击父组件菜单按钮时,抽屉应该在第一次加载后就打开了很好,但是当我关闭它时,它向我显示此错误。我只想在道具中传递真假

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "drawer"

这就是我想做的。

在父母中

<template>
    <div @click="drawer = true" class="hamburger">
       <span></span>
       <span></span>
       <span></span>
    </div>

   <mobile-drawer-menu :drawer="drawer"/>
</template>

<script>
   import MobileDrawerMenu from "./MobileDrawerMenu";

   export default {
     components : {
        MobileDrawerMenu
    },

     data() {
        return {
            drawer : false,
        }
     },

   }
</script>

在孩子中

<template>
    <div v-if="drawer" class="fixed top-0 left-0 z-200">
        <div @click="drawer = false" class="overlay"></div>
        <div class="drawer-wrapper">
            <div class="drawer-close">
               <div class="flex items-center justify-end">
                  <svg @click="drawer = false"></svg>
               </div>
            </div>
        </div>
    </div>                     
</template>

<script>
   export default {
      name: "MobileDrawerMenu",
      props : {
        drawer : {
            type : Boolean,
            required : true
        }
     },
   }
</script>

2 个答案:

答案 0 :(得分:2)

您可以使用.sync modifier,并用$emit更新道具:

<template>
    <div @click="drawer = true" class="hamburger">
       <span></span>
       <span></span>
       <span></span>
    </div>

   <mobile-drawer-menu :drawer.sync="drawer"/>
</template>

<script>
   import MobileDrawerMenu from "./MobileDrawerMenu";

   export default {
     components : {
        MobileDrawerMenu
    },

     data() {
        return {
            drawer : false,
        }
     },

   }
</script>

孩子

<template>
    <div v-if="drawer" class="fixed top-0 left-0 z-200">
        <div @click="$emit('update:drawer', false)" class="overlay"></div>
        <div class="drawer-wrapper">
            <div class="drawer-close">
               <div class="flex items-center justify-end">
                  <svg @click="$emit('update:drawer', false)"></svg>
               </div>
            </div>
        </div>
    </div>                     
</template>

<script>
   export default {
      name: "MobileDrawerMenu",
      props : {
        drawer : {
            type : Boolean,
            required : true
        }
     },
   }
</script>

JsFiddle:https://jsfiddle.net/hansfelix50/176oba9n/

答案 1 :(得分:1)

您不应在子组件中更改道具。您可以发出事件并在父控制器中关闭,也可以仅使drawer仅在子组件中并使用ref通过功能切换打开:

父母:

<template>
    <div @click="open" class="hamburger">
       <span></span>
       <span></span>
       <span></span>
    </div>

   <mobile-drawer-menu ref="modal"/>
</template>

<script>
    import MobileDrawerMenu from "./MobileDrawerMenu";

    export default {
        components : {
            MobileDrawerMenu
        },
        methods: {
            open() {
                this.$refs.modal.open();
            }
        },
    }
</script>

孩子:

<template>
    <div v-if="drawer" class="fixed top-0 left-0 z-200">
        <div @click="close" class="overlay"></div>
        <div class="drawer-wrapper">
            <div class="drawer-close">
               <div class="flex items-center justify-end">
                  <svg @click="close"></svg>
               </div>
            </div>
        </div>
    </div>                     
</template>

<script>
    export default {
        name: "MobileDrawerMenu",
        data: () => ({
            drawer: false
        }),
        methods: {
            open() {
                this.drawer = true;
            },
            close() {
                this.drawer = false;
            }
        }
    }
</script>

如您所见,您可以使用ref访问子方法(和状态值)。 有关参考文献here的更多信息。 您也可以使用“发射”来执行此操作,如果需要在父组件中保留drawer属性,则可以阅读here