1

I created a vuejs3 single page application "WITHOUT" router and routing and also without "url" change ( want to always showing home in address bar) But need help to do it in a correct way.

I want to

  1. have a main html page on page have links, buttons or so, that at run time page is filed (how???)
  2. on start page be filled with the first home page
  3. on click of each link or buttons the selected component to be replace in the page

index.html page:

 <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <link rel="icon" type="image/svg+xml" href="/vite.svg" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Vite + Vue</title>
      </head>
      <body>
        <div id="app"></div>
        <script type="module" src="/src/main.js"></script>
      </body>
    </html>
main.js
import { createApp } from 'vue'
    import App    from './App.vue'
    import store  from './store'
    import './style.css'
    const app = createApp(App)
    app.use(store)
    app.mount('#app')

app.vue file

 <template>
        <div>
            <h1>Hello world</h1>
            <button type="button" @click="changeView(0)"> Home 1 </button>
            <button type="button" @click="changeView(1)"> Home 2 </button>
            <button type="button" @click="changeView(2)"> Home 3 </button>
        </div>
        <Suspense v-if="isLoggedIn">
            <template #default>
                <changeViews />
            </template>
            <template #fallback>
                <p>loading...</p>
            </template> 
        </Suspense>
        <changeViews v-if="showIt" />
    </template>
    <script setup>
        import { defineAsyncComponent, ref, markRaw } from 'vue'
        const menus = [
            {
                name: "home"
                ,url: "home"
            },
            {
                name: "about"
                ,url: "about"
            },
            {
                name: "contact"
                ,url: "contact"
            },
        ]
        let showIt = ref(false)
        let changeViews = ref(null)
        changeViews.value = markRaw(defineAsyncComponent((loc) => 
            import(`./components/${menus[0].url}/index.vue`)
        ))
        function changeView(ja){
            showIt.value = false
            if(ja===1) {
                showIt.value = true
                changeViews.value = defineAsyncComponent((loc) => 
                    import(`./components/${menus[ja].url}/index.vue`)
                )
            }
        }
    </script>

Pages (home, about, contact) are very simple:

<template>
        <h2> Home </h2>
        <div class="card">
            <button type="button" @click="count++">count is {{ count }}</button>
            <button type="button" @click="count++">count is {{ count }}</button>
            <button type="button" @click="count++">count is {{ count }}</button>
        </div>
    </template>
    <script lang="ts" setup>
        import { ref } from 'vue'
        const count = ref(0)
    </script>

It is working, but it seems messy and I have no idea how to do it in a good way.

I have searched but every where they talk about how to use routing, while I want to avoid routing and no url-change

1 Answer 1

5

I think you need to use dynamic components. You can dynamically specify which component to render at a single place.

<template>
  <component :is="currentPage" />
</template>

<script setup>
import PageA from '@/components/PageA.vue'
import PageB from '@/components/PageB.vue'
import PageC from '@/components/PageC.vue'

const currentPage = ref('PageA')

function changeView(page) {
  currentPage.value = page
}
</script>
Sign up to request clarification or add additional context in comments.

16 Comments

I also used it this way and it works too. but is it the best way?
It's definitely better than defining an anonymous async component on each view change. Here you will benefit from caching (not importing twice the same component), avoid re-render with <keep-alive> wrapper etc.
And is this way of handling all app components and views a good way or weird?
may we make a sample git project?
Just wanted to add that this link in Vue documentation supports using Dynamic Components as an alternative/simple replacement for Vue Router: "If you only need very simple routing and do not wish to involve a full-featured router library, you can do so with Dynamic Components and update the current component state by listening to browser hashchange events or using the History API." @AhmadEbrahimi
|

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.