vue + vue-router + vue-resource + es6 + stylus + webpack 高仿饿了么外卖App商家详情
VUE高仿餓了么app
本項目github地址:https://github.com/motysla/eleme.git
VUE 搭建簡介
剛學習了VUE高仿餓了么app課,記錄課的要點,鞏固知識。
VUE 優勢
Vue.js 是一個用于創建 web 交互界面的。其特點是
簡潔 HTML 模板 + JSON 數據,再創建一個 Vue 實例,就這么簡單。 數據驅動 自動追蹤依賴的模板表達式和計算屬性。 組件化 用解耦、可復用的組件來構造界面。 輕量 ~24kb min+gzip,無依賴。 快速 精確有效的異步批量 DOM 更新。 模塊友好 通過 NPM 或 Bower 安裝,無縫融入你的工作流。VUE 搭建工具
借用express + data 構建擬后臺
vue 1.0 express vue.router vue.rescrouse better-scroll lessCSS 使用的要點
1像素邊框制作
設備上像素 = 樣式像素 * 設備縮放比例
屏幕寬度 320px 480px 640px 縮放比例 1 1.5 2當樣式像素一定時,因手機有320px,640px等.各自的縮放比差異,所以設備顯示像素就會有1Npx,2Npx.為保設計稿還原度,解決就是用media + scale.
.border(@borderColor){position: relative;&::after{content: "";position: absolute;bottom: 0;left: 0;width: 100%;border-top: 1px solid @borderColor;} }@media (min-device-pixel-ratio: 1.5) {.border{&::after{transform: scaleY(0.7);}} }@media (min-device-pixel-ratio: 2) {.border{&::after{transform: scaleY(0.5);}} }
通過查詢它的縮放比,在媒體寬為1.5倍時, round(1px?1.5 / 0.7) = 1px 在媒體寬為2倍時, round(1px?2 / 0.5) = 1px.
自適應寬
在商品路由中,導航寬度固定80px的,因為手機分辨率大小不一,所以食物詳情自適應.解決就是flex布局.
css
html
<div class="food"><section class="nav"></section><section class="foodList"></section> </div>
在父元素設彈性布局,導航里設彈性為0,定寬為80px.商品食物詳情彈性為1.就適應寬度變化.
Sticky footer
做商家彈出頁時,信息高度是無法預定的,有可能溢出window高度,也可能少于window高度,但底部按鈕,當信息高度少于window高度,要固定在底部40px.解決就是用sticky footer布局
css
html
<div class="showDetil"><section class="sellerDetil"></section><section class="btn"></section> </div>
父元素高相同window高,信息最小高就相同window高,按鈕這時就溢出了.
再設置底的填充,底內邊距高就是按鈕的高. 按鈕在用相對定位,定在信息的底填充里.
因信息最少高度是100%,所按鈕要不釘在底部了.要不溢出.
自適相等寬高
在食物彈出頁.設計圖食物圖的寬高是相等,每張圖的寬高比例有可能有區別,但也要做自適應.解決就是用padding邊距.
css
html
<div class="imgs"><img src="..." class="image"> </div>
在父元素,邊距的長是取決去寬的,所其寬度與邊距的長是相等的.
在把高設為0,寬為100%,上邊距100%,上邊據就盒子的高.盒子是為正形.
子元素設寬與高為100%,那也是正形.
VUE要點
小圖標的編選
根據后臺輸出的數據,判定顯示那個的圖標.這vue典型的數據.驅動.解決是使用:class困綁數據
html
js
<script type="text/javascript">export default{data() {return {classmap: ['decrease', 'discount', 'guarantee', 'invoice', 'special']};}} </script>css
<style type="text/less"> .bgimg(@imgs) {background-image: url('@imgs+".png"') 0 0 no-repeat ~'/' 100% 100%; }.decrease{display: inline-block;height: 12px;width: 12px;.bgimg('decrease_3');}.discount{display: inline-block;height: 12px;width: 12px;.bgimg('discount_3');}.guarantee{display: inline-block;height: 12px;width: 12px;.bgimg('guarantee_3');}.invoice{display: inline-block;height: 12px;width: 12px;.bgimg('invoice_3');}.special{display: inline-block;height: 12px;width: 12px;.bgimg('special_3');} </style>
通過v-for,遍歷數據,所以date.type得到數據并判斷類型.然后通classmap數組判定綁那個class.來加圖標.
小球動畫
點擊加食物時,觸動小球彈出的動畫,小球的落點是在車的中央.但起點是根各個節點位子而又差別的.解決使用transitions + events + dispatch事件冒泡
cartcontrol子組件
html
js
<script type="text/javascript"> export default {props: {food: {type: Object}},methods: {addCart(event) {if (!this.food.count) {Vue.set(this.food, 'count', 1);this.food.count = 1;} else {this.food.count++;};this.$dispatch('cart.add', event.target);},decreaseCart() {if (this.food.count) {this.food.count--;};}} }; </script>
在加食物,觸發了addCart事件,設用set方法給數據加屬性,并使cart.add事件冒泡出去,event.target作為事件參數,即節點冒泡出去.
goods父組件
html
js
<script>export default {methods: {_drop(target) {this.$refs.shop.drop(target);}},events: {'cart.add'(target) {this._drop(target);}},components: {shop,cartcontrol,food}}; </script>
在冒泡被events鉤子監聽,與觸動_drop方法,通過接口獲得購物車組建的事件,就把control組建event.target傳入購物車組建的事件,及把control節點傳入了shop組建.
shop組建
html
js
<script type="text/javascript">export default {data() {return {balls: [{show: false},{show: false},{show: false},{show: false},{show: false}],dropBalls: [],fold: true};},methods: {drop(el) {for (var i = 0; i < this.balls.length; i++) {let ball = this.balls[i];if (!ball.show) {ball.show = true;ball.el = el;this.dropBalls.push(ball);return;};};}},transitions: {drop: {beforeEnter(el) {let count = this.balls.length;while (count--) {let ball = this.balls[count];if (ball.show) {let rect = ball.el.getBoundingClientRect();let x = rect.left - 32;let y = -(window.innerHeight - rect.top - 22);el.style.display = '';el.style.transform = `translate3d(0,${y}px,0)`;let inner = el.getElementsByClassName('inner-hook')[0];inner.style.transform = `translate3d(${x}px,0,0)`;}}},enter(el) {let rf = el.offsetHeight;this.$nextTick(() => {el.style.transform = 'translate3d(0,0,0)';let inner = el.getElementsByClassName('inner-hook')[0];inner.style.transform = 'translate3d(0,0,0)';});},afterEnter(el) {let ball = this.dropBalls.shift();if (ball) {ball.show = false;el.style.display = 'none';};}}},components: {cartcontrol}}; </script>
傳入節點數據,過渡執行前可插入一個beforeEnter事件,通getBoundingClientRect定位.動畫執行后可插入一個afterEnter,還原小球
接后臺數據
與后臺的配合,通過插vue.resource + express 連接得到數據
dev-server
通過與配和框架express,連到數據。并放在api里.
main.js
引進插件和使用,在全局也可以使用.
header組建
在框架的鉤子,及創建就通過http.get連到express發的數據,通參數response得到.body表示數據以json格式響應.注意接收數據是異步實現,如果出報錯undefined,可用v-if判斷,當獲取數據后在渲染.
評分類換
用戶的滿意度有,推薦與吐槽再加上全部,就三個分頁,分頁通過按鈕切換.如何制作呢?解決是使用v-show進判斷.
ratingselect子組件
html
js
<script type="text/javascript"> export default{props: {ratings: {type: Array,default() {return [];}},selectType: {type: Number,default: 2},onlyContent: {type: Boolean,default: true},desc: {type: Object,default() {return {all: '全部',positive: '滿意',negative: '不滿意'};}}},methods: {select(type) {this.selectType = type;this.$dispatch('ratingtype.select', type);},toggleContent() {this.onlyContent = !this.onlyContent;this.$dispatch('ratingtype.toggleContent', this.onlyContent);}} }; </script>滿意是為:0,不滿意是為:1,全部是為:2.
因在點擊切換按鈕,觸發方法,通過傳入參數來替換數據,數據selectType賦值等于參數.參數是自義定,然而可以在參數下功夫,然用冒泡將數據分出.
food父組件
html
js
<script type="text/javascript">import Vue from 'vue';import ratingselect from 'components/ratings/ratingselect';const POSITIVE = 0;const NEGATIVE = 1;const ALL = 2;export default {data() {return {showFlage: false,selectType: ALL,onlyContent: true,desc: {all: '全部',positive: '推薦',negative: '吐槽'}};},methods: {needShow(type, text) {if (this.onlyContent && !text) {return false;}if (this.selectType === ALL) {return true;} else {return type === this.selectType;}}},events: {'ratingtype.select'(type) {this.selectType = type;this.$nextTick(() => {this.scroll.refresh();});},'ratingtype.toggleContent'(onlyContent) {this.onlyContent = onlyContent;this.$nextTick(() => {this.scroll.refresh();});}},components: {ratingselect}}; </script>
在事件鉤子上,實行監聽,把冒泡觸發并賦值,數據就得到.在遍歷數據,用v-show進行判斷.
VUE雜項
過渡流程
只在v-if,v-show,v-for觸動節點的變動效果
當 show 屬性改變時,Vue.js 將相應地插入或刪除元素,按照如下規則改變過渡的 CSS 類名:
如果 show 變為 false,Vue.js 將:
調用 beforeLeave 鉤子;
添加 v-leave 類名到元素上以觸發過渡;
調用 leave 鉤子;
等待過渡結束(監聽 transitionend 事件);
從 DOM 中刪除元素并刪除 v-leave 類名;
調用 afterLeave 鉤子。
如果 show 變為 true,Vue.js 將:
調用 beforeEnter 鉤子;
添加 v-enter 類名到元素上;
把它插入 DOM;
調用 enter 鉤子;
強制一次 CSS 布局,讓 v-enter 確實生效。然后刪除 v-enter 類名,以觸發過渡,回到元素的原始狀態;
等待過渡結束;
調用 afterEnter 鉤子。
better-scroll
節點溢滿時,是設計稿沒有滾動條的,要上下移動.解決使用better-scroll插件.
html
js
<script type="text/javascript">ready() {this.$nextTick(() => {if (!this.scroll) {this.scroll = new Bscroll(this.$els.seller, {click: true});} else {this.scroll.refresh();}});}, </script>
但父元素設置溢出隱藏,可用插件的移動顯出子節點超的內容.要在節點放個接口,使用框架鉤子,創建betterScroll事例,那藏的內容通立體相上下移.better-scroll是調用樣式的translate是子節點上下引動.
less樣式處理
通過引入樣式,有是會錯誤.解決使用設置標簽
處理器會識別到標簽的樣式類別,編譯樣式.
esLint
在使用eslint語法校驗時,經常報錯,但可以在eslintrc設置進行忽略.
no mixed spaces and tabs
是把標簽縮進與空格捆和使用,解決是可用tab代替空格.
Expected indentation of 2 space characters but found 3 indent
'indent': 0,
'space-before-function-paren': 0
設置縮進空行.
defined but never use
可在前加注銷
/?eslint-disable no-unused-vars?/
后序
要靈活的用vue,先要處理好數據的邏輯.?然而要懂得基本的數據傳遞屬性.
子組件傳給父組件- 可以用接口ref;也可以子組件的冒泡把數據傳去,父組件用鉤子events監聽并接到數據. 父組件傳給子組件- 可以在子組件props鉤子,接收父組件的傳遞.也可以父組件用ref接口調用子組件的方法,并把數據傳入方法去.實戰是最重要.
總結
以上是生活随笔為你收集整理的vue + vue-router + vue-resource + es6 + stylus + webpack 高仿饿了么外卖App商家详情的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android和ios报价,安卓和iOS
- 下一篇: html5倒计时秒杀怎么做,vue 设