【问题标题】:How correctly to set two navigation drawer of Vuetify framework?如何正确设置 Vuetify 框架的两个导航抽屉?
【发布时间】:2020-03-27 11:38:45
【问题描述】:

在我的Vue.JS 应用程序中,我尝试使用Vuetify 框架中的两个v-navigation-drawer。出于某种原因,我的下一个代码引发了错误。就我而言,每个侧边栏都在一个单独的组件中。如何解决此类错误?

错误:

vue.esm.js?efeb:628 [Vue 警告]:避免直接改变 prop,因为 每当父组件时,该值将被覆盖 重新渲染。相反,使用基于 道具的价值。正在变异的道具:“打开”

BaseLayout.vue:

<template>
  <div>
    <v-app-bar app>
      <v-btn
        icon
        @click.stop="openLeftNavigationDrawer=!openLeftNavigationDrawer">
        <v-icon>mdi-map-clock-outline</v-icon>
      </v-btn>

      <v-spacer></v-spacer>

      <v-btn
        icon
        @click.stop="openRightNavigationDrawer=!openRightNavigationDrawer">
        <v-icon>mdi-filter</v-icon>
      </v-btn>
    </v-app-bar>

    <left-navigation-drawer
      :open="openLeftNavigationDrawer">
    </left-navigation-drawer>

    <right-navigation-drawer
      :open="openRightNavigationDrawer">
    </right-navigation-drawer>

    <v-content style="padding:unset!important;">
      <slot></slot>
    </v-content>
  </div>
</template>

<script>
import LeftNavigationDrawer from '../elements/LeftNavigationDrawer'
import RightNavigationDrawer from '../elements/RightNavigationDrawer'

export default {
  name: 'BaseLayout',
  components: {
    LeftNavigationDrawer,
    RightNavigationDrawer
  },
  data: function () {
    return {
      openLeftNavigationDrawer: false,
      openRightNavigationDrawer: false
    }
  }
}
</script>

LeftNavigationDrawer.vue:

<template>
  <v-navigation-drawer
    v-model="open"
    absolute
    left>
  </v-navigation-drawer>
</template>

<script>
export default {
  name: 'LeftNavigationDrawer',
  props: {
    open: false
  }
}
</script>

RightNavigationDrawer.vue:

<template>
  <v-navigation-drawer
    v-model="open"
    absolute
    right>
  </v-navigation-drawer>
</template>

<script>
export default {
  name: 'RightNavigationDrawer',
  props: {
    open: false
  }
}
</script>

【问题讨论】:

    标签: javascript vue.js vue-component vuetify.js vue-props


    【解决方案1】:

    在你LeftNavigationDrawerRightNavigationDrawer组件中,当你写v-model="open"时,它允许v-navigation-drawer组件改变open的值。

    但是,在 VueJS 中,一个组件是不允许改变它的 props 值的。只有父母才能做到这一点。因为open 是一个道具,而v-navigation-bar 正在尝试更改它,所以您会看到错误Avoid mutating a prop...

    为了修复它,您可以在发送到v-navigation-drawer 的组件中定义data。像这样的:

    // RightNavigationDrawer.vue/LeftNavigationDrawer
    <template>
      <v-navigation-drawer
        v-model="drawerOpen"
        @input="onInput"
        absolute
        right>
      </v-navigation-drawer>
    </template>
    
    <script>
    export default {
      name: 'RightNavigationDrawer',
      props: {
        open: {
           type: Boolean,
           default: false
        }
    
      },
     data(){
       return {
          drawerOpen: this.open
       }
     },
     watch:{
       open(newVal){
          this.drawerOpen = newVal
       }
     },
     methods:{
       onInput(isOpen){
          this.$emit('drawerOpened', isOpen)
       }
     }
    }
    </script>
    
    • 数据drawerOpen存储了Vuetify的v-navigation-drawer是否打开。
    • open 的监视允许您在 open 属性更改时更改抽屉状态(父子通信)
    • @input 处理程序允许您将新抽屉状态发送到父组件(子到父通信)

    对左右导航抽屉组件进行更改后,您的BaseLayout.vue 将需要监听drawerOpened 事件。

    // BaseLayout.vue
    <template>
      <div>
        <v-app-bar app>
          <v-btn
            icon
            @click.stop="openLeftNavigationDrawer=!openLeftNavigationDrawer">
            <v-icon>mdi-map-clock-outline</v-icon>
          </v-btn>
    
          <v-spacer></v-spacer>
    
          <v-btn
            icon
            @click.stop="openRightNavigationDrawer=!openRightNavigationDrawer">
            <v-icon>mdi-filter</v-icon>
          </v-btn>
        </v-app-bar>
    
        <left-navigation-drawer
          :open="openLeftNavigationDrawer"
          @drawer-opened="handleDrawerChange("left", $event)"   // Add these event handlers
        >
        </left-navigation-drawer>
    
        <right-navigation-drawer
          :open="openRightNavigationDrawer"
          @drawer-opened="handleDrawerChange("right", $event)"
        >
        </right-navigation-drawer>
    
        <v-content style="padding:unset!important;">
          <slot></slot>
        </v-content>
      </div>
    </template>
    
    <script>
    import LeftNavigationDrawer from '../elements/LeftNavigationDrawer'
    import RightNavigationDrawer from '../elements/RightNavigationDrawer'
    
    export default {
      name: 'BaseLayout',
      components: {
        LeftNavigationDrawer,
        RightNavigationDrawer
      },
      data: function () {
        return {
          openLeftNavigationDrawer: false,
          openRightNavigationDrawer: false
        }
      },
      methods:{
        handleDrawerChange(type, isOpen){
           if(type === "left"){
              this.openLeftNavigationDrawer = isOpen
           }else{
              this.openRightNavigationDrawer = isOpen
           }
        }
    
      }
    }
    </script>
    
    
    • 在您的 HTML 中,您侦听 drawer-opened 事件。
    • 在事件处理程序中,您传递 2 个参数:一个是抽屉是左还是右。另一个参数是从组件接收到的值。
    • 根据抽屉是左还是右,更改BaseLayout.vue中相应数据的值

    【讨论】:

    • 感谢您的回答!我注意到小 (600px &gt; &lt; 960px) 屏幕设备的奇怪行为。假设我打开右侧导航抽屉,然后单击需要打开左侧导航抽屉的左侧按钮。在这种情况下,右侧导航抽屉关闭,左侧导航抽屉打开。在这种情况下,openRightNavigationDrawer 变量的值没有改变。我需要在小屏幕设备中更改该值。你对这种行为有什么想法吗?
    • 我不知道为什么,但是handleDrawerChange 方法永远不会被调用。
    • @NurzhanNogerbek 我无法重现您的场景。这是一个带有您的代码的代码框:codesandbox.io/s/vue-4f24x。在这个handleDrawerChange 被调用。你能分叉这个并尝试重现你的问题吗?
    • 另外,请考虑通过单击tick 图标来接受我的回答,以帮助社区中的其他开发人员
    • 另外,请注意您不需要 2 个抽屉。您可以只创建一个抽屉(NavigationDrawer)并将 right 属性设置为正确的导航抽屉。更好的是直接在BaseLayout.vue 中使用v-navigation-drawer,并且没有额外的抽屉组件。
    猜你喜欢
    • 2019-01-09
    • 2019-06-05
    • 2019-09-07
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 2020-03-29
    • 2021-12-14
    • 2020-06-19
    相关资源
    最近更新 更多