Build a Vue.js 1.x Single Page Application from Scratch – Step‑by‑Step Guide
This tutorial walks you through the reasons for using SPA, why Vue.js is a lightweight alternative to React, how to set up the Node environment, configure Webpack, create components, manage routing, handle component lifecycles, and implement nested routes with practical code examples.
In recent years the front‑end ecosystem has shifted rapidly from MVC to MVVM, with frameworks such as Backbone and AngularJS fading while React and the lighter Vue are thriving; this guide demonstrates an initial experience with Vue 1.0.
1. Why SPA?
SPA (Single Page Application) eliminates page reloads, avoiding white‑screen blocking and greatly improving performance for hybrid H5 apps, delivering a near‑native fluid experience.
2. Why Choose Vue?
Compared with a React demo, Vue is far lighter; its view layer works directly on the DOM and custom Vue directives act as custom tags, resulting in lower learning cost.
3. Environment Setup
Initialize the project with Node and npm, then run the following commands:
// Initialize package.json
npm init
// Install Vue and its router
npm install vue --save
npm install vue-router --save
// Install Webpack development dependencies
npm install webpack --save-dev
// Install Babel ES6 loader dependencies
npm install babel --save-dev
npm install babel-core --save-dev
npm install babel-loader --save-dev
npm install babel-preset-es2015 --save-dev
// Install HTML loader
npm install html-loader --save-dev4. Directory Structure
src – development folder (components and templates sub‑folders)
dist – built output folder
index.html – entry file
package.json – project description generated by npm init webpack.config.js – Webpack configuration file
5. Webpack Configuration
var webpack = require("webpack");
module.exports = {
entry: {
bundle: ["./src/app.js"]
},
output: {
path: __dirname,
publicPath: "/",
filename: "dist/[name].js"
},
module: {
loaders: [
{test: /\.html$/, loaders: ['html']},
{test: /(\.js)$/, loader: ["babel"], exclude: /node_modules/,
query: {presets: ["es2015"]}}
]
},
plugins: []
};6. Entry File
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Router Demo</title>
</head>
<body>
<div id="app">
<router-view></router-view>
</div>
<script src="dist/bundle.js"></script>
</body>
</html>The div#app serves as the container; router-view is rendered by vue‑router.
7. First Component
// components/index.js
module.exports = {
template: require('../templates/index'),
ready: function () {}
}; <h1>Index</h1>
<hr/>
<p>Hello World Index!</p>8. Component Navigation
Update the index component to use v-link for navigation:
<h1>Index</h1>
<hr/>
<p>Hello World Index!</p>
<p><a v-link="{path:'/list'}">List Page</a></p>List component:
// components/list.js
module.exports = {
template: require('../templates/list'),
data: function(){
return {items:[{"id":1,"name":"hello11"},{"id":2,"name":"hello22"}]};
},
ready: function () {}
}; <h1>List</h1>
<hr/>
<p>Hello List Page!</p>
<ul>
<li v-for="(index,item) in items">${item.id} : ${item.name}</li>
</ul>Running webpack --watch automatically rebuilds the bundle on file changes.
9. Component Lifecycle
// components/list.js (with lifecycle hooks)
module.exports = {
template: require('../templates/list'),
data: function(){
return {items:[{"id":1,"name":"hello11"},{"id":2,"name":"hello22"}]};
},
init: function(){ console.log("init.."); },
created: function(){ console.log("created.."); },
beforeCompile: function(){ console.log("beforeCompile.."); },
compiled: function(){ console.log("compiled.."); },
ready: function(){ console.log("ready.."); },
attached: function(){ console.log("attached.."); },
detached: function(){ console.log("detached.."); },
beforeDestroy: function(){ console.log("beforeDestroy.."); },
destroyed: function(){ console.log("destroyed.."); }
};Browser console shows the execution order when entering and leaving the List page.
10. Parent‑Child Components
// components/item.js
module.exports = {
template: require('../templates/item'),
props: ["id","name"],
ready: function () {}
}; <p>I am subitem: ${id} - ${name}</p>Update list.js to register the child component and use it:
// components/list.js
import item from "./item";
module.exports = {
template: require('../templates/list'),
data: function(){
return {items:[{"id":1,"name":"hello11"},{"id":2,"name":"hello22"}]};
},
components: {"item": item},
ready: function () {}
}; <ul>
<li v-for="(index,item) in items">
<!-- use item component and pass props -->
<item v-bind:id="item.id" v-bind:name="item.name"></item>
</li>
</ul>11. Navigation with Parameters
// routes.js (add show route)
module.exports = {
'/': {component: require('./components/index')},
'/list': {component: require('./components/list')},
'/show/:id': {name: "show", component: require('./components/show')},
'*': {component: require('./components/notFound')}
}; // components/show.js
module.exports = {
template: require('../templates/show'),
data: function(){return {};},
created: function(){
var id = this.$route.params.id;
if (id == 1){ this.$data = {id:id, name:"hello111", age:24}; }
else { this.$data = {id:id, name:"hello222", age:28}; }
},
ready: function(){ console.log(this.$data); }
}; <h1>Show</h1>
<hr/>
<p>Hello show page!</p>
<p>id:${id}</p>
<p>name:${name}</p>
<p>age:${age}</p>Modify templates/item.html to link to the detail page:
<p>I am subitem: <a v-link="{name:'show',params:{'id':id}}">${id} : ${name}</a> </p>12. Nested Routes
// components/tab1.js
module.exports = {template: "<p>Tab1 content</p>"};
// components/tab2.js
module.exports = {template: "<p>Tab2 content</p>"}; // components/index.js (register tabs)
import tab1 from "./tab1";
import tab2 from "./tab2";
module.exports = {
template: require('../templates/index'),
components: {"tab1": tab1, "tab2": tab2},
ready: function () {}
}; // routes.js (nested routes with default)
module.exports = {
'/': {
component: require('./components/index'),
subRoutes: {
'/': {component: require('./components/tab1')},
'/tab1': {component: require('./components/tab1')},
'/tab2': {component: require('./components/tab2')}
}
},
'/list': {component: require('./components/list')},
'/show/:id': {name: "show", component: require('./components/show')},
'*': {component: require('./components/notFound')}
};13. Real‑World Vue Usage
Examples of Vue in production include the Xiaomi Mobile website (http://m.mi.com/1/#/index) and Ele.me’s mobile recruitment site (https://jobs-mobile.ele.me/#!/).
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent TDS Service
TDS Service offers client and web front‑end developers and operators an intelligent low‑code platform, cross‑platform development framework, universal release platform, runtime container engine, monitoring and analysis platform, and a security‑privacy compliance suite.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
