SlideShare a Scribd company logo
1 of 49
Download to read offline
以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.

More Related Content

What's hot

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
 

What's hot (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 to 以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 to 以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
 

Recently uploaded

20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...Akihiro Suda
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecturerahul_net
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLionel Briand
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identityteam-WIBU
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 

Recently uploaded (20)

20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecture
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and Repair
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identity
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 

以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.