Skip to content
Muhammet Şafak
tr
Interface 4 min read

Single-page application routing with Vue Router

A walkthrough of the core concepts and practical setup I encountered while moving page transitions to the client side with Vue Router.


Back in April I wrote my first component with Vue.js. Since then I’ve used it in a handful of small UI pieces, and my positive impression of the reactive approach has only grown. This time I wanted to take a bigger step: setting up a full single-page application (SPA) architecture with Vue Router.

An SPA is an approach where all page transitions happen in the browser. The server delivers a single HTML file and the required assets (JavaScript, CSS) on the first request; every subsequent navigation is handled entirely by JavaScript. No full page reloads, fast transitions.

What is Vue Router?

Vue Router is the official routing library for Vue.js. It maps URLs to components. Install it via npm:

npm install vue-router

Basic setup

First I define the components — each “page” is a Vue component:

// components/Anasayfa.js
var Anasayfa = {
    template: '<div><h2>Hoşgeldiniz</h2><p>Ana sayfa içeriği.</p></div>'
};

// components/Hakkimda.js
var Hakkimda = {
    template: '<div><h2>Hakkımda</h2><p>Bu benim sayfam.</p></div>'
};

// components/UrunDetay.js
var UrunDetay = {
    template: '<div><h2>Ürün {{ $route.params.id }}</h2></div>'
};

Then I define the routes and create the router:

var rotalar = [
    { path: '/',              component: Anasayfa   },
    { path: '/hakkimda',      component: Hakkimda   },
    { path: '/urunler/:id',   component: UrunDetay  }
];

var router = new VueRouter({
    routes: rotalar
});

var uygulama = new Vue({
    router: router,
    el: '#uygulama'
});

On the HTML side, the <router-view> tag marks where the active component should be rendered:

<div id="uygulama">
    <nav>
        <router-link to="/">Anasayfa</router-link>
        <router-link to="/hakkimda">Hakkımda</router-link>
    </nav>

    <router-view></router-view>
</div>

<router-link> is used in place of a standard <a> tag — it handles the link without triggering a full page reload.

URL mode: hash vs. history

In the default mode, URLs look like /#/hakkimda. This is hash mode; it requires no server configuration because the hash fragment is never sent to the server.

For clean URLs (/hakkimda), you switch to history mode:

var router = new VueRouter({
    mode: 'history',
    routes: rotalar
});

This mode, however, requires a server-side change: all requests must be redirected to index.html. On Nginx that looks like:

location / {
    try_files $uri $uri/ /index.html;
}

Without this, a direct visit to /hakkimda returns a 404 from the server. Apache needs a similar .htaccess rule. I skipped this on my first try and spent a good while wondering why things weren’t working — it’s a common trap when setting up an SPA for the first time.

Dynamic route parameters

For dynamic routes like a product detail page, I use the :id syntax to capture URL parameters:

var UrunDetay = {
    template: '<div>Ürün ID: {{ urunId }}</div>',

    computed: {
        urunId: function () {
            return this.$route.params.id;
        }
    },

    created: function () {
        // Fetch data when the page loads
        console.log('Ürün ID:', this.$route.params.id);
    }
};

I access the :id value from the URL via this.$route.params.id. It’s available from any method or computed property inside the component.

One thing to watch with dynamic routes: when the same component is reused with different parameters, Vue does not recreate the component — only the parameters change. This means the created hook is only called on the initial load. To react to parameter changes you need to watch $route; I missed this at first and spent a long time chasing why my data wasn’t updating.

Sometimes you need to redirect programmatically after an action completes — for example, after a form submission:

var UrunEkle = {
    template: '<button @click="kaydet">Kaydet</button>',

    methods: {
        kaydet: function () {
            // Save logic...

            // Redirect to product list
            this.$router.push('/urunler');
        }
    }
};

Observations

Setting up an SPA with Vue Router turned out to be easier than I expected. The relationship between components and routes is clean and easy to reason about.

A few things still puzzle me: routes with multiple parameters, nested routes, transition animations. I need to explore those separately.

There is also the server-side rendering (SSR) question — important for SEO. For now I’m experimenting with the SPA approach on a small admin panel where SEO doesn’t matter. For any public-facing application, though, that topic needs to be addressed.

Vue Router is a natural next step within the Vue ecosystem. Pair reactive components with routing and you get a genuine application skeleton.

Tags: #Vue.js
Share:

Comments

Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.

Related Posts

Search the site

Start typing to search posts, projects and pages.

Esc to close Powered by Pagefind