SlideShare una empresa de Scribd logo
1 de 49
Descargar para leer sin conexión
以Vue開發電⼦子商務網站

架構與眉⾓角
2017/8/22
• Mayu Chen

• Frontend Developer of gelovery.com / patio.tw

• windfish27@gmail.com

๏ 以下範例例為經驗分享

๏ 感謝後端⼤大⼤大的⽀支援...m(_ _)m
About me
• 專案環境簡介

• 初始專案建置

• Css Style 

• 網站路路由

• 狀狀態管理理

• 溝通Server

• 取得⾴頁⾯面資料
Agenda
專案環境簡介
• Docker

• Rails

• Vue (SPA)

• Node

• Yarn

• Atom

• Package: languague-vue

• Chrome extension

• Vue.js devtools
專案技術列列表
• Html / Css

• Scss (Sass)

• Javascript (ES6)、JSON

• Vue

• Vue-router / Vuex / Vue-resource

• Webpack
$ npm install -g vue-cli
$ vue init webpack vue-new
⾃自訂專案名稱
Template variables:

https://github.com/vuejs/vue-cli
初始專案建置:Vue-cli
Preference: Github: Vuejs/vue-cli
This will install Vue 2.x version of the template.
For Vue 1.x use: vue init webpack#1.0 vue-new
? Project name vue-new
? Project description A Vue.js project
? Author Meiyu <windfish27+GH@gmail.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Setup unit tests with Karma + Mocha? No
? Setup e2e tests with Nightwatch? No
vue-cli Generated "vue-new".
To get started:
cd vue-new
npm install
npm run dev
Documentation can be found at https://vuejs-templates.github.io/
webpack
$ npm run build ⟶ Production ready build.
$ npm run unit ⟶ Unit tests run.
$ npm run e2e ⟶ End-to-end tests.
$ cd vue-new
$ npm install / yarn
$ npm run dev
初始專案建置:Vue-cli
初始專案建置:Vue-cli專案結構
─ build/
─ config/
─ node_modules/
─ src/
 ├ assets/
 ├ components/
  └ Hello.vue
 ├ router/
  └ index.js
 ├ App.vue
 └ main.js
─ static/
─ index.html
─ package.json
─ yarn.lock
初始專案建置:vue-template
<template lang="html">
html or other html loader
</template>
<script>
export default {
vue methods
}
</script>
<style lang="css">
css or other css loader
</style>
*.vue
import Vue from 'vue'
import App from './App'
import router from './
router'
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
main.js
初始專案建置:Vue-cli初始檔案
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Project Name</
title>
</head>
<body>
<div id="app"></div>
<!-- built files will be
auto injected -->
</body>
</html>
index.html
初始專案建置:Vue-cli初始檔案
<template>
<div id="#app">
<img src="./assets/logo.png">
<router-view></router-view>
<hello></hello>
</div>
</template>
<script>
import Hello from './components/Hello'
export default {
name: 'app',
components: { Hello }
}
</script>
App.vue
<style lang="css">
…
</style>
初始專案建置:⾃自訂專案結構
─ src/
 ├ api/
 ├ assets/
 ├ components/
 ├ mixins/
 ├ router/
 ├ scss/
 ├ store/
 ├ pages/
 ├ vue-plugin/
 ├ App.vue
 └ main.js
$ npm install node-sass sass-loader
$ yarn add node-sass sass-loader
<style lang="scss">
.style{
…
}
</style>
<style lang="sass">
.style
…
</style>
Css Style:Scss
<style lang="scss">
@import '../scss/function/
function';
.component-style{
…
}
</style>
Css Style:Scss
$variables: $color;
$width: 640px;
…
scss/function/_variables.scss
@mixin function-name($value) {
css-proprety: $value;
}
…
scss/function/_mixins.scss
@import 'mixins';
@import 'variables';
scss/function/function.scss
*.vue
Css Style:Scss
<style lang="scss">
@import 'scss/style';
</style>
App.vue
@import 'base/base';
@import 'function/function';
@import 'plugins/plugins';
@import 'partials/partials';
@import 'components/components';
@import 'views/views';
scss/style.scss
眉⾓角:iOS safari scroll
-webkit-overflow-scrolling: touch; // iOS safari scroll smooth
• Fixed footer範例例

• 發現⾴頁⾯面加上以上屬性,在iOS Safari滑動會變很順

