Vuetify 导航抽屉工作一次然后停止

Posted

技术标签:

【中文标题】Vuetify 导航抽屉工作一次然后停止【英文标题】:Vuetify Navigation Drawer works once then stops 【发布时间】:2018-07-01 12:17:41 【问题描述】:

我正在使用 Vuetify 导航抽屉。打开它的元素位于标题中的单独组件(v-toobar-side-icon)中。我正在商店中存储抽屉的打开/关闭状态。我正在使用计算方法来获取抽屉的状态。我不断收到错误消息

Computed property "drawerState" was assigned to but it has no setter.

我知道这是因为我必须使用v-model 来控制抽屉的可见性。我不想使用计算的 setter 来更改抽屉的状态,我想使用 click 方法。

我尝试使用:value 而不是v-model,但我也无法让它正常工作。我遇到的实际问题是导航抽屉控件(打开/关闭)在主页上工作,但是一旦我导航到另一个页面,它们就会停止工作。如果我导航回主页,它们仍然不起作用。 getter 和 setter 正在更改状态并更新它们应有的方式,但导航抽屉的 isActive 属性保持为 false

App.vue

<template lang="pug">
  v-app
    app-NavDrawer
    app-header
    router-view
    v-footer(app dark)
      span &copy; 2018 #[a(href="http://www.smellydogcoding.com") Smellydog Coding]
</template>

<script>
  import Header from './components/header/Header.vue'
  import NavDrawer from './components/header/NavDrawer.vue'
  export default 
    data () 
      return 

      
    ,
    components: 
      appHeader: Header,
      appNavDrawer: NavDrawer
    
  
</script>

<style>
html 
  overflow-y: auto;

a 
  text-decoration: none;

 footer 
   color: white;
 
</style>

Header.vue

<template lang="pug">
  v-toolbar.mt-0(dark)
    v-toolbar-side-icon(@click.stop="openDrawer")
    router-link(to="/" tag="v-toolbar-title") Pool Math
</template>

<script>

export default 
  methods: 
    openDrawer() 
      this.$store.dispatch('navDrawer','open');
    
  

</script>

<style scoped>
  .toolbar__title 
    cursor: pointer;
  
</style>

NavDrawer.vue

