Vue仿餓了麼app項目總結

前言

這是我的第一個基於Vue項目的作品,目的是把之前的前端知識累積加上目前流行的前端框架,以項目的形式展示出來。
大家在學習Vue的時候,可以將此項目作爲學習Vue框架的一個模板
cmd-markdown-logo

源碼地址

源碼:https://github.com/shifengming/sell

實現功能

  • Goods、Ratings、Seller 組件視圖均可上下滾動

  • 商品頁 點擊左側menu,右側list對應跳轉到相應位置

  • 點擊list查看商品詳情頁,父子組件的通信

  • 評論內容可以篩選查看

  • 購物車組件,包括添加刪除商品及動效,購物控件與購物車組件之間爲兄弟組件通信,點擊購物車圖標,展示已選擇的商品列表

  • 商家實景圖片可以左右滑動

  • loaclStorage 緩存商家信息(id、name)

使用的技術棧

vue2.0 + vue-router + vue-cli + axios + stylus + flex佈局 + es6 + eslint + webpack2 

項目目錄

  • app.vue
  • header.vue頭部組件
  • star.vue星星評分組件
  • goods.vue商品組件
  • shopcart.vue購物車組件,包括小球飛入購物車動畫
  • cartcontrol.vue購買加減圖標控件–選中數量返回給父組件goods,goods響應後,重新計算選中的數量,將數據發送給購物車組件
  • food.vue商品詳情頁
  • ratingselect.vue評論內容篩選組件
  • ratings.vue評論組件
  • seller.vue商家組件
  • split.vue關於分割線組件

項目結構

common文件夾存放的是通用的css和fonts
componets文件夾用來存放Vue組件
router文件夾存放Vue組件
build文件是webpack的打包編譯配置文件
config文件夾存放的是一些配置項,比如我們服務器訪問的端口配置等
dist該文件一開始是不存放,在項目經過build之後纔會生成
Prod.server.js該文件是測試模擬的服務器配置,用來運行dist裏面的文件
config/index.js中,build對象中添加一條端口設置port:9000
App.vue根組件,所有的子組件都將在這裏被引用
Index.html整個項目的入口文件,將會引用我們的根組件App.vue
Main.js入口文件的js邏輯,在webpack打包之後將被注入到index.html

搭建Vue的運行環境

1,首先是安裝node

