You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8.5 KiB
8.5 KiB
Tutorial vue pwa
- Vue PWA template is built on top of Vue webpack template
- Webpack is a modern and powerful module bundler for Javascript application
- Project layout
- build: webpack and vue-loader configuration files
- config: app config (environments, parameters)
- src: application source code
- statis: images, css & other public assets
- test: unit test files (Karma & Mocha)
$ npm install -g vue-cli
// use pwa template to scaffold a project
$ vue init pwa cropchat
$ cd cropchat
$ npm install
$ npm run dev
// launch browser at http://localhost:8080
- Vue pwa template provide default
static/manifest.json. Edit it to customize the project
{
"name": "cropchat",
"short_name": "cropchat",
"icons": [
{
"src": "/static/img/icons/cropchat-icon-64x64.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/static/img/icons/cropchat-icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "/static/img/icons/cropchat-icon-256x256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "/static/img/icons/cropchat-icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/",
"display": "fullscreen",
"orientation": "portrait",
"background_color": "#2196f3",
"theme_color": "#2196f3"
}
index.htmlalready provide the manifest link
...
<meta name="viewport" content="width=device-width, initial-scale=1">
...
<link rel="manifest" href="<%= htmlWebpackPlugin.files.publicPath %>static/manifest.json">
Access from mobile
- use
ngrokto forward internet address to localhost host
$ npm install -g ngrok
$ ngrok http 8080
ngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Version 2.1.18
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://5ef29506.ngrok.io -> localhost:8080
Forwarding https://5ef29506.ngrok.io -> localhost:8080
Connections ttl opn rt1 rt5 p50 p90
39 3 0.01 0.01 120.01 881.89
- Access
https://5ef29506.ngrok.iofrom mobile
Develop Vue App
src/components/HomeView.vue
<template>
<ul class="list">
</ul>
</template>
<script>
export default {
}
</script>
<style scoped>
.list {
width: 100%;
padding: 0;
}
</style>
src/components/DetailView.vue
<template>
<div class="card-image">
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>
src/components/PostView.vue
<template>
<div class="waiting">
Not yet available
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.waiting {
padding: 10px;
color: #555;
}
</style>
- Update
src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HomeView from '@/components/HomeView'
import DetailView from '@/components/DetailView'
import PostView from '@/components/PostView'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/detail/:id',
name: 'detail',
component: DetailView
},
{
path: '/post',
name: 'post',
component: PostView
}
]
})
- Remove
Hello.vue
Layout Design
- install material Design
$ npm install material-design-lite --save
- Update
src/App.vue
<script>
require('material-design-lite')
...
</script>
<style>
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
@import url('https://code.getmdl.io/1.2.1/material.blue-red.min.css');
</style>
- Add Navigation Bar. Update
src/App.vuetemplate
<template>
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
<header class="mdl-layout__header">
<div class="mdl-layout__header-row">
<span class="mdl-layout-title">CropChat</span>
</div>
</header>
<div class="mdl-layout__drawer">
<span class="mdl-layout-title">CropChat</span>
<nav class="mdl-navigation">
<router-link class="mdl-navigation__link" to="/" @click.native="hideMenu">Home</router-link>
<router-link class="mdl-navigation__link" to="/post" @click.native="hideMenu">Post a picture</router-link>
</nav>
</div>
<main class="mdl-layout__content">
<div class="page-content">
<router-view></router-view>
</div>
</main>
</div>
</template>
- Hide burger menu upon click menu link
<script>
...
export default {
name: 'app',
methods: {
hideMenu: function () {
document.getElementsByClassName('mdl-layout__drawer')[0].classList.remove('is-visible')
document.getElementsByClassName('mdl-layout__obfuscator')[0].classList.remove('is-visible')
}
}
}
</script>
- Populate views
- Create
src/data.js
export default {
pictures: [
{
'id': 0,
'url': 'https://25.media.tumblr.com/tumblr_m40h4ksiUa1qbyxr0o1_400.gif',
'comment': 'A cat game',
'info': 'Posted by Kevin on Friday'
},
{
'id': 1,
'url': 'https://25.media.tumblr.com/tumblr_lhd7n9Qec01qgnva2o1_500.jpg',
'comment': 'Tatoo & cat',
'info': 'Posted by Charles on Tuesday'
},
{
'id': 2,
'url': 'https://24.media.tumblr.com/tumblr_m4j2atctRm1qejbiro1_1280.jpg',
'comment': 'Santa cat',
'info': 'Posted by Richard on Monday'
},
{
'id': 3,
'url': 'https://25.media.tumblr.com/tumblr_m3rmbwhVB51qhwmnpo1_1280.jpg',
'comment': 'Mexico cat',
'info': 'Posted by Richard on Monday'
},
{
'id': 4,
'url': 'https://24.media.tumblr.com/tumblr_mceknxs4Lo1qd477zo1_500.jpg',
'comment': 'Curious cat',
'info': 'Posted by Richard on Monday'
}
]
}
- Update
src/components/HomeView.vueto display mocked data
<script>
import data from '../data'
export default {
methods: {
displayDetails (id) {
this.$router.push({name: 'detail', params: { id: id }})
}
},
data () {
return {
'pictures': data.pictures
}
}
}
</script>
- Update temple ans style
<template>
<div>
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--3-col mdl-cell mdl-cell--1-col-tablet mdl-cell--hide-phone"></div>
<div class="mdl-cell mdl-cell--6-col mdl-cell--4-col-phone">
<div v-for="picture in this.pictures" class="image-card" @click="displayDetails(picture.id)">
<div class="image-card__picture">
<img :src="picture.url" />
</div>
<div class="image-card__comment mdl-card__actions">
<span>{{ picture.comment }}</span>
</div>
</div>
</div>
</div>
<router-link class="add-picture-button mdl-button mdl-js-button mdl-button--fab mdl-button--colored" to="/post">
<i class="material-icons">add</i>
</router-link>
</div>
</template>
...
<style scoped>
.add-picture-button {
position: fixed;
right: 24px;
bottom: 24px;
z-index: 998;
}
.image-card {
position: relative;
margin-bottom: 8px;
}
.image-card__picture > img {
width:100%;
}
.image-card__comment {
position: absolute;
bottom: 0;
height: 52px;
padding: 16px;
text-align: right;
background: rgba(0, 0, 0, 0.5);
}
.image-card__comment > span {
color: #fff;
font-size: 14px;
font-weight: bold;
}
</style>