Child 在 boolean 属性更改时不更新

Child is not updated when boolean prop is changed

我有以下组件:

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>

在parent组件中,调用login方法时,authenticated变量变为true。由于 authenticated 作为道具传递给 Child 组件,我希望 Child 在 authenticated 更改时刷新。但是,Child 不会刷新。

我认为问题可能是因为我根本没有在 child 的模板中使用 authenticated。相反,我只在 mounted 挂钩中使用它。就我而言,模板中的 authenticated 没用。

我尝试了两种解决方案:

你没有在模板中使用它很好,问题是你只在 child 的 mounted 挂钩中检查 authenticated,它只运行一次(当时是false)。

您应该使用 watch 来跟踪对 authenticated 属性的更改,而不是 mounted:

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

每次 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"
      });
    }
  }
}

你需要的是使用观察者。 实际上,您的代码只有 运行 一次(当安装 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>