Vuejs 3:将密钥注入到子组件中?

人气:933 发布:2022-10-16 标签: vuejs3

问题描述

版本:

VueJS: 3.x
Chrome: Version 93.0.4577.63 (Official Build) (x86_64)
macOS: Big Sur 11.5.2

我的用例必须是常见的,我对它不能开箱即用感到有点惊讶。

我有以下简单的路线:

/patients/new
/patients/1
/about

我通过vueJSrouter-links:

从单页面应用程序(SPA)访问
    <router-link to="/about">About</router-link> |
    <router-link to="/patients/new">New Patient</router-link> |
    <router-link to="/patients/1">Update Patient</router-link>

/patients/1返回一个预先填充的HTML表单,其中包含ID为1的患者的详细信息。 /patients/new返回相同的具有空白条目的HTML表单。

直观地说,如果我先访问/patients/1链接,然后再访问/patients/new,我会认为HTML表单是空的;相反,如果我先访问/patients/new,然后再访问/patients/1,我会希望相应地预先填充HTML表单。

这不是发生的事情。相反,SPA不会重新创建/重新装载该HTML表单。

解决方案:许多文章建议在HTML表单中使用由:key属性引用的反应变量。然后,无论我们访问哪个链接,只要我们更改了反应变量,就应该重新创建/重新挂载包含该HTML表单的vueJS组件。

我的方法是:provide根组件上的一个反应变量,inject它在呈现HTML表单的vueJS组件(即这里的Patient组件)中。

我的根组件如下所示:

<script lang="ts">
import { defineComponent } from 'vue'
import Vue from 'vue'

export default defineComponent({
  name: "App",
  provide() {
    return {
      routePath: Vue.computed(() => this.$route.path)
    }
  }
});
</script>
其中反应变量为routePath。然后,在Patient组件中,我有以下内容:

export default defineComponent({
  name: "Patient",
  inject: ['routePath'],
  ...
});

使用:key属性定义的HTML表单如下:

<template>
  <form :key="routePath">
    ...
  </form>
</template>

我认为这里的基本想法是合理的,但它不起作用,而且它确实看起来像是一种笨拙的方法。

所以,以下是我的问题:

这种方法合理吗? 为什么Vue.computed()调用中断?以下是Chrome控制台的堆栈跟踪:
App.vue?3acc:9 Uncaught TypeError: Cannot read properties of undefined (reading 'computed')
    at Proxy.provide (App.vue?3acc:9)
    at qe (runtime-core.esm-bundler.js:2463)
    at Pr (runtime-core.esm-bundler.js:6713)
    at Lr (runtime-core.esm-bundler.js:6632)
    at Tr (runtime-core.esm-bundler.js:6562)
    at D (runtime-core.esm-bundler.js:4421)
    at N (runtime-core.esm-bundler.js:4396)
    at m (runtime-core.esm-bundler.js:3991)
    at K (runtime-core.esm-bundler.js:5140)
    at mount (runtime-core.esm-bundler.js:3477)

感谢您的调查。

推荐答案

在vueJS 3.x中似乎未解决此问题。详情请参见open issue。有一些变通的办法。例如,参见this github project。在我的情况下,我已决定更改工作流以避免上述问题。

610