简体   繁体   English

Vuejs 中的 State 突变

[英]State mutation in Vuejs

I am using vuetify with vuejs to add a sidebar to my web app using the <v-navigation-drawer> component.我正在使用带有vuejsvuetify使用<v-navigation-drawer>组件向我的 web 应用程序添加侧边栏。 Everything works as expected, however, when I click outside the sidebar component, I get a warning about mutating state (the drawer variable).一切都按预期工作,但是,当我在侧边栏组件外部单击时,我收到有关变异 state (抽屉变量)的警告。 The warning does not happen if I close the sidebar by using the button that I have added to it.如果我使用添加到侧边栏的按钮关闭侧边栏,则不会发生警告。 You can see the warning here: warning regarding state您可以在此处查看警告:关于 state的警告

You can see my code here:你可以在这里看到我的代码:

// sidebar.vue

<template>
  <v-navigation-drawer
    v-if="li"
    v-model="drawer"
    clipped="clipped"
    app
    height="100vh"
    floating
    disable-route-watcher
    fixed
    temporary
  >
    <v-list-item class="px-2">
      <v-list-item-avatar>
        <v-img src="/assets/logo.svg" contain alt="logo"></v-img>
        <!-- <v-icon>mdi-account</v-icon> -->
      </v-list-item-avatar>
      <v-list-item-title>{{ username }}</v-list-item-title>
      <v-btn icon @click.stop="toggleDrawer">
        <v-icon>mdi-chevron-left</v-icon>
      </v-btn>
    </v-list-item>
    <v-divider></v-divider>
    <v-list dense>
      <v-list-item
        v-for="item in items"
        :key="item.title"
        link
        @click="changeRoute(item.route)"
      >
        <v-list-item-icon>
          <v-icon>{{ item.icon }}</v-icon>
        </v-list-item-icon>
        <v-list-item-content>
          <v-list-item-title>{{ item.title }}</v-list-item-title>
        </v-list-item-content>
      </v-list-item>
    </v-list>
    <v-spacer></v-spacer>
    <v-list dense style="position: absolute; bottom: 0; width: 100%">
      <v-list-item @click="logout">
        <v-list-item-icon>
          <v-icon>mdi-logout-variant </v-icon>
        </v-list-item-icon>
        <v-list-item-content>
          <v-list-item-title>Sign out</v-list-item-title>
        </v-list-item-content>
      </v-list-item>
      <v-list-item @click="toggleDarkMode">
        <v-list-item-icon>
          <v-icon>mdi-theme-light-dark </v-icon>
        </v-list-item-icon>
        <v-list-item-content>
          <v-list-item-title>{{ darkModeButtonText }}</v-list-item-title>
        </v-list-item-content>
      </v-list-item>
    </v-list>
  </v-navigation-drawer>
</template>

<script lang="ts">
import { Vue, Component, Prop, Emit } from "vue-property-decorator";

@Component
export default class Sidebar extends Vue {
  @Prop() li!: boolean; // li = Logged In
  @Prop() username!: string;
  @Prop() darkModeButtonText!: string;
  @Prop() darkModeState!: boolean;
  @Prop() drawer!: boolean;
  @Prop() clipped!: boolean;

  @Emit("toggleDarkMode")
  toggleDarkMode() {
    return;
  }

  @Emit("logout")
  logout() {
    console.log(""); // method needs something in to avoid prettier rules, doesn't need to do anything, just emits
  }

  @Emit("toggleDrawer")
  toggleDrawer() {
    return;
  }

  changeRoute(newPath: string) {
    if (this.$route.path !== newPath) {
      this.$router.push(newPath);
    }
    return;
  }

  data() {
    return {
      items: [
        {
          title: "New Assessment",
          icon: "mdi-molecule-co2",
          route: "/assessment",
        },
        { title: "Home", icon: "mdi-home", route: "/landing" },
        { title: "About", icon: "mdi-information-outline", route: "/about" },
      ],
    };
  }
}
</script>

The drawer variables is defined in data() in the parent component of sidebar.vue and I'm using @Emit to change the variable state (the toggleDrawer() function).抽屉变量在sidebar.vue父组件的data()中定义,我使用@Emit更改变量 state( toggleDrawer()函数)。

Is there anything obviously wrong that I'm doing?我做的有什么明显的错误吗? I was following the examples HERE我在按照这里的例子

I should mention I'm new to vuejs and vuetify.我应该提到我是 vuejs 和 vuetify 的新手。

Thanks in advance.提前致谢。

The proper way to mutate parent data is to send it a message, letting the component that 'owns' the data mutate it.改变父数据的正确方法是向它发送一条消息,让“拥有”数据的组件改变它。 v-model is usually just sugar for :value and @input , so replace and forward. v-model通常只是:value@input的糖,所以替换和转发。

sidebar侧边栏

Add a prop to sidebar called drawer向侧边栏添加一个名为drawerprop

<v-navigation-drawer
    v-if="li"
    :value="drawer"
    @input="$emit('update:drawer', $event)"
props: {
  drawer:{}
}

parent父母

<sidebar :drawer='drawer' @update:drawer='drawer=$event' />
data() {
 return {
   drawer: false
 }
}

Other Options其他选项

You can also use a reactive store, such as Vuex to hold the value, and then your message and binding would be directed to the store instead of emitted to the parent.您还可以使用响应式存储,例如 Vuex 来保存值,然后您的消息和绑定将被定向到存储而不是发送到父级。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM