Vuetify Navigation Drawer 工作一次然后停止
Vuetify Navigation Drawer works once then stops
我正在使用 Vuetify 导航抽屉。打开它的元素位于 header 中的单独组件 (v-toobar-side-icon) 中。我正在商店中存储抽屉的 open/close 状态。我正在使用计算方法来获取抽屉的状态。我不断收到错误消息
Computed property "drawerState" was assigned to but it has no setter.
我知道这是因为我必须使用 v-model
来控制抽屉的可见性。我不想使用计算 setter 来更改抽屉的状态,我想使用点击方法。
我尝试使用 :value
而不是 v-model
,但我也无法使其正常工作。我遇到的实际问题是导航抽屉控件 (open/close) 在主页上工作,但一旦我导航到另一个页面,它们就会停止工作。如果我导航回主页,它们仍然不起作用。吸气剂和 setters 正在改变状态并更新它们应该的方式,但是导航抽屉的 isActive
属性 保持 false
.
App.vue
<template lang="pug">
v-app
app-NavDrawer
app-header
router-view
v-footer(app dark)
span © 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)
}
}
});
如果您不想使用 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();
}
},
},
},
我能够通过将汉堡包图标 v-toolbar-side-icon
从页眉组件移动到导航抽屉组件来解决这个问题(尽管从技术上讲它是一种解决方法):
v-toolbar-side-icon(@click="drawer = !drawer")
v-navigation-drawer(v-model="drawer" dark fixed temporary width="350")
因为打开和关闭按钮现在在我可以使用的同一个组件中
@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();
}
}
发生的事情是,当我单击汉堡包时,导航抽屉将开始打开,然后立即关闭。我认为发生这种情况是因为一旦您单击汉堡包打开它就会改变状态,并且每次状态改变都会关闭抽屉。通过检查状态然后根据状态触发 openDrawer
或 closeDrawer
,一切都按预期工作。
谢谢你的建议 :value
更重要的是,指出我需要听听 @input
(我找到的关于 :value
的其他帖子没有提到这个.) 非常感谢!
如果有人正在寻找让 Vuetify 的导航抽屉与 Vuex 状态一起工作的方法 属性,我是这样处理这个案例的:避免无限循环导致应用程序崩溃的秘诀是拥有一个以计算的 属性 的 setter 方法为条件,它确保 $store.state
属性 仅在组件的 v-model
值与$store.state
.
computed: {
navigation: {
get () {
return this.$store.state.navigation
},
set (state) {
if (state !== this.$store.state.navigation) {
this.$store.dispatch('toggleNavigation')
}
}
}
},
我正在使用 Vuetify 导航抽屉。打开它的元素位于 header 中的单独组件 (v-toobar-side-icon) 中。我正在商店中存储抽屉的 open/close 状态。我正在使用计算方法来获取抽屉的状态。我不断收到错误消息
Computed property "drawerState" was assigned to but it has no setter.
我知道这是因为我必须使用 v-model
来控制抽屉的可见性。我不想使用计算 setter 来更改抽屉的状态,我想使用点击方法。
我尝试使用 :value
而不是 v-model
,但我也无法使其正常工作。我遇到的实际问题是导航抽屉控件 (open/close) 在主页上工作,但一旦我导航到另一个页面,它们就会停止工作。如果我导航回主页,它们仍然不起作用。吸气剂和 setters 正在改变状态并更新它们应该的方式,但是导航抽屉的 isActive
属性 保持 false
.
App.vue
<template lang="pug">
v-app
app-NavDrawer
app-header
router-view
v-footer(app dark)
span © 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)
}
}
});
如果您不想使用 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();
}
},
},
},
我能够通过将汉堡包图标 v-toolbar-side-icon
从页眉组件移动到导航抽屉组件来解决这个问题(尽管从技术上讲它是一种解决方法):
v-toolbar-side-icon(@click="drawer = !drawer")
v-navigation-drawer(v-model="drawer" dark fixed temporary width="350")
因为打开和关闭按钮现在在我可以使用的同一个组件中
@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();
}
}
发生的事情是,当我单击汉堡包时,导航抽屉将开始打开,然后立即关闭。我认为发生这种情况是因为一旦您单击汉堡包打开它就会改变状态,并且每次状态改变都会关闭抽屉。通过检查状态然后根据状态触发 openDrawer
或 closeDrawer
,一切都按预期工作。
谢谢你的建议 :value
更重要的是,指出我需要听听 @input
(我找到的关于 :value
的其他帖子没有提到这个.) 非常感谢!
如果有人正在寻找让 Vuetify 的导航抽屉与 Vuex 状态一起工作的方法 属性,我是这样处理这个案例的:避免无限循环导致应用程序崩溃的秘诀是拥有一个以计算的 属性 的 setter 方法为条件,它确保 $store.state
属性 仅在组件的 v-model
值与$store.state
.
computed: {
navigation: {
get () {
return this.$store.state.navigation
},
set (state) {
if (state !== this.$store.state.navigation) {
this.$store.dispatch('toggleNavigation')
}
}
}
},