简体   繁体   English

更改 boolean 道具时不会更新子级

[英]Child is not updated when boolean prop is changed

I have the following components:我有以下组件:

Parent:家长:

<template>
    <Child path="instance.json" 
             v-bind:authenticated="authenticated" 
             v-bind:authenticator="authenticator" 
    />
</template>

<script>
import { getAuthenticator } from '../auth';
export default {
  data() {
    return {
      authenticated: false,
      authenticator: null
    };
  },
  beforeMount: async function () {
    this.authenticator = getAuthenticator()
    this.checkAccess();
  },
  methods: {
    checkAccess() {
      this.authenticated = this.authenticator.isAuthenticated();
    },
    async login() {
      this.checkAccess();
      await this.authenticator.signIn();
      this.checkAccess();
    }
  }
};
</script>

Child:孩子:

<template>
  <div id="swagger-ui"></div>
</template>

<script>
import swagger from "swagger-ui-dist";
import "swagger-ui-dist/swagger-ui.css";

export default {
  props: ["path", "authenticated", "authenticator"],
  mounted: async function() {
    if (this.authenticated) {
      let token = (await this.authenticator.getToken()).accessToken;

      const ui = swagger.SwaggerUIBundle({
        url: this.path,
        dom_id: "#swagger-ui",
        onComplete: function() {
          ui.preauthorizeApiKey("token", token);
        }
      });
    } else {
      const ui = swagger.SwaggerUIBundle({
        url: this.path,
        dom_id: "#swagger-ui"
      });
    }
  }
};
</script>

In the parent component, when the login method is called, the authenticated variable changes to true .在父组件中,当调用login方法时, authenticated变量变为true Since authenticated is passed as a prop to the Child component, I'd expect the Child to be refreshed whenever authenticated is changed.由于authenticated作为 prop 传递给 Child 组件,因此我希望 Child 在authenticated更改时会被刷新。 However, the Child does not refresh.但是,Child 不会刷新。

I think that the problem might be caused by the fact that I am not using authenticated in the template of the child at all.我认为问题可能是由于我根本没有在孩子的模板中使用经过authenticated的事实引起的。 Instead, I'm using it only in the mounted hook.相反,我只在mounted的钩子中使用它。 In my case, I have no use for authenticated in the template.就我而言,我没有使用模板中的authenticated

I tried two solutions:我尝试了两种解决方案:

  • calling this.$forceUpdate() in the login method of Parent - that didn't work at all (nothing changed)在 Parent 的login方法中调用this.$forceUpdate() - 这根本不起作用(没有改变)
  • Adding :key to the Child, and changing the key each time the login is called - this works, however, it's a bit hacky.:key添加到 Child,并在每次调用login时更改密钥 - 这可行,但是,它有点 hacky。 I'd like to understand how to do that properly.我想了解如何正确地做到这一点。

It's fine that you're not using it in the template, the issue is that you only check authenticated in the child's mounted hook, which only runs once (and is false at that time).您不在模板中使用它很好,问题是您只检查子mounted钩子中的authenticated ,该钩子只运行一次(当时是false的)。

You should use a watch to track changes to the authenticated prop instead of mounted :您应该使用watch来跟踪对经过authenticated的道具的更改,而不是mounted

watch: {
  authenticated: {
    handler(newValue, oldValue) {
      this.setUi();
    },
    immediate: true   // Run the watch when `authenticated` is first set, too
  }
}

That will call a setUi method every time authenticated changes:每次经过authenticated的更改都会调用setUi方法:

methods: {
  async setUi() {
    if (this.authenticated) {
      let token = (await this.authenticator.getToken()).accessToken;

      const ui = swagger.SwaggerUIBundle({
        url: this.path,
        dom_id: "#swagger-ui",
        onComplete: function() {
          ui.preauthorizeApiKey("token", token);
        }
      });
    } else {
      const ui = swagger.SwaggerUIBundle({
        url: this.path,
        dom_id: "#swagger-ui"
      });
    }
  }
}

what you need is to use a watcher.你需要的是使用观察者。 Actually, your code is only run once (when de component is mounted), not at each prop change.实际上,您的代码只运行一次(安装 de 组件时),而不是在每次 prop 更改时运行。

<template>
  <div id="swagger-ui"></div>
</template>

<script>
import swagger from 'swagger-ui-dist';
import 'swagger-ui-dist/swagger-ui.css';

export default {
  props: {
    path: {
      type: String,
      default: '',
    },
    authenticated: {
      type: Boolean,
      default: false,
    },
    authenticator: {
      type: Object,
      default: () => {},
    },
  },
  watch: {
    async authenticated(newValue) {
      await this.updateSwagger(newValue);
    },
  },
  async mounted() {
    await this.updateSwagger(this.authenticated);
  }
  methods: {
    async updateSwagger(authenticated) {
      if (authenticated) {
        const token = (await this.authenticator.getToken()).accessToken;

        const ui = swagger.SwaggerUIBundle({
          url: this.path,
          dom_id: '#swagger-ui',
          onComplete: function () {
            ui.preauthorizeApiKey('token', token);
          },
        });
      } else {
        const ui = swagger.SwaggerUIBundle({
          url: this.path,
          dom_id: '#swagger-ui',
        });
      }
    },
  },
};
</script>

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

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