端開發框架和環境都是需要Node.js,先安裝node.js開發環境,vue的運行是依賴於node的npm的管理工具來實現的,下載地址(https://nodejs.org/en/)

2,查看node的版本號

下載好node之後,打開cmd管理工具,輸入node -v,回車,查看node版本號,出現版本號則說明安裝成功

node -v

3,安裝淘寶npm鏡像

由於npm是國外的,使用起來比較慢,這裏使用淘寶cnpm鏡像來安裝vue,淘寶的cnpm命令管理工具可以代替默認的npm管理工具

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

4,安裝全局vue-cli腳手架

淘寶鏡像安裝之後,我們就可以全局vue-cli腳手架,輸入命令:cnpm install -g vue-cli回車;驗證是否安裝成功,在命令輸入vue,出來vue的信息,及說明安裝成功

cnpm install -g vue-cli

5,初始化項目

Vue init webpack demo

(demo指的是你新建的項目名稱/文件名稱)

6,運行項目

npm run dev

然後就會出來http://localhost:8080 把這個網址複製到瀏覽器中打開

7,發佈代碼

npm run build

發佈完代碼後會生成dist目錄,保存着項目的所有可運行的代碼

開發過程中重點問題總結

better-scroll

Better-scroll可能是目前最好用的移動端滾動插件
插件在移動端使用時需要設置 click:true,否則移動端滑動無效


分開設置css樣式

1,圖標icon.css–文字圖標樣式,通過icomoon.io網站,將svg圖片轉成文字圖標樣式

2,公共base.css–處理設備像素比的一些樣式,針對border-1px問題,不同設備像素比,顯示的線條粗細不同

3,工具mixin.css–設備border-1px樣式和背景樣式


sticky-footer佈局

在這個項目的header組件的詳情頁採用stick-footer佈局

特點:如果頁面內容不夠長,頁腳塊粘貼在視窗底部;
如果內容足夠長,頁腳塊會被內容向下推送

實現:父級 position:fixed,內容設爲padding-bottom:64px,頁腳相對定位,margin-top:-64px,clear:both爲了保證兼容性,父級要清除浮動

cmd-markdown-logo

參考:https://www.jianshu.com/p/3853024d5838


要求自適應佈局

1,左側寬度固定,右側寬度自適應

左側固定width:80px,右側自適應

parent:
    display:fiexd;
child-left:
    flex:0 0 80px
child-right:
flex:1

2,元素寬度自適應設備寬度,且元素要求等寬高樣式

商品詳情頁面的商品圖片展示樣式

.img_header {
    position:relative
    width:100% // width是 設備寬度
    height:0
    padding-top:100% // 高度設爲0,使用padding撐開
    .img {
        position:absolute //定位佈局
        top:0
        left:0
        width:100%
        height:100%
    }
}

背景模糊效果

filter:blur(10px)

注意,所有在內的子元素也會模糊,包括文字,所以採用定位佈局,背景單獨佔用一個層,ios有一個設置backdrop-filter:blur(10px),只會模糊背景,但不支持android

cmd-markdown-logo


transition過渡

在購買控件中使用transition過渡效果,實現添加減少按鈕的動效,和小球飛入購物車的動效(模仿貝塞爾曲線的效果)

name-String用於自動生成css過渡類名

name: ‘fade’ 將自動拓展爲.fade-enter,.fade-enter-active等。默認類名爲 “v”

fade-enter
fade-enter-active
fade-leave
fade-leave-active

seller組件

問題一:seller頁面中商品商家實景圖片橫向滾動

解決方案:每個 li 要 display:inline-block,因爲width不會自動撐開父級ul,所以需要將計算後的寬度賦值給ul的width,(每一張圖片的width+margin)*圖片數量-一個margin,因爲最後一張圖片沒有margin

同時new BScroll裏面要設置scrollX: true,eventPassthrough: ‘vertical’, // 滾動方向橫向

cmd-markdown-logo

問題二:打開seller頁面,無法滾動

問題分析:出現這種現象是因爲better-scroll插件是嚴格基於DOM的,數據是採用異步傳輸的,頁面剛打開,DOM並沒有被渲染,所以,要確保DOM渲染了,才能使用 better-scroll,

解決方案:用到mounted鉤子函數,同時必須搭配this.$nextTick()

cmd-markdown-logo
問題三:在seller頁面,刷新後,無法滾動

問題分析:出現這種情況是因爲mounted函數在整個生命週期中只會只行一次

解決方案:使用watch方法監控數據變化,並執行滾動函數 this._initScroll();this._initPicScroll();


緩存數據

//將頁面信息保存到localStorage裏
export function saveToLocal(id, key, value) {
  let seller = window.localStorage.__seller__;//新定義一個key值_store_,存放要保存的數據對象
  if (!seller) { // 不存在Seller
    seller = {};
    seller[id] = {};
  } else {
    seller = JSON.parse(seller);//string格式-->json格式
    if (!seller[id]) {
      seller[id] = {};
    }
  }
  seller[id][key] = value;
  window.localStorage.__seller__ = JSON.stringify(seller);//將json格式轉成String格式,存放到window.localStorage._store中
};


//將localStorage信息設置到頁面中
export function loadFromLocal(id, key, def) {
  let seller = window.localStorage.__seller__;
  if (!seller) {//開始是沒有的,因爲沒有點擊事件,所以顯示默認數據
    return def;
  }
  seller = JSON.parse(seller)[id];//將json格式-->String格式
  if (!seller) {
    return def;
  }
  let ret = seller[key];
  return ret || def;
};

goods,ratings,seller組件之間切換時會重新渲染

在 app.vue 內使用 keep-alive,保留各組件狀態,避免重新渲染

<keep-alive>
    <router-view :seller="seller"></router-view>
</keep-alive>

vue-router

使用<router-link>組件完成導航,<router-link> 默認會被渲染成一個 <a> 標籤,但必須使用 to屬性,指定連接
// app.vue
 <!-- 導航 -->
<router-link to="/home">home</router-link>
<router-link to="/about">about</router-link>

<!-- 路由出口 組件渲染容器 -->
<router-view></router-view>
// router: index.js

import Vue from 'vue';
import Router from 'vue-router';
import goods from 'components/goods/goods.vue';
import ratings from 'components/ratings/ratings.vue';
import seller from 'components/seller/seller.vue';

Vue.use(Router);

const routes = [{
  path: '/',
  redirect: '/goods'
}, {
  path: '/goods',
  component: goods
}, {
  path: '/ratings',
  component: ratings
}, {
  path: '/seller',
  component: seller
}];

axios

在vue1.x的時候,vue的官方推薦HTTP請求工具是vue-resource,但是在vue2.0的時候將推薦工具改成了axios


組件間通訊

vue是組件式開發,所以組件間通訊是必不可少的

  • 父傳子: props

  • 子傳父: $emit

  • 兄弟通訊

       event bus: 利用一箇中間組件來作爲信息傳遞中介
    
       vuex: 信息樹
    

父傳子: props

子組件定義 props 來接受父組件傳遞來的數據對象

// 父組件
<v-header :seller="seller"></v-header>

// 子組件 header.vue
props: {
  seller: {
    type: Object
  }
}

子傳父: $emit

如果是子組件想傳遞數據給父組件,需要派發自定義事件,使用 $emit 派發

父組件使用v-on接收監控(v-on可以簡寫成@)

// 子組件 ratingSelect.vue,派發自定義事件select,將type數據傳給父級
this.$emit('select', type);
this.$emit('toggle', this.onlyContent2);


// 父組件 food.vue 在子組件的模板標籤裏,使用v-on監控toggleContent傳過來的數據
<ratingselect @select="selectRating" @toggle="toggleContent"></ratingselect>

非父子組件之間通信

1,大型項目可以用 Vue官方推薦的vuex

2,EventBus

3,子組件A $emit 派發具體事件,由父組件 @ 監聽得到數據

父組件再利用 $refs 直接訪問子組件B的方法,間接實現數據從子組件A傳遞至子組件B


組件提取管理

將相同樣式或功能的區塊單獨提出來,作爲一個組件。
另外組件中用到的圖片等資源就近維護,即可以考慮在組件文件夾中新建images文件夾。

抽離組件遵循原則:
要儘量遵循單一職責原則,複用性更高,不要設置額外的margin等影響佈局的東西


打開app應用,默認顯示 goods 頁面內容

想默認顯示goods頁面內容,有兩種方法,一種是利用重定向,另一種是利用vue-router的導航式編程

1,重定向

  routes: [
    {
      path: '/',
      redirect: '/goods'  //重定向
    },
    {
      path: '/goods',
      name: 'goods',
      component: goods
    },{
      path: '/ratings',
      name: 'ratings',
      component: ratings
    },{
      path: '/seller',
      name: 'seller',
      component: seller
    }
  ]

2,導航式編程

router.push('/Goods');

關於ESlint

eslint 是一個js代碼風格檢查器,配合vue-cli腳手架中的熱更新,可以很方便的定位和提示錯誤。在公司多人協作開發時可以確保代碼風格保持一致,可以很方便的閱讀他人的代碼

手機訪問項目

1、在config文件夾中的index.js中的host選項,將本地localhost改爲0.0.0.0
cmd-markdown-logo
2、在cmd中輸入ipconfig查看本地IP,
cmd-markdown-logo

4、端口號訪問(http://192.168.0.110:8080),將這個網址複製到網頁版“草料二維碼”中,用QQ掃碼訪問即可

最後

如果本文對你有幫助得話,給本文點個贊❤️❤️❤️

歡迎大家加入,一起學習前端,共同進步!
cmd-markdown-logo
cmd-markdown-logo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章