javascript 为什么Vue3中的组件标签不能正常工作以动态呈现组件?

gwbalxhn  于 2023-03-28  发布在  Java
关注(0)|答案(4)|浏览(237)

我刚开始学习Vue,并尝试使用组件标签学习动态渲染。这段代码有什么问题吗?控制台中没有显示错误,但点击按钮仍然没有显示所需的组件。它确实可以使用v-if,但我下面这节课的重点是使用组件动态渲染。这不起作用:

<template>
  <div>
    <the-header></the-header>
    <button @click="setSelectedComponent('active-goals')">Active goals</button>
    <button @click="setSelectedComponent('manage-goals')">Manage goals</button>
    <component :is="selectedTab"></component>
  </div>
</template>

<script setup>
/* eslint-disable no-unused-vars */
import { ref, defineExpose, defineComponent } from 'vue';
import TheHeader from './components/TheHeader.vue';
import ActiveGoals from './components/ActiveGoals.vue';
import ManageGoals from './components/ManageGoals.vue';

const selectedTab = ref('active-goals');
const setSelectedComponent = (tab) => {
  selectedTab.value = tab;
};

defineExpose({
  selectedTab,
  setSelectedComponent,
});

defineComponent({
  components: {
    TheHeader,
    ActiveGoals,
    ManageGoals,
  },
});
</script>

<style>
html {
  font-family: sans-serif;
}

body {
  margin: 0;
}
</style>

谢谢你的帮助!

fcg9iug3

fcg9iug31#

如果组件未注册,则不能在:is中使用字符串。
您可以使用组件本身而不是字符串(@Tolbxela或@Bussadjra的答案),或者注册组件。
而且你不能在<script setup>中注册这些组件(很容易),因为<script setup>的语法是有限的。它实际上是一个要写的宏:

<script>
import { defineComponent } from 'vue'
export default defineComponent({
  setup() {
    // CODE HERE
  }
})

如:

<script setup>
// CODE HERE
</script>

...一些mods允许import的内部setup()功能和一些其他的好东西(definePropsdefineEmits,等等...).
限制应该是显而易见的:如果你需要defineComponent()中的setup()函数的内容之外的任何东西,你想使用一个普通的<script>
换句话说,<script setup>应该被看作是一个减少样板文件的工具,你不应该尝试用它来编写所有的组件。
最后,<script setup>可以和普通的<script>标签一起使用。在您的例子中:

<script setup>
const selectedTab = ref('active-goals');
const setSelectedComponent = (tab) => {
  selectedTab.value = tab;
};
</script>

<script>
import { defineComponent } from 'vue'
import TheHeader from './components/TheHeader.vue';
import ActiveGoals from './components/ActiveGoals.vue';
import ManageGoals from './components/ManageGoals.vue';
export default defineComponent({
  components: {
    TheHeader,
    ActiveGoals,
    ManageGoals,
  },
});
</script>

普通的<script>注册组件,因此<template>可以将字符串转换为实际的组件。

zed5wv10

zed5wv102#

在脚本设置中,导入的组件被视为变量,因为它们不像我们在非脚本设置语法中的components选项中那样在键下注册,因此您可以将它们Map到对象内部的键:

<template>
  <div>
    <the-header></the-header>
    <button @click="setSelectedComponent('ActiveGoals')">Active goals</button>
    <button @click="setSelectedComponent('ManageGoals')">Manage goals</button>
    <component :is="selectedTab"></component>
  </div>
</template>

<script setup>
/* eslint-disable no-unused-vars */
import { ref, defineExpose, defineComponent } from 'vue';
import TheHeader from './components/TheHeader.vue';
import ActiveGoals from './components/ActiveGoals.vue';
import ManageGoals from './components/ManageGoals.vue';

const selectedTab = ref(ActiveGoals);
 const components = {
    ActiveGoals,
    ManageGoals,
  }
const setSelectedComponent = (tab) => {
  selectedTab.value = components[tab];
};

defineExpose({
  selectedTab,
  setSelectedComponent,
});


</script>
n9vozmp4

n9vozmp43#

要做到这一点,你可以全局注册你的组件,让Vue与你选择的组件建立链接。否则,你可以使用Vue的defineAsync方法。
注册全球
定义异步
1:您的.vue

<template>
  <div>
    <the-header></the-header>
    <button @click="setSelectedComponent(ActiveGoals)">Active goals</button>
    <button @click="setSelectedComponent(ManageGoals)">Manage goals</button>
    <component :is="selectedTab"></component>
  </div>
</template>

<script setup>
/* eslint-disable no-unused-vars */
import { ref, defineExpose, defineComponent } from 'vue';
import TheHeader from './components/TheHeader.vue';

const selectedTab = ref('active-goals');
const setSelectedComponent = (tab) => {
  selectedTab.value = tab;
};

defineExpose({
  selectedTab,
  setSelectedComponent,
});

defineComponent({
  components: {
    TheHeader,
  },
});
</script>

在你的主

import { createApp } from 'vue';
import App from './App.vue';
import ActiveGoals from './components/ActiveGoals.vue';
import ManageGoals from './components/ManageGoals.vue';

const app = createApp(App);
app.component('active-goals', ActiveGoals)
app.component('manage-goals', ManageGoals)
app.mount('#app');

2:你的.vue

<template>
  <div>
    <the-header></the-header>
    <button @click="setSelectedComponent('active-goals')">Active goals</button>
    <button @click="setSelectedComponent('manage-goals')">Manage goals</button>
    <component :is="selectedTab"></component>
  </div>
</template>

<script setup>
/* eslint-disable no-unused-vars */
import { ref, defineExpose, defineComponent } from 'vue';
import TheHeader from './components/TheHeader.vue';
import { defineAsyncComponent } from 'vue'

const ActiveGoals = defineAsyncComponent(() =>
  import('./components/ActiveGoals.vue')
)
const ManageGoals = defineAsyncComponent(() =>
  import('./components/ManageGoals.vue')
)

const selectedTab = ref(ActiveGoals);
const setSelectedComponent = (tab) => {
  selectedTab.value = tab;
};

defineExpose({
  selectedTab,
  setSelectedComponent,
});

defineComponent({
  components: {
    TheHeader,
  },
});
</script>
t5zmwmid

t5zmwmid4#

更新2

Playground与道的解决方案

更新

回答道:
要使<component :is="">能够处理字符串,必须使用名称注册组件。
在这种情况下,您不需要defineComponent
检查Dynamic Components中标签的原始Vue溶液
用你的代码工作Playground
下面是你的固定代码:

<script setup>
/* eslint-disable no-unused-vars */
import { ref, defineExpose, defineComponent } from 'vue';
import TheHeader from './TheHeader.vue';
import ActiveGoals from './ActiveGoals.vue';
import ManageGoals from './ManageGoals.vue';

const selectedTab = ref('active-goals');
const setSelectedComponent = (tab) => {
  selectedTab.value = tab;
};

const tabs = {
  'active-goals': ActiveGoals,
  'manage-goals': ManageGoals
}

</script>

<template>
    <the-header></the-header>
    selectedTab: {{selectedTab}}<br/>
    <button @click="setSelectedComponent('active-goals')">Active goals</button>&nbsp;
    <button @click="setSelectedComponent('manage-goals')">Manage goals</button>&nbsp;
    <hr/>
    <component :is="tabs[selectedTab]"></component>
</template>

相关问题