1. 程式人生 > >餓了麼--vue專案總結

餓了麼--vue專案總結

來遲了來遲了,早就應該動手寫了,無奈卡在webpack的學習中,深陷泥潭。

github原始碼地址:餓了麼專案原始碼

餓了麼專案包含以下三個方面的技術點,以及所瞭解的知識。
1.    流程及開發方法:

  •     元件化、模組化的開發模式
  •     學會模擬json後端資料,前後端分離開發
  •     瞭解webpack的打包原理

2.    第三方元件

  • 學會使用vue-router開發單頁應用
  • 學會使用vue-resource與後端資料互動
  • 學會如何在Vue.js框架裡和第三方JS外掛互動

3.     設計思想與模式

  • 瞭解移動端裝置畫素比的概念
  • 學會解決移動端1px邊框問題
  • 學會移動端經典的css sticky footer佈局
  • 學會flex彈性佈局

第一個方面從webpack設定入手:

在build/webpack.base.conf.js檔案下,可以看到基本的webpack設定(出入口檔案位置,字尾補充以及別名等):

module.exports = {
  context: path.resolve(__dirname, '../'),
  // webpack編譯的入口檔案
  entry: {
    app: './src/main.js' 
  },
  output: {
    path: config.build.assetsRoot,
    // 生成的檔名字
    filename: '[name].js',
    // 請求的靜態資源的絕對路徑
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    // 自動補全檔案字尾
    extensions: ['.js', '.vue', '.json'],
    // 別名,只針對於js庫,css的引入還是要寫相對路徑,不能省略
    alias: {
      '@': resolve('src'),
      // vue:'vue/dist/vue.js',
      'components': path.resolve(__dirname, '../src/components'),
      'common': path.resolve(__dirname, '../src/common'), //當在js檔案中import其他檔案時路徑直接寫commont相當於../src/common
    }
  },

然後在webpack.dev.conf.js檔案中,設定了資料所在的位置,用於模擬後端資料的獲取。

// 資料獲取
var express = require('express')  // express 是nodejs框架
var apiServer = express()  
var bodyParser = require('body-parser')  
apiServer.use(bodyParser.urlencoded({ extended: true }))  
apiServer.use(bodyParser.json())  
var apiRouter = express.Router()  
var fs = require('fs')  
apiRouter.route('/:apiName') //介面路徑  
  .all(function (req, res) {  
    fs.readFile('./db.json', 'utf8', function (err, data) {  //讀取介面檔案  
      if (err) throw err  
      var data = JSON.parse(data)  
      if (data[req.params.apiName]) {  
        res.json(data[req.params.apiName])  
      }  
      else {  
        res.send('no such api name')  
      }  
  
    })  
  })  
  
// 資料所在的位置
apiServer.use('/api', apiRouter);  
apiServer.listen(3000, function (err) {  
  if (err) {  
    console.log(err)  
    return  
  }  
  console.log('Listening at http://localhost:' + 3000 + '\n')  
}) 

之後config/index.js目錄下

module.exports = {
  dev: {

    // Paths
    assetsSubDirectory: 'static', //被webpack編譯處理過的資原始檔都會在這個目錄下
    assetsPublicPath: '/',      //根目錄
    proxyTable: {                //解決跨域問題
        '/api': 'http://localhost:3000/'  
    },

    // Various Dev Server settings
    host: 'localhost', // can be overwritten by process.env.HOST
    port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
    autoOpenBrowser: false,
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false, 
    devtool: 'cheap-module-eval-source-map', //編譯輸出格式
  },
}

  webpack打包原理:

現象:假如說需要引入一大堆的js/css檔案,且相互之間還存在引用關係,手動處理的時候就得按照一定的順序。

解決:webpack將一大堆的檔案都從一個入口引入,然後自動處理。(將模組的前後關係打包成一個js,指定js的單獨打包等等),webpack實現模組化的管理。

功能:

1、根據模板生成html,並且自動處理上面的css/JS引用路徑

2、自動處理img裡圖片路徑,css樣式中背景圖的路徑...字型引用

3、開啟本地伺服器,變寫程式碼邊自動更新頁面內容

4、編譯jsx、es6、sass、less、coffeescript等等並新增md5、sourcemap等輔助

5、非同步載入內容,比如彈出框,不需要時不載入到dom

6、配合vue.js、react等框架開發等。

第二方面vue的主要檔案設定:

根目錄下的index.html設定viewport移動端檢視,並且引入重置樣式:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>vueeleme</title>
    <meta name="viewport" content="width=device-width,inital-scale=1.0,
    maximum-scale=1.0,user-scalable=no">  // 這個meta標籤使得頁面寬度等於裝置寬度,頁面的縮放預設為1,且使用者不能縮放。
    <link rel="stylesheet" href="./static/css/reset.css">    //基礎樣式重置
  </head>
  <body>
    <div id="app"></div>        //掛載所需的id(在main.js中設定)
    <!-- built files will be auto injected -->
  </body>
</html>

main.js: 匯入VueRouter 管理路由, 匯入 VueResource實現資料互動。

///////main.js檔案部分內容:
const routes = [        //設定路由及相應元件
        {
          path:'/',
          redirect:"goods"    //根目錄下重定向到主頁面
        },
        {
          path:'/goods',        //不同的路由使用不同的元件
          component:goods    
        },
        {
          path:'/ratings',
          component:ratings
        },{
          path:'/seller',
          component:seller
        }
]
const router = new VueRouter({        //將路由匯入VueRouter
    mode:'history', //可以去掉#
    'linkActiveClass': 'active', 
    routes            
})
const app = new Vue({            //渲染App.vue, 掛載到idnex.html中的#app中
  router,
  render: h => h(App)
}).$mount('#app')

App.vue 頭部採用元件的形式,導航採用flex佈局三等分,內容利用路由router-view進行顯示。

<template>
  <div>
    <!-- 頭部 -->
    <v-header :seller="seller"></v-header>        //元件化
    <!-- 中部導航欄 -->
    <div class="tab border-1px">                  //flex三等分佈局
        <div class="tab-item">
          <router-link to="/goods">商品</router-link>
        </div>
        <div class="tab-item">
          <router-link to="/ratings">評論</router-link>
        </div>
        <div class="tab-item">
          <router-link to="/seller">商家</router-link>
        </div>
    </div>
    <!-- 路由改變時,顯示相應的內容 -->
    <keep-alive>
      <router-view :seller="seller"></router-view>            //父元件傳遞資料
    </keep-alive>
  </div>
</template>

第三方面設計思路:

     裝置畫素比:devicePixelRatio,視覺稿是以iphone6的375×667螢幕螢幕高度作為基準,為了達到高清效果,視覺稿的畫布大小會是基準的2倍。(對iphone6而言:原先的375×667,就會變成750×1334)。而在設計時候的數值為設計稿上的一半。

     並且需要知道:1px 的 CSS 畫素並不一定等於 1px 的物理畫素,不同的裝置會根據其對應裝置畫素比決定使用多少個物理畫素顯示 1px 的 CSS 畫素。所以,在移動端不建議使用 px 作為佈局單位,而是應該使用 rem 或者百分比作為佈局單位

    移動端1px邊框:   利用偽類元素設定邊框

border-1px($color)
  position : relative
  &:after
    display: block
    position: absolute
    left: 0
    bottom: 0
    border-top 1px solid $color
    width: 100%
    content: ''

“Sticky Footer”:  指的就是一種網頁效果: 如果頁面內容不足夠長時,頁尾固定在瀏覽器視窗的底部;如果內容足夠長時,頁尾固定在頁面的最底部。但如果網頁內容不夠長,置底的頁尾就會保持在瀏覽器視窗底部。

自適應佈局:flex,兩端的line自適應

html:
                    <div class="title">
                        <div class="line"></div>
                        <div class="text">優惠訊息</div>
                        <div class="line"></div>
                    </div>
CSS:
            .title
                display: flex
                margin: 28px auto 24px auto
                width:80%
                .line
                    flex:1
                    position:relative
                    top: -6px
                    border-bottom:1px solid rgba(255,255,255,.2)
                .text
                    padding:0 12px
                    font-size:14px
                    font-weight:700