• 發現Bug:iOS Safari切換⾴頁⾯面載入Data時,沒有偵測到捲軸,
就會鎖死⾴頁⾯面。即使下⾯面還有內容,也無法往下滑。
Preference: How we fixed the -webkit-overflow-scrolling: touch; bug on iOS
.outer {
overflow: scroll;
-webkit-overflow-scrolling: touch;
/* More properties for a fixed height ... */
}
.inner {
height: calc(100% + 1px);
}
眉⾓角:iOS safari scroll
網站路路由:Vue-router
Preference: Github: Vuejs/vue-router
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '../components/Hello'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Hello',
component: Hello
}
]
})
Vue-cli預設router樣式
…
export default new Router({
mode: 'history',
scrollBehavior (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { x: 0, y: 0 }
}
},
…
})
Vue-router:Settings
router/index.js
…
export default new Router({
…
routes: [
{
path: '/',
name: 'index',
component: (resolve) => {
require(['../pages/index.vue'], resolve)
}
},
…
]
})
Vue-router:Lazy Loading Routes
router/index.js
<router-link :to="{ name: 'index' }">連結⽂文字</router-link>
…
export default new Router({
…
routes: [
…
{
path: '/page/:pageId',
name: 'page',
component: (resolve) => {
require(['../pages/page.vue'], resolve)
}
},
…
]
})
Vue-router:Params
router/index.js
<router-link :to="{ name: 'page', params: { pageId: id } }">連結⽂文
字</router-link>
routes: [
…
{
path: '/404',
name: 'unfound',
component: (resolve) => {
require(['../pages/unfound.vue'], resolve)
}
},
{
path: '*',
redirect: to => {
return { name: 'unfound' }
}
}
]
…
Vue-router:Unfound Page
router/index.js
狀狀態管理理:Vuex
$ yarn add vuex
…
import store from './store'
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})
main.js─ src/
 ├ …
 ├ store/
  ├ modules/
   ├ app.js
   └ …
  └ index.js
 ├ … 
Preference: Github: Vuejs/vuex
Vuex Modules
import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
…
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
app,
…
}
})
store/index.js
Vuex Modules
const state = {
isLoading: false
…
}
const getters = {
isLoading: state => state.isLoading
…
}
const mutations = {
[types.setLoading] (state, boolean) {
state.isLoading = boolean
},
…
}
store/modules/app.js
Vuex Modules
const types = {
setLoading: 'app/setLoading',
…
}
const actions = {
setLodingAction ({commit}, boolean) {
commit(types.setLoading, boolean)
},
…
}
export default {
state,
getters,
mutations,
actions
}
store/modules/app.js
Vuex mapGetters, mapActions
import { mapGetters, mapActions } from 'vuex'
export default {
computed: mapGetters([
'isLoading',
…
]),
methods: {
...mapActions([
'setLodingAction',
…
]),
…
}
}
*.vue
computed: {
isLoading: this.$store.state.app.isLoading
}
methods: {
setLoadingMethod (value) {
this.$store.commit('setLoading', value)
// Commit mutations
}
}
Vuex Devtools
中場休息
import Vue from 'vue'
import VueResource from 'vue-resource'
Vue.use(VueResource)
export const pageResource =
Vue.resource(api_link + '{/params}')
…
api/resource.js─ src/
 ├ …
 ├ api/
  ├ resource.js
  └ index.js
 ├ … 
