Más contenido relacionado La actualidad más candente (20) Similar a 以Vue開發電子商務網站
架構與眉角 (20) 以Vue開發電子商務網站
架構與眉角2. • Mayu Chen
• Frontend Developer of gelovery.com / patio.tw
• windfish27@gmail.com
๏ 以下範例例為經驗分享
๏ 感謝後端⼤大⼤大的⽀支援...m(_ _)m
About me
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
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
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
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
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
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:取得資料
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
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順序
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狀狀態
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