30

I am using the experimental script setup to create a learn enviroment. I got a selfmade navigation bar with open a single component.

I am having trouble using the <component :is="" /> method. This method is described in the docs under component basics -> dynamic-components

In the Vue 3 Composition API, it works as expected:

<template>
  <NavigationBar
    @switchTab="changeTab"
    :activeTab="tab"
  />
  <component :is="tab" />
</template>

<script>
import { ref } from 'vue'
import NavigationBar from './components/NavigationBar.vue'
import TemplateSyntax from './components/TemplateSyntax.vue'
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'

export default {
  components: {
    NavigationBar,
    TemplateSyntax,
    DataPropsAndMethods
  },
  setup () {
    const tab = ref('DataPropsAndMethods')
    function changeTab (newTab) {
      tab.value = newTab
    }

    return {
      changeTab,
      tab
    }
  }
}
</script>

My approach with the script setup fails:

<template>
  <NavigationBar
    @switchTab="changeTab"
    :activeTab="tab"
  />
  <component :is="tab" />
</template>

<script setup>
import NavigationBar from './components/NavigationBar.vue'
import TemplateSyntax from './components/TemplateSyntax.vue'
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref } from 'vue'

const tab = ref('DataPropsAndMethods')
function changeTab (newTab) {
  tab.value = newTab
}
</script>

do you got any idea how to solve this with the script setup method?

1
  • import {defineAsyncComponent} from "vue" <component :is="defineAsyncComponent(()=>import(../components/${yourComponent}))"></component> Commented Jul 3, 2023 at 15:18

2 Answers 2

27

It seems with <script setup>, tab needs to reference the component definition itself instead of the component name.

To reference the component definition, which does not need reactivity, use markRaw() before setting tab.value:

<script setup>
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref, markRaw } from 'vue'

const tab = ref(null)

changeTab(DataPropsAndMethods)

// newTab: component definition (not a string)
function changeTab (newTab) {
  tab.value = markRaw(newTab)
}
</script>

demo 1

If you need to pass the component name to changeTab(), you could use a lookup:

<script setup>
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref, markRaw } from 'vue'

const tab = ref(null)

changeTab('DataPropsAndMethods')

// newTab: component name (string)
function changeTab (newTab) {
  const lookup = {
    DataPropsAndMethods,
    /* ...other component definitions */
  }
  tab.value = markRaw(lookup[newTab])
}
</script>

demo 2

Tested with Vue 3.0.9 setup with Vue CLI 5.0.0-alpha.8

Sign up to request clarification or add additional context in comments.

Comments

3

My approach :

<template>
  <NavigationBar
    @switchTab="changeTab"
    :activeTab="tab"
  />
  <component :is="activeTab" />
</template>

<script setup lang="ts">
import NavigationBar from './components/NavigationBar.vue'
import TemplateSyntax from './components/TemplateSyntax.vue'
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref , computed} from 'vue'


const tab = ref('DataPropsAndMethods')
const activeTab=computed(()=>({
    NavigationBar,
    TemplateSyntax,
    DataPropsAndMethods
}[tab.value]))


function changeTab (newTab) {
  tab.value = newTab
}
</script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.