溝通Server:Vue-resource
$ yarn add vue-resource
Preference: Github: vue-resource
import * as resource from './resources'
export const getPage = (id) => resource.
pageResource.get({ params: id })
export const postPage = (object) => resource.
pageResource.save(object)
export const putPage = (id, object) => resource.
pageResource.update({ params: id }, object)
export const deletePage = (id) => resource.
pageResource.delete({ params: id })
…
api/index.js
溝通Server:Vue-resource
import { getPage } from '../api'
…
export default {
…
methods: {
fetchData () {
let id = this.$route.params.pageId // vue-router params
getPage(id).then(response => {
response.json().then(json => {
this.data = json
})
}, (response) => {
response.json().then(json => {
this.errorMsg(json)
})
})
}
}
}
pages/*.vue
Vue-resource:取得資料
Vue-router:Data Fetching
取得資料顯⽰示在⾴頁⾯面上有兩兩種⽅方式:

• 導入⾴頁⾯面之後獲取

• 導入⾴頁⾯面之前獲取
๏ 需要載入(或進度條)畫⾯面,讓使⽤用者知道正在載入

๏ 第⼆二種⽅方式在beforeRouteEnter取得資料,缺點是這個時候⾴頁
⾯面未載入,不能使⽤用this取得Vue其他資料

๏ 上⼀一⾴頁/下⼀一⾴頁時,這些⾴頁⾯面在v-for載入資料之前就先把卷軸定
位,所以router內建的scrollBehavior沒有⽤用。必須另外處理理。

๏ 以下說明第⼀一種⽅方式
import { mapGetters } from 'vuex'
export default {
computed: mapGetters([
'initial',
…
]),
created () {
this.fetchData()
},
watch: {
'$route' () {
this.fetchData()
}
},
…
}
mixins/routeFetching.vue
Component載入後取得數據
router有其他變動,取得數據
例例如params改變
Vue-router:Data Fetching
Vue-router:Data Fetching
pages/*.vue
import routeLoading from '../mixins/routeFetching'
export default {
…
mixins: [
routeLoading
]
…
}
…
眉⾓角:Data Fetching順序
App.vue router-view
新⾴頁⾯面/重新整理理

取得預先資料
created () 同時執⾏行行
initial = false
不執⾏行行fetchData
vuex
initial = false
已取得資料 initial = true watch initial變動
initial = true
fetchData
切換不同route initial = true created () 執⾏行行

initial = true
fetchData
切換同⼀一route

params變動
initial = true watch $route變動

initial = true
fetchData
initial 是 App.vue最外⾯面那層獲取
資料之後(例例如辨別會員是否登入)

,由false → true
import { mapGetters } from 'vuex'
export default {
computed: mapGetters([
'initial',
…
]),
created () {
this.startFetch(this.initial)
},
watch: {
'$route' () {
this.startFetch(this.initial)
},
'initial' (value) {
this.startFetch(value)
}
},
mixins/routeFetching.vue
methods: {
startFetch (initial) {
if (initial) {
this.fetchData()
}
}
}
}
眉⾓角:Data Fetching順序
眉⾓角:⾴頁⾯面Loading狀狀態
export default {
…
data () {
return {
loading: false
}
}
…
}
mixins/routeFetching.vue
<template>
<div>
<loading v-if="loading"></loading>
<div v-else>
// 顯⽰示的資料
</div>
</div>
</template>
pages/*.vue
眉⾓角:⾴頁⾯面Loading狀狀態
export default {
…
methods: {
fetchData () {
let id = this.$route.params.pageId // vue-router params
this.loading = true // loading true
getPage(id).then(response => {
response.json().then(json => {
this.data = json
this.loading = false // loading false
})
}, (response) => {
response.json().then(json => {
this.errorMsg(json) // in errorMsg redirect error.
})
})
},
…
}
}
pages/*.vue
眉⾓角:⾴頁⾯面Loading狀狀態
眉⾓角:ScrollPosition
• 離開⾴頁⾯面之前,儲存scrollPosition

• 偵測上⼀一⾴頁、下⼀一⾴頁啟動時機,popstate = true

• loading = true、讀取本⾴頁資料

• popstate = false、loading = false

• v-for讀取值產⽣生⾴頁⾯面

• 跳⾄至此⾴頁⾯面儲存的最後⼀一個scrollPosition

• 如果沒有偵測到上⼀一⾴頁下⼀一⾴頁,loading = false
import { mapActions } from 'vuex'
export default {
…
beforeRouteLeave (to, from, next) {
this.savePostionAction({
path: from.path,
pos: window.scrollY
})
next()
},
methods: {
...mapActions([
'savePostionAction'
]),
…
}
}
mixins/routeFetching.vue
眉⾓角:ScrollPosition
export default {
…
beforeMount () {
…
let self = this
window.onpopstate = function (event) {
self.setPopstateAction(true)
}
},
…
methods: {
...mapActions([
'setPopstateAction',
…
]),
…
}
}
App.vue
眉⾓角:ScrollPosition
pages/*.vue
export default {
…
methods: {
fetchData () {
let id = this.$route.params.pageId // vue-router params
this.loading = true // loading true
getPage(id).then(response => {
response.json().then(json => {
this.data = json
this.getPagePosition() // detect page position
})
}, (response) => {
response.json().then(json => {
this.errorMsg(json) // in errorMsg set loading false
})
})
},
…
}
}
眉⾓角:ScrollPosition
mixins/routeFetching.vue
…
export default {
…
computed: mapGetters([
'popstate'
…
]),
methods: {
getPagePosition () {
let path = this.$route.path
let pagePositions = this.savedPostions.filter(object => {
if (object.name === name) {
return object
}
})
// 接下⾴頁
眉⾓角:ScrollPosition
mixins/routeFetching.vue
let length = pagePositions.length
if (length > 0 && this.popstate) {
let lastPosition = pagePositions[length - 1]
this.setPopstateAction(false)
setTimeout(function () {
window.scrollTo(0, lastPosition.pos)
}, 10)
}
this.loading = false
}
…
}
}
眉⾓角:ScrollPosition
缺點:

• 連續按上⼀一⾴頁時,如遇到相同路路徑的⾴頁⾯面,取得的
ScrollPosition可能不會是正確的。

• 重新整理理之後,Vuex儲存的ScrollPosition會清空。這時上⼀一⾴頁
會因為沒有紀錄所以置頂。
眉⾓角:ScrollPosition
Ending & QA
Thanks for listening.

Más contenido relacionado

La actualidad más candente

Vue.js
Vue.jsVue.js
Vue.jsBADR
 
Vue Introduction
Vue IntroductionVue Introduction
Vue IntroductionElad Gasner
 
Javascript MVVM with Vue.JS
Javascript MVVM with Vue.JSJavascript MVVM with Vue.JS
Javascript MVVM with Vue.JSEueung Mulyana
 
The Point of Vue - Intro to Vue.js
The Point of Vue - Intro to Vue.jsThe Point of Vue - Intro to Vue.js
The Point of Vue - Intro to Vue.jsHolly Schinsky
 
Enjoy the vue.js
Enjoy the vue.jsEnjoy the vue.js
Enjoy the vue.jsTechExeter
 
Vue.js is boring - and that's a good thing
Vue.js is boring - and that's a good thingVue.js is boring - and that's a good thing
Vue.js is boring - and that's a good thingJoonas Lehtonen
 
Building a Single Page Application with VueJS
Building a Single Page Application with VueJSBuilding a Single Page Application with VueJS
Building a Single Page Application with VueJSdanpastori
 
Scalable Front-end Development with Vue.JS
Scalable Front-end Development with Vue.JSScalable Front-end Development with Vue.JS
Scalable Front-end Development with Vue.JSGalih Pratama
 
Vue 2.0 + Vuex Router & Vuex at Vue.js
Vue 2.0 + Vuex Router & Vuex at Vue.jsVue 2.0 + Vuex Router & Vuex at Vue.js
Vue 2.0 + Vuex Router & Vuex at Vue.jsTakuya Tejima
 
Vue js and Vue Material
Vue js and Vue MaterialVue js and Vue Material
Vue js and Vue MaterialEueung Mulyana
 
Modern frontend development with VueJs
Modern frontend development with VueJsModern frontend development with VueJs
Modern frontend development with VueJsTudor Barbu
 
An introduction to Vue.js
An introduction to Vue.jsAn introduction to Vue.js
An introduction to Vue.jsPagepro
 
Room with a Vue - Introduction to Vue.js
Room with a Vue - Introduction to Vue.jsRoom with a Vue - Introduction to Vue.js
Room with a Vue - Introduction to Vue.jsZachary Klein
 
Vue.js Getting Started
Vue.js Getting StartedVue.js Getting Started
Vue.js Getting StartedMurat Doğan
 

La actualidad más candente (20)

Vue JS Intro
Vue JS IntroVue JS Intro
Vue JS Intro
 
Vue.js
Vue.jsVue.js
Vue.js
 
Vue Introduction
Vue IntroductionVue Introduction
Vue Introduction
 
Vue business first
Vue business firstVue business first
Vue business first
 
Javascript MVVM with Vue.JS
Javascript MVVM with Vue.JSJavascript MVVM with Vue.JS
Javascript MVVM with Vue.JS
 
Vue.js
Vue.jsVue.js
Vue.js
 
The Point of Vue - Intro to Vue.js
The Point of Vue - Intro to Vue.jsThe Point of Vue - Intro to Vue.js
The Point of Vue - Intro to Vue.js
 
Enjoy the vue.js
Enjoy the vue.jsEnjoy the vue.js
Enjoy the vue.js
 
Vue.js is boring - and that's a good thing
Vue.js is boring - and that's a good thingVue.js is boring - and that's a good thing
Vue.js is boring - and that's a good thing
 
Building a Single Page Application with VueJS
Building a Single Page Application with VueJSBuilding a Single Page Application with VueJS
Building a Single Page Application with VueJS
 
Scalable Front-end Development with Vue.JS
Scalable Front-end Development with Vue.JSScalable Front-end Development with Vue.JS
Scalable Front-end Development with Vue.JS
 
Vue 2.0 + Vuex Router & Vuex at Vue.js
Vue 2.0 + Vuex Router & Vuex at Vue.jsVue 2.0 + Vuex Router & Vuex at Vue.js
Vue 2.0 + Vuex Router & Vuex at Vue.js
 
Why Vue.js?
Why Vue.js?Why Vue.js?
Why Vue.js?
 
Love at first Vue
Love at first VueLove at first Vue
Love at first Vue
 
Vue js and Vue Material
Vue js and Vue MaterialVue js and Vue Material
Vue js and Vue Material
 
Modern frontend development with VueJs
Modern frontend development with VueJsModern frontend development with VueJs
Modern frontend development with VueJs
 
An introduction to Vue.js
An introduction to Vue.jsAn introduction to Vue.js
An introduction to Vue.js
 
Room with a Vue - Introduction to Vue.js
Room with a Vue - Introduction to Vue.jsRoom with a Vue - Introduction to Vue.js
Room with a Vue - Introduction to Vue.js
 
Vue.js Getting Started
Vue.js Getting StartedVue.js Getting Started
Vue.js Getting Started
 
Vuex
VuexVuex
Vuex
 

Similar a 以Vue開發電子商務網站
架構與眉角

Webpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of usWebpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of usStefan Adolf
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVCAlive Kuo
 
125 고성능 web view-deview 2013 발표 자료_공유용
125 고성능 web view-deview 2013 발표 자료_공유용125 고성능 web view-deview 2013 발표 자료_공유용
125 고성능 web view-deview 2013 발표 자료_공유용NAVER D2
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoJavier Abadía
 
Express Presentation
Express PresentationExpress Presentation
Express Presentationaaronheckmann
 
Fisl 11 - Dicas de Desenvolvimento Web com Ruby
Fisl 11 - Dicas de Desenvolvimento Web com RubyFisl 11 - Dicas de Desenvolvimento Web com Ruby
Fisl 11 - Dicas de Desenvolvimento Web com RubyFabio Akita
 
The Future of CSS with Web components
The Future of CSS with Web componentsThe Future of CSS with Web components
The Future of CSS with Web componentsdevObjective
 
The Future of CSS with Web Components
The Future of CSS with Web ComponentsThe Future of CSS with Web Components
The Future of CSS with Web ComponentsColdFusionConference
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdevFrank Rousseau
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)Doris Chen
 
A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019Matt Raible
 
Modern JavaScript, without giving up on Rails
Modern JavaScript, without giving up on RailsModern JavaScript, without giving up on Rails
Modern JavaScript, without giving up on RailsJonathan Johnson
 
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010Arun Gupta
 
RESS – Responsive Webdesign and Server Side Components
RESS – Responsive Webdesign and Server Side ComponentsRESS – Responsive Webdesign and Server Side Components
RESS – Responsive Webdesign and Server Side ComponentsSven Wolfermann
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackIgnacio Martín
 

Similar a 以Vue開發電子商務網站
架構與眉角 (20)

Death of a Themer
Death of a ThemerDeath of a Themer
Death of a Themer
 
Webpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of usWebpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of us
 
Nodejs.meetup
Nodejs.meetupNodejs.meetup
Nodejs.meetup
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
 
Sprockets
SprocketsSprockets
Sprockets
 
Vue js and Dyploma
Vue js and DyplomaVue js and Dyploma
Vue js and Dyploma
 
125 고성능 web view-deview 2013 발표 자료_공유용
125 고성능 web view-deview 2013 발표 자료_공유용125 고성능 web view-deview 2013 발표 자료_공유용
125 고성능 web view-deview 2013 발표 자료_공유용
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar Django
 
Express Presentation
Express PresentationExpress Presentation
Express Presentation
 
Fisl 11 - Dicas de Desenvolvimento Web com Ruby
Fisl 11 - Dicas de Desenvolvimento Web com RubyFisl 11 - Dicas de Desenvolvimento Web com Ruby
Fisl 11 - Dicas de Desenvolvimento Web com Ruby
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
The Future of CSS with Web components
The Future of CSS with Web componentsThe Future of CSS with Web components
The Future of CSS with Web components
 
The Future of CSS with Web Components
The Future of CSS with Web ComponentsThe Future of CSS with Web Components
The Future of CSS with Web Components
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
 
A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019
 
Modern JavaScript, without giving up on Rails
Modern JavaScript, without giving up on RailsModern JavaScript, without giving up on Rails
Modern JavaScript, without giving up on Rails
 
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
Hyperproductive JSF 2.0 @ JavaOne Brazil 2010
 
RESS – Responsive Webdesign and Server Side Components
RESS – Responsive Webdesign and Server Side ComponentsRESS – Responsive Webdesign and Server Side Components
RESS – Responsive Webdesign and Server Side Components
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 

Último

8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
Generic or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsBert Jan Schrijver
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfayushiqss
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationShrmpro
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 

Último (20)

8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Generic or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 

以Vue開發電子商務網站
架構與眉角

  • 2. • Mayu Chen • Frontend Developer of gelovery.com / patio.tw • windfish27@gmail.com ๏ 以下範例例為經驗分享 ๏ 感謝後端⼤大⼤大的⽀支援...m(_ _)m About me
  • 3. • 專案環境簡介 • 初始專案建置 • Css Style • 網站路路由 • 狀狀態管理理 • 溝通Server • 取得⾴頁⾯面資料 Agenda
  • 4. 專案環境簡介 • Docker • Rails • Vue (SPA) • Node • Yarn • Atom • Package: languague-vue • Chrome extension • Vue.js devtools
  • 5. 專案技術列列表 • Html / Css • Scss (Sass) • Javascript (ES6)、JSON • Vue • Vue-router / Vuex / Vue-resource • Webpack
  • 6. $ npm install -g vue-cli $ vue init webpack vue-new ⾃自訂專案名稱 Template variables:
 https://github.com/vuejs/vue-cli 初始專案建置:Vue-cli Preference: Github: Vuejs/vue-cli
  • 7. This will install Vue 2.x version of the template. For Vue 1.x use: vue init webpack#1.0 vue-new ? Project name vue-new ? Project description A Vue.js project ? Author Meiyu <windfish27+GH@gmail.com> ? Vue build standalone ? Install vue-router? Yes ? Use ESLint to lint your code? Yes ? Pick an ESLint preset Standard ? Setup unit tests with Karma + Mocha? No ? Setup e2e tests with Nightwatch? No vue-cli Generated "vue-new". To get started: cd vue-new npm install npm run dev Documentation can be found at https://vuejs-templates.github.io/ webpack
  • 8. $ npm run build ⟶ Production ready build. $ npm run unit ⟶ Unit tests run. $ npm run e2e ⟶ End-to-end tests. $ cd vue-new $ npm install / yarn $ npm run dev 初始專案建置:Vue-cli
  • 9. 初始專案建置:Vue-cli專案結構 ─ build/ ─ config/ ─ node_modules/ ─ src/  ├ assets/  ├ components/   └ Hello.vue  ├ router/   └ index.js  ├ App.vue  └ main.js ─ static/ ─ index.html ─ package.json ─ yarn.lock
  • 10. 初始專案建置:vue-template <template lang="html"> html or other html loader </template> <script> export default { vue methods } </script> <style lang="css"> css or other css loader </style> *.vue
  • 11. import Vue from 'vue' import App from './App' import router from './ router' new Vue({ el: '#app', router, template: '<App/>', components: { App } }) main.js 初始專案建置:Vue-cli初始檔案 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Project Name</ title> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> </body> </html> index.html
  • 12. 初始專案建置:Vue-cli初始檔案 <template> <div id="#app"> <img src="./assets/logo.png"> <router-view></router-view> <hello></hello> </div> </template> <script> import Hello from './components/Hello' export default { name: 'app', components: { Hello } } </script> App.vue <style lang="css"> … </style>
  • 13. 初始專案建置:⾃自訂專案結構 ─ src/  ├ api/  ├ assets/  ├ components/  ├ mixins/  ├ router/  ├ scss/  ├ store/  ├ pages/  ├ vue-plugin/  ├ App.vue  └ main.js
  • 14. $ npm install node-sass sass-loader $ yarn add node-sass sass-loader <style lang="scss"> .style{ … } </style> <style lang="sass"> .style … </style> Css Style:Scss
  • 15. <style lang="scss"> @import '../scss/function/ function'; .component-style{ … } </style> Css Style:Scss $variables: $color; $width: 640px; … scss/function/_variables.scss @mixin function-name($value) { css-proprety: $value; } … scss/function/_mixins.scss @import 'mixins'; @import 'variables'; scss/function/function.scss *.vue
  • 16. Css Style:Scss <style lang="scss"> @import 'scss/style'; </style> App.vue @import 'base/base'; @import 'function/function'; @import 'plugins/plugins'; @import 'partials/partials'; @import 'components/components'; @import 'views/views'; scss/style.scss
  • 17. 眉⾓角:iOS safari scroll -webkit-overflow-scrolling: touch; // iOS safari scroll smooth • Fixed footer範例例 • 發現⾴頁⾯面加上以上屬性,在iOS Safari滑動會變很順 • 發現Bug:iOS Safari切換⾴頁⾯面載入Data時,沒有偵測到捲軸, 就會鎖死⾴頁⾯面。即使下⾯面還有內容,也無法往下滑。
  • 18. Preference: How we fixed the -webkit-overflow-scrolling: touch; bug on iOS .outer { overflow: scroll; -webkit-overflow-scrolling: touch; /* More properties for a fixed height ... */ } .inner { height: calc(100% + 1px); } 眉⾓角:iOS safari scroll
  • 19. 網站路路由:Vue-router Preference: Github: Vuejs/vue-router router/index.js import Vue from 'vue' import Router from 'vue-router' import Hello from '../components/Hello' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'Hello', component: Hello } ] }) Vue-cli預設router樣式
  • 20. … export default new Router({ mode: 'history', scrollBehavior (to, from, savedPosition) { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } } }, … }) Vue-router:Settings router/index.js
  • 21. … export default new Router({ … routes: [ { path: '/', name: 'index', component: (resolve) => { require(['../pages/index.vue'], resolve) } }, … ] }) Vue-router:Lazy Loading Routes router/index.js <router-link :to="{ name: 'index' }">連結⽂文字</router-link>
  • 22. … export default new Router({ … routes: [ … { path: '/page/:pageId', name: 'page', component: (resolve) => { require(['../pages/page.vue'], resolve) } }, … ] }) Vue-router:Params router/index.js <router-link :to="{ name: 'page', params: { pageId: id } }">連結⽂文 字</router-link>
  • 23. routes: [ … { path: '/404', name: 'unfound', component: (resolve) => { require(['../pages/unfound.vue'], resolve) } }, { path: '*', redirect: to => { return { name: 'unfound' } } } ] … Vue-router:Unfound Page router/index.js
  • 24. 狀狀態管理理:Vuex $ yarn add vuex … import store from './store' new Vue({ el: '#app', router, store, template: '<App/>', components: { App } }) main.js─ src/  ├ …  ├ store/   ├ modules/    ├ app.js    └ …   └ index.js  ├ …  Preference: Github: Vuejs/vuex
  • 25. Vuex Modules import Vue from 'vue' import Vuex from 'vuex' import app from './modules/app' … Vue.use(Vuex) export default new Vuex.Store({ modules: { app, … } }) store/index.js
  • 26. Vuex Modules const state = { isLoading: false … } const getters = { isLoading: state => state.isLoading … } const mutations = { [types.setLoading] (state, boolean) { state.isLoading = boolean }, … } store/modules/app.js
  • 27. Vuex Modules const types = { setLoading: 'app/setLoading', … } const actions = { setLodingAction ({commit}, boolean) { commit(types.setLoading, boolean) }, … } export default { state, getters, mutations, actions } store/modules/app.js
  • 28. Vuex mapGetters, mapActions import { mapGetters, mapActions } from 'vuex' export default { computed: mapGetters([ 'isLoading', … ]), methods: { ...mapActions([ 'setLodingAction', … ]), … } } *.vue computed: { isLoading: this.$store.state.app.isLoading } methods: { setLoadingMethod (value) { this.$store.commit('setLoading', value) // Commit mutations } }
  • 31. import Vue from 'vue' import VueResource from 'vue-resource' Vue.use(VueResource) export const pageResource = Vue.resource(api_link + '{/params}') … api/resource.js─ src/  ├ …  ├ api/   ├ resource.js   └ index.js  ├ …  溝通Server:Vue-resource $ yarn add vue-resource Preference: Github: vue-resource
  • 32. import * as resource from './resources' export const getPage = (id) => resource. pageResource.get({ params: id }) export const postPage = (object) => resource. pageResource.save(object) export const putPage = (id, object) => resource. pageResource.update({ params: id }, object) export const deletePage = (id) => resource. pageResource.delete({ params: id }) … api/index.js 溝通Server:Vue-resource
  • 33. import { getPage } from '../api' … export default { … methods: { fetchData () { let id = this.$route.params.pageId // vue-router params getPage(id).then(response => { response.json().then(json => { this.data = json }) }, (response) => { response.json().then(json => { this.errorMsg(json) }) }) } } } pages/*.vue Vue-resource:取得資料
  • 34. Vue-router:Data Fetching 取得資料顯⽰示在⾴頁⾯面上有兩兩種⽅方式: • 導入⾴頁⾯面之後獲取 • 導入⾴頁⾯面之前獲取 ๏ 需要載入(或進度條)畫⾯面,讓使⽤用者知道正在載入 ๏ 第⼆二種⽅方式在beforeRouteEnter取得資料,缺點是這個時候⾴頁 ⾯面未載入,不能使⽤用this取得Vue其他資料 ๏ 上⼀一⾴頁/下⼀一⾴頁時,這些⾴頁⾯面在v-for載入資料之前就先把卷軸定 位,所以router內建的scrollBehavior沒有⽤用。必須另外處理理。 ๏ 以下說明第⼀一種⽅方式
  • 35. import { mapGetters } from 'vuex' export default { computed: mapGetters([ 'initial', … ]), created () { this.fetchData() }, watch: { '$route' () { this.fetchData() } }, … } mixins/routeFetching.vue Component載入後取得數據 router有其他變動,取得數據 例例如params改變 Vue-router:Data Fetching
  • 36. Vue-router:Data Fetching pages/*.vue import routeLoading from '../mixins/routeFetching' export default { … mixins: [ routeLoading ] … } …
  • 37. 眉⾓角:Data Fetching順序 App.vue router-view 新⾴頁⾯面/重新整理理
 取得預先資料 created () 同時執⾏行行 initial = false 不執⾏行行fetchData vuex initial = false 已取得資料 initial = true watch initial變動 initial = true fetchData 切換不同route initial = true created () 執⾏行行
 initial = true fetchData 切換同⼀一route
 params變動 initial = true watch $route變動
 initial = true fetchData
  • 38. initial 是 App.vue最外⾯面那層獲取 資料之後(例例如辨別會員是否登入)
 ,由false → true import { mapGetters } from 'vuex' export default { computed: mapGetters([ 'initial', … ]), created () { this.startFetch(this.initial) }, watch: { '$route' () { this.startFetch(this.initial) }, 'initial' (value) { this.startFetch(value) } }, mixins/routeFetching.vue methods: { startFetch (initial) { if (initial) { this.fetchData() } } } } 眉⾓角:Data Fetching順序
  • 39. 眉⾓角:⾴頁⾯面Loading狀狀態 export default { … data () { return { loading: false } } … } mixins/routeFetching.vue
  • 40. <template> <div> <loading v-if="loading"></loading> <div v-else> // 顯⽰示的資料 </div> </div> </template> pages/*.vue 眉⾓角:⾴頁⾯面Loading狀狀態
  • 41. export default { … methods: { fetchData () { let id = this.$route.params.pageId // vue-router params this.loading = true // loading true getPage(id).then(response => { response.json().then(json => { this.data = json this.loading = false // loading false }) }, (response) => { response.json().then(json => { this.errorMsg(json) // in errorMsg redirect error. }) }) }, … } } pages/*.vue 眉⾓角:⾴頁⾯面Loading狀狀態
  • 42. 眉⾓角:ScrollPosition • 離開⾴頁⾯面之前,儲存scrollPosition • 偵測上⼀一⾴頁、下⼀一⾴頁啟動時機,popstate = true • loading = true、讀取本⾴頁資料 • popstate = false、loading = false • v-for讀取值產⽣生⾴頁⾯面 • 跳⾄至此⾴頁⾯面儲存的最後⼀一個scrollPosition • 如果沒有偵測到上⼀一⾴頁下⼀一⾴頁,loading = false
  • 43. import { mapActions } from 'vuex' export default { … beforeRouteLeave (to, from, next) { this.savePostionAction({ path: from.path, pos: window.scrollY }) next() }, methods: { ...mapActions([ 'savePostionAction' ]), … } } mixins/routeFetching.vue 眉⾓角:ScrollPosition
  • 44. export default { … beforeMount () { … let self = this window.onpopstate = function (event) { self.setPopstateAction(true) } }, … methods: { ...mapActions([ 'setPopstateAction', … ]), … } } App.vue 眉⾓角:ScrollPosition
  • 45. pages/*.vue export default { … methods: { fetchData () { let id = this.$route.params.pageId // vue-router params this.loading = true // loading true getPage(id).then(response => { response.json().then(json => { this.data = json this.getPagePosition() // detect page position }) }, (response) => { response.json().then(json => { this.errorMsg(json) // in errorMsg set loading false }) }) }, … } } 眉⾓角:ScrollPosition
  • 46. mixins/routeFetching.vue … export default { … computed: mapGetters([ 'popstate' … ]), methods: { getPagePosition () { let path = this.$route.path let pagePositions = this.savedPostions.filter(object => { if (object.name === name) { return object } }) // 接下⾴頁 眉⾓角:ScrollPosition
  • 47. mixins/routeFetching.vue let length = pagePositions.length if (length > 0 && this.popstate) { let lastPosition = pagePositions[length - 1] this.setPopstateAction(false) setTimeout(function () { window.scrollTo(0, lastPosition.pos) }, 10) } this.loading = false } … } } 眉⾓角:ScrollPosition
  • 49. Ending & QA Thanks for listening.