繁体   English   中英

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

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

我有以下组件:

家长:

<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>

孩子:

<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>

在父组件中,当调用login方法时, authenticated变量变为true 由于authenticated作为 prop 传递给 Child 组件,因此我希望 Child 在authenticated更改时会被刷新。 但是,Child 不会刷新。

我认为问题可能是由于我根本没有在孩子的模板中使用经过authenticated的事实引起的。 相反,我只在mounted的钩子中使用它。 就我而言,我没有使用模板中的authenticated

我尝试了两种解决方案:

  • 在 Parent 的login方法中调用this.$forceUpdate() - 这根本不起作用(没有改变)
  • :key添加到 Child,并在每次调用login时更改密钥 - 这可行,但是,它有点 hacky。 我想了解如何正确地做到这一点。

您不在模板中使用它很好,问题是您只检查子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>

暂无
暂无

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

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