Single-Page Applications (SPAs) are web apps that load a single HTML page and dynamically update that page as the user interacts with the app. SPAs use AJAX and HTML5 to create fluid and responsive Web apps, without constant page reloads.
As stated in the above description taken from Wikipedia, the main advantage of SPAs is that the app can respond to user interactions without fully reloading the page, resulting in a much more fluid user experience.
All the code for this post can be found on Github.
Creating the Home Component
Let's kick things off here by applying a navigation bar to the app. But first, we'll need to add Bootstrap for some styling. A quick way to do this is to grab the CSS from Bootstrap's CDN.
vue-time-tracker
The best place for the navbar is our App.vue
file, so let's edit it to have a new template.
There's a smaller div
that will be used for our sidebar, and a larger one that will show other components through the router-view
tag, vue-router
does this as well through router-view
.
The Home
component for our app really just needs to show a simple message. Let's create a Home.vue
and give it a template with that message.
Vue Time Tracker
Get started by
creating a time entry .
Creating the Time Entries Component
We'll make a component that lists out existing time entries, called TimeEntries.vue
, and then another one for entering new time entries, called LogTime.vue
. We'll add a link from TimeEntries
to LogTime
so the user can jump to the spot for adding new time entries quickly.
We see a router-view
below the hr
tag, and this is because we'll be registering a sub-route for logging time entries. Essentially we're nesting one route within another, so the LogTime
component will be two levels deep. This is the cool thing about routing--we can just keep putting router-view
elements in our templates, and as long as we register a component for them, they will keep nesting further down.
Creating the store.js
we're just working with local data by localStorage
.
/* 使用 localStorage 临时保存数据 */
const STORAGE_KEY = 'vue-time-tracker'
export default {
fetch() {
return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
},
save(items) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(items))
},
totalTimes() {
var total = 0
this.fetch().forEach(function (item) {
total += parseInt(item.totalTime)
});
return total
}
}
Creating the Log Time Component
We need a component that provides a screen for the user to log time entries.
We're initializing the timeEntry
model with some data for the user so that we can have a name and profile photo.
When our app grows and needs to communicate a lot of data between many components. We'll see how to fix this by using Vuex for state management.
Creating the router.js
We need to add the LogTime
component as a sub-route of TimeEntries
in our router configuration. By doing this, the router will know that LogTime
is a child of TimeEntries
, and the appropriate URI structure will be generated when we navigate to it.
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from './components/Home'
import TimeEntries from './components/TimeEntries'
import LogTime from './components/LogTime'
Vue.use(VueRouter)
const routes = [{
path: '/home',
component: Home
},
{
path: '/time-entries',
component: TimeEntries,
children: [{
path: 'log-time',
component: LogTime
}]
},
{
path: '*',
redirect: '/home'
}
]
export default new VueRouter({
mode: 'history',
routes
})
Creating the Sidebar Component
Sidebar
component will hold the total number of hours for all of our time entries.
Total Time
{{ time }} hours
The props
array is where we can specify any properties that we want to use which are passed into the component, and here we are getting the time
prop which is placed on the sidebar
element in App.vue
.
{{ timeEntry.comment }}