<template lang="pug">
  v-navigation-drawer(v-model="drawerState" dark fixed temporary)
    v-list.pa-1
      v-list-tile(avatar tag="div")
        v-list-tile-avatar
          img(src="../../../public/v.png")
        v-list-tile-content
          v-list-tile-title Guest
        v-list-tile-action
          v-btn(icon @click.stop="closeDrawer")
            v-icon close
    v-list.pt-0(dense)
      v-divider(light)
      router-link(to="/s1p0" tag="v-list-tile" active-class="active").expansion-panel__header.how-to
        v-list-tile-content
          v-list-tile-title.text-xs-center How to Use This Website
      v-expansion-panel
        v-expansion-panel-content
          div(slot="header") Section 1 - Conversions
          router-link(to="/s1p0" tag="v-list-tile" active-class="active")
            v-list-tile-content
              v-list-tile-title 1.0 - Useful Conversions
          router-link(to="/s1p1" tag="v-list-tile" active-class="active")
            v-list-tile-content
              v-list-tile-title 1.1 - Convert ounces to pounds
          router-link(to="/s1p2" tag="v-list-tile" active-class="active")
            v-list-tile-content
              v-list-tile-title 1.2 - Convert fluid ounces to gallons
          router-link(to="/s1p3" tag="v-list-tile" active-class="active")
            v-list-tile-content
              v-list-tile-title 1.3 - Convert fluid ounces to cups
          router-link(to="/s1p4" tag="v-list-tile" active-class="active")
            v-list-tile-content
              v-list-tile-title 1.4 - Convert inches to feet
        v-expansion-panel-content
          div(slot="header") Section 2 - Area and Volume
          router-link(to="/s2p0" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 2.0 - Introduction to This Section
          router-link(to="/s2p1" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 2.1 - Area of a Swimming Pool
          router-link(to="/s2p2" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 2.2 - Area of a Hot Tub
          router-link(to="/s2p3" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 2.3 - Volume of Water in a Swimming Pool
          router-link(to="/s2p4" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 2.4 - Volume of Water in a Multi-Depth Pool
          router-link(to="/s2p5" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 2.5 - Volume of Water in a Hot Tub
          router-link(to="/s2p6" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 2.6 - Volume of Water in a Hot Tub with Seats
          router-link(to="/s2p7" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 2.7 - Volume of Water Loss in a Swimming Pool
          router-link(to="/s2p8" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 2.8 - Volume of Water Loss in a Hot Tub
        v-expansion-panel-content
          div(slot="header") Section 3 - Water Balance
          router-link(to="/s3p0" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 3.0 - Introduction to This Section
          router-link(to="/s3p1" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 3.1 - Calculate Saturation Index
          router-link(to="/s3p2" tag="v-list-tile" active-class="active")
            v-list-tile-content
                v-list-tile-title 3.2 - Calculate Saturation Index - With CA
</template>

<script>
export default 
  computed: 
    drawerState() 
      return this.$store.getters.navDrawer; 
    
  ,
  methods: 
    closeDrawer()  this.$store.dispatch('navDrawer','close')
  

</script>

<style scoped>
  aside 
    overflow-y: auto;
  
  .navigation-drawer 
    padding: 0 0 1.0rem;
  
  .how-to 
    border-bottom: 1px solid rgba(255,255,255,0.12);
  
  .how-to .list__tile__title 
    font-size: 1.15rem;
  
</style>

store.js

import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios';

Vue.use(Vuex);

export const store = new Vuex.Store(
  state: 
    drawer: false
  ,
  getters:   // send state to a component
    navDrawer: state => 
      return state.drawer
    
  ,
  mutations:  // modify state synchronously
    navDrawer: (state, command) => 
      command === 'open' ? state.drawer = true : state.drawer = false;
    
  ,
  actions:  // modify state aschronously
    navDrawer: (commit, command) => 
      commit('navDrawer', command)
    
  
);

【问题讨论】:

【参考方案1】:

如果您不想使用v-model,您可以通过:value 属性将其替换为值的绑定,如您所说。但是如果你这样做了,你将不得不监听 @input 事件,当值改变时引发。

在我看来,您将能够通过将 v-model 替换为 :value="drawerState" 并将新方法 updateDrawerState 绑定到 @input 事件来实现您想要做的事情。

您的 NavDrawer.vue 将以

开头
<template lang="pug">
  v-navigation-drawer(:value="drawerState" @input="updateDrawerState" dark fixed temporary)

你必须在同一个组件中添加这个方法:

updateDrawerState(state) 
  if (state) 
    this.closeDrawer();
  

仅供参考:您可以通过向您的计算中添加一个 setter 来实现几乎相同的事情:

computed: 
    drawerState: 
      get() 
        return this.$store.getters.navDrawer; 
      ,
      set(state) 
        if (state) 
          this.closeDrawer();
        
      ,
    ,
,

【讨论】:

也许不是全部真相。我有 :value="drawerState" 并且没有 @click 事件。【参考方案2】:

如果有人正在寻找一种方法来让 Vuetify 的 Navigation Drawer 与 Vuex 状态属性一起工作,这就是我处理此案例的方法:避免导致应用程序崩溃的无限循环的秘诀是在 setter 方法上设置条件计算属性,它确保只有在组件的 v-model 值与 $store.state 中的值不同时才会更改 $store.state 属性。

  computed: 
    navigation: 
      get () 
        return this.$store.state.navigation
      ,
      set (state) 
        if (state !== this.$store.state.navigation) 
          this.$store.dispatch('toggleNavigation')
        
      
    
  ,

【讨论】:

【参考方案3】:

我能够通过将汉堡图标 v-toolbar-side-icon 从标题组件移动到导航抽屉组件来解决这个问题(尽管从技术上讲,这是一种解决方法):

v-toolbar-side-icon(@click="drawer = !drawer") v-navigation-drawer(v-model="drawer" dark fixed temporary )

因为打开和关闭按钮现在位于我可以使用的同一个组件中

@click="drawer = !drawer"

切换导航抽屉的可见性。

托马斯·费罗:

我确实尝试了您的解决方案,并且只需稍作修改就可以很好地工作:

methods: 
    updateDrawerState(state) 
      if (!state)  this.closeDrawer(); 
      else  this.openDrawer(); 
      console.log(state)
    ,
    openDrawer()  this.$store.dispatch('navDrawer','open') ,
    closeDrawer()  this.$store.dispatch('navDrawer','close') 
  

当我尝试使用时

updateDrawerState(state) 
  if (state) 
    this.closeDrawer();
  

发生的情况是,当我单击汉堡时,导航抽屉将开始打开,然后立即关闭。我认为这是因为一旦你点击汉堡打开它就会改变状态并且每次状态改变都会关闭抽屉。通过检查状态,然后根据状态触发 openDrawercloseDrawer,一切都按预期工作。

感谢您对:value 的建议和更多的点,指出我需要听@input(我发现的关于:value 的其他帖子没有提到这一点。)非常感谢!

【讨论】:

以上是关于Vuetify 导航抽屉工作一次然后停止的主要内容,如果未能解决你的问题,请参考以下文章

Vuetify 导航抽屉开始关闭,然后一秒钟后打开

Vuetify 导航抽屉拖动以调整大小

Vuetify 导航抽屉问题

导航抽屉遮挡了 Vuetify 工具栏

Vuetify 2 个工具栏和 1 个导航抽屉,导航抽屉上方有 1 个工具栏

如何使用 Vuetify 的组件“导航抽屉”重现此导航?