前言:學習Vue.js高仿餓了麼課程過程當中,總結了這個Web App項目從準備到開發完畢本身以爲很重要的知識點。這一篇主要介紹:項目準備、頁面骨架開發、header組件開發。javascript
項目github地址:https://github.com/66Web/ljq_eleme,歡迎Star。css
App | header |
1、項目分析&學習目標 |
當前最火的MVVM框架html
高仿上線外賣App標準來開發前端
開發一個webApp的全流程vue
以線上生產環境的代碼質量做標準html5
功能技術分析java
學習目標node
學習內容react
2、Vue.js介紹 |
近年來前端開發趨勢webpack
(前者傳統MVC:更新數據會刷新頁面 後者前端MV*: 向後端REST API異步請求數據,局部刷新頁面)
MV* —— MVC、MVP、MVVM
MVVM框架
View ViewModel Model
視圖 通信 數據
對比Anglar React
vue.js 核心思想
組件設計原則
3、Vue-cli開啓Vue項目 |
Vue-cli 是Vue的腳手架工具 —— 幫助寫好Vue基礎代碼的工具
安裝使用
(sudo) npm install -g vue-cli // sudo:mac環境下有關管理權限的命令
vue init webpack my-project
項目文件
→ scripts: 配置一些須要執行的命令
→ dependencies:開發環境中的依賴
→ devdependencies: 編譯過程當中的依賴
項目運行
npm run dev
【小知識點】sublime自動格式化 —— Command+option+L 或 Control+alt+L |
import Hello from './compoments/Hello'
export default{ components: { Hello //es6語法 至關於 'Hello': Hello
} }
<hello><hello>
開發時的Webpack配置與編譯
→ 配置默認識別的路徑
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
}
4、準備工做 |
圖標字體制做
項目目錄設計
【css的stylus語法】
npm install stylus stylus-loader --save-dev
|
<link rel="stylesheet" type="text/css" href="static/css/reset.css">
先後端分離
{ "seller":{} //商家相關字段
"goods":{} //商品相關字段
"rattings":{} //評論相關字段
}
webpack.dev.conf.js中配置
const express = require('express')//開啓一個node server
const app = express() //定義一個對象,包含express返回的數據
var appData = require('../data.json') //定義一個對象引入data數據
var seller = appData.seller; var goods = appData.goods; var ratings = appData.ratings; app.use('/api', apiRoutes); //調用app對象
before(app) { app.get('/api/seller', (req, res) => { res.json({ errno: 0, //錯誤碼:其實是業務方根據業務本身定的
data: seller }) //接口返回json數據,上面配置的數據seller就賦值給data請求後調用
}), app.get('/api/goods', (req, res) => { res.json({ errno: 0, data: goods }) }), app.get('/api/ratings', (req, res) => { res.json({ errno: 0, data: ratings }) }) }
查看json數據
【Google安裝第三方插件】
—— 轉載自【小白白打醬油博客】 |
5、頁面骨架開發 |
移動端視口
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
App.vue 中把頁面拆爲三個區塊
<div id="app">
<div class="header">header</div>
<div class="tab">tab</div>
<div class="content">content</div>
</div>
而後,分別抽成一個組件,引用 —— 全部組件自定義標籤名不可與html自己標籤重合 'v-header': header
移動端經典佈局 flex
<div class="tab"> <div class="tab-item">商品</div> <div class="tab-item">評論</div> <div class="tab-item">商家</div> </div>
.tab
display: flex
width: 100%
height: 40px
line-height: 40px
.tab-item
flex:1
text-align: center
vueRouter
<router-link :to="{ path: '/goods' }">商品</router-link>
<router-view></router-view>
main.js 中設置單頁面應用路由的【掛載組件】—— 默認App.vue 也能夠自定義組件如layout.vue
/* eslint-disable no-new */
new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
配置【路由map】:router->index.js
export default new Router({ mode: 'history', routes: [ { path: '/', redirect: '/goods',//默認頁面重定向
}, { path: '/goods', component: goods }, { path: '/ratings', component: ratings }, ] })
#app .tab .tab-item>a{ display: block; font-size: 14px; color: rgb(77, 85, 93);
} #app .tab .tab-item>a.router-link-active{ color: rgb(240, 20, 20) }
1像素border實現
.tab{ border-bottom: 1px solid rgba(7,17,27,0.1) }
【PC開發中用手機實時預覽的小技巧】
|
<div class="tab border-1px">
border-1px($color)
position: relative
&:before
display: block
position: absolute
left:0
top: 0
width: 100%
border-bottom: 1px solid $color
content: ''
&:after
display: block
position: absolute
left:0
bottom: 0
width: 100%
border-top: 1px solid $color
content: ''
@media(-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)//DPR爲1.5的縮放0.7倍
.border-1px
&:before
-webkit-transform: scaleY(0.7)
transform:scaleY(0.7)
&:after
-webkit-transform: scaleY(0.7)
transform:scaleY(0.7)
@media(-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2)//DPR爲2的縮放0.5倍
.border-1px
&:before
-webkit-transform: scaleY(0.5)
transform:scaleY(0.5)
&:after
-webkit-transform: scaleY(0.5)
transform:scaleY(0.5)
@import"./mixin" //import後無空格
@import"./icon"
@import"./base"
main.js: import '@/common/stylus/index.styl' //import後有空格
6、header組件開發 |
vue-resource
npm install vue-resource --save
注意:每次install完插件等以後須要從新啓動項目
import VueResource from 'vue-resource' Vue.use(VueResource)
以後就能夠在項目任何地方:使用 this.$http 命令
const ERR_OK = 0; //定義常量,加強程序可讀性
data() { return { seller:{} //維護數據 seller
} }
created: function () { this.$http.get('/api/seller') //發送get請求,
.then(function(res){ //.then方法 請求完成後調用
//第一個函數是請求成功後方法
}, function (err) { //第二個函數是請求失敗後方法
}) }
使用ES6 箭頭函數:箭頭函數先後必須有空格
created: function () { this.$http.get('/api/seller') .then((res) => { res = res.body //拿到response返回的promise對象的body(Data Object)
if (res.errno === ERR_OK) { this.seller = res.data; //console.log(this.seller)
} }, (err) => { }) }
外部組件
<v-header :seller="seller"></v-header>
props: {
seller: {
type: Object
}
}
:src="seller.avatar"
{{seller.name}}
<div class="support" v-if="seller.supports">
<span class="icon" :class="this.classMap[seller.supports[0].type]"></span>
<span class="text">{{seller.supports[0].description}}</span>
</div>
created (){ this.classMap = ['decrease','descount','guarantee','invoice','special'] }
<span class="icon" :class="this.classMap[seller.supports[0].type]"></span>
bg-image($url)
background-image: url($url+"@2x.png")
@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
background-image: url($url+"@3x.png")
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
.background position: absolute top: 0 left: 0 width: 100% height: 100% z-index: -1 filter: blur(10px)
詳情彈層頁
<div class="detail" v-show="detailShow"></div>
data () { return { detailShow: false //經過改變數據detailShow 的true/false,控制元素的顯示/隱藏
} }
<div class="bulletin-wrapper" @click="showDetail>
methods: { showDetail () { this.detailShow = true; } }
【Css Sticky footers佈局】
|
Star組件抽象
<div class="star" :class="starType">
<span v-for="itemClass in itemClasses" :key="itemClass.value" :class="itemClass" class="star-item">
</span>
</div>
props:{
size: {
type: Number
},
score: {
type: Number
}
}
@import "../../common/stylus/mixin"
.star
.star-item
display: inline-block
background-repeat: no-repeat
&.star-48
.star-item
width: 20px
height: 20px
margin-right: 22px
background-size: 20px 20px
&:last-child
margin-right: 0
&.on
bg-image('star48_on')
&.half
bg-image('star48_half')
&.off
bg-image('star48_off')
&.star-36
.star-item
width: 15px
height: 15px
margin-right: 16px
background-size: 15px 15px
&:last-child
margin-right: 0
&.on
bg-image('star36_on')
&.half
bg-image('star36_half')
&.off
bg-image('star36_off')
&.star-24
.star-item
width: 10px
height: 10px
margin-right: 3px
background-size: 10px 10px
&:last-child
margin-right: 0
&.on
bg-image('star24_on')
&.half
bg-image('star24_half')
&.off
bg-image('star24_off')
const LENGTH = 5; const CLS_ON = 'on'; const CLS_HALF = 'half'; const CLS_OFF = 'off'; computed: { starType() { return 'star-' + this.size; //根據size 計算出動態的class
}, itemClasses() { let result = []; let score = Math.floor(this.score*2)/2;
let hasDecimal = score % 1 !== 0; let integar = Math.floor(score); for(let i=0; i<integar; i++){ result.push(CLS_ON) //根據score 在itemClasses中push進對應個數的全亮星星class
} if(hasDecimal) { result.push(CLS_HALF);//判斷若是有半分或不足5分的,push進半星class和灰色星class
} while (result.length < LENGTH) { result.push(CLS_OFF) } return result; //根據itemClasses中對應的class顯示對應的星星圖片
} }
小標題自適應線
<div class="title">
<div class="line"></div>
<div class="text">優惠信息</div>
<div class="line"></div>
</div>
.title
display: flex
width: 80%
margin: 30px auto 24px auto
.line
flex: 1
position: relative
top: -6px
border-bottom: 1px solid rgba(255, 255, 255, 0.2)
.text
padding: 0 12px
font-size: 14px
【Postcss工具】
|
過渡動畫組件 transition
<transition name="fade">
<div class="detail">
</transition>
.detail
opacity: 1
background: rgba(7, 17, 27, 0.8)
&.fade-enter-active, &.fade-leave-active
transition: all 0.5s ease
&.fade-enter, &.fade-leave-active
opacity: 0
background: rgba(7, 17, 27, 0)
iPhone手機背景模糊效果
backdrop-filter: blur(10px) // PC端和其它手機看不出效果
注:項目來自慕課網