1. 程式人生 > >Elm仿餓了麼vuejs app學習筆記

Elm仿餓了麼vuejs app學習筆記

兩端橫線,中間文字

<div class="line"></div>

<div class="text"></div>
<div class="line"></div>


.title
 display:flex
.line
flex:1----------------------------------------------------------------flex彈性佈局
position:relative
top:-6px
border-bottom: 1px solid rgba(255, 255, 255, 0.2)------------------橫線的效果
.text
padding:0 12px
font-size:14px




postcss工具-------》自動補齊相容性css程式碼
 
 
mixin方法:


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

border-none()
  &:after
    display:none


設定最後一個元素沒有底邊的:
.food-item
  display:flex
  margin:18px
  border-1px(rgba(7,17,27,0.1))------>1px border-bottom設定display:block  
  &:last-child
     border-none()  ---------->設定底邊display:none


 
 
  <ul>
<li @click="selectFood(food,$event)" v-for="food in item.foods" class="food-item border-1px">------------每一個食品分類進行遍歷。點選某一個食品,跳轉商品詳情頁面。
 <div class="icon">
<img width="57" height="57" :src="food.icon">
 </div>
 <div class="content">
<h2 class="name">{{food.name}}</h2>
<p class="desc">{{food.description}}</p>
<div class="extra">
 <span class="count">月售{{food.sellCount}}份</span><span>好評率{{food.rating}}%</span>
</div>
<div class="price">
 <span class="now">¥{{food.price}}</span><span class="old"
v-show="food.oldPrice">¥{{food.oldPrice}}</span>
</div>
<div class="cartcontrol-wrapper">
 <cartcontrol :food="food"></cartcontrol>
</div>
 </div>
</li>
  </ul>


<food :food="selectedFood" v-ref:food></food>-----------商品詳情頁面元件作為子元件引入。
  
  import shopcart from 'components/shopcart/shopcart';
  import cartcontrol from 'components/cartcontrol/cartcontrol';
  import food from 'components/food/food';
components: {
 shopcart,
 cartcontrol,
 food
},

    selectFood(food, event) {
        if (!event._constructed) {
          return;
        }
        this.selectedFood = food;
        this.$refs.food.show();---------父元件呼叫子元件的方法show()

      },
 


子頁面:詳情頁面
<div v-show="showFlag" class="food" transition="move" v-el:food>----------增加了transition="move"頁面切換的過渡效果
</div>


  .food
    position: fixed
    left: 0
    top: 0
    bottom: 48px
    z-index: 30
    width: 100%
    background: #fff
    &.move-transition
      transition: all 0.2s linear-----------------過渡效果
      transform: translate3d(0, 0, 0)-------------最終位置
    &.move-enter, &.move-leave

      transform: translate3d(100%, 0, 0)----------進入離開的位置
.image-header
 position: relative
 width: 100%
 height: 0----------------------設定height:0
 padding-top: 100%-------------->padding-top值等於width的寬度值。佔據了一個寬高相同的區域,留給img載入展示用
 img
position: absolute
top: 0
left: 0
width: 100%
height: 100%
 
 show() {--------------------------子元件裡面的方法
        this.showFlag = true;
        this.selectType = ALL;
        this.onlyContent = true;
        this.$nextTick(() => {
          if (!this.scroll) {
            this.scroll = new BScroll(this.$els.food, {
              click: true
            });
          } else {
            this.scroll.refresh();
          }
        });
      },
 


最新價格/舊的價格:  
<div class="price">
  <span class="now">¥{{food.price}}</span><span class="old" v-show="food.oldPrice">¥{{food.oldPrice}}</span>
</div>
 
.price
        font-weight: 700
        line-height: 24px
        .now
          margin-right: 8px
          font-size: 14px
          color: rgb(240, 20, 20)
        .old
          text-decoration: line-through------------>橫線中間穿過,舊的價格
          font-size: 10px
          color: rgb(147, 153, 159)
 
 
詳情頁面內容超過視窗的高度時,引用BetterScroll,可以滾動內容,但是不會出現滾動條:
    1)BetterScroll繫結在外層div
    2)內層div的內容超出外層div的高度時,內層div可以進行滾動操作
 
<div v-show="showFlag" class="food" transition="move" v-el:food>
       <div class="food-content"></div>
</div>

import BScroll from 'better-scroll';
 
show() {
        this.showFlag = true;
        this.selectType = ALL;----------created時進行初始化設定
        this.onlyContent = true;--------created時進行初始化設定
        this.$nextTick(() => {--------------------------只有$nextTick才能夠保證dom時渲染的,高度才能被計算過
          if (!this.scroll) {
            this.scroll = new BScroll(this.$els.food, {-------傳入dom
              click: true-------------------------------------裡面有些地方是可以被點選的,所以設定為click:true
            });
          } else {
            this.scroll.refresh();-----------------------重新做一次計算
          }
        });
      },
 


<div class="cartcontrol-wrapper">------------增加減少數量的元件
  <cartcontrol :food="food"></cartcontrol>
</div>
<div @click.stop.prevent="addFirst" class="buy" v-show="!food.count || food.count===0" transition="fade">加入購物車</div>-----------沒有選數量的時候,出現“加入購物車”按鈕  
----------------------------->@click.stop.prevent阻止點選穿透冒泡
      .cartcontrol-wrapper
        position: absolute
        right: 12px
        bottom: 12px
      .buy
        position: absolute
        right: 18px
        bottom: 18px
        z-index: 10------------------用來覆蓋cartcontrol-wrapper元件的,所以設定z-index:10
        height: 24px
        line-height: 24px
        padding: 0 12px
        box-sizing: border-box
        border-radius: 12px
        font-size: 10px
        color: #fff
        background: rgb(0, 160, 220)
&.fade-transition--------------------加上transition過渡效果,同時解決了cartcontrol-wrapper元件的問題
          transition: all 0.2s
          opacity: 1
        &.fade-enter, &.fade-leave
          opacity: 0


addFirst(event) {
if (!event._constructed) {----------防止pc多次點選。better scroll傳入的event有_constructed屬性,遮蔽掉瀏覽器的預設操作即可
 return;
}
this.$dispatch('cart.add', event.target);
Vue.set(this.food, 'count', 1);
 },




 
<p class="text">
<span :class="{'icon-thumb_up':rating.rateType===0,'icon-thumb_down':rating.rateType===1}"></span>{{rating.text}}------------->:class=“{}”一個物件,寫入多個屬性值來判斷用哪個class
</p>  
 



<div class="user">
<span class="name">{{rating.username}}</span>
<img class="avatar" width="12" height="12" :src="rating.avatar">
</div>

.user
position: absolute
right: 0
top: 16px
line-height: 12px
font-size: 0------------------父元素的font-size: 0,消除子元素之間(inline-block  圖片與文字之間)預設存在的空白間隙
.name
 display: inline-block
 margin-right: 6px
 vertical-align: top---------與img的top對齊
 font-size: 10px
 color: rgb(147, 153, 159)
.avatar
 border-radius: 50%
 
 
'ratingtype.select'(type) {--------------改變選擇評價按鈕選項時,需要重新生成dom,重新整理BetterScroll
        this.selectType = type;
        this.$nextTick(() => {----------------更新dom
          this.scroll.refresh();--------------重新計算BetterScroll
        });
      },  
 
 
 

preloader------------loader之前處理

include---只對該目錄下檔案檢查
exclude---排除該目錄下的檔案          
              


<router-view :seller="seller" keep-alive></router-view>-------------seller是非同步獲取到的。

  export default {
    data() {
      return {
        seller: {
          id: (() => {
            let queryParam = urlParse();
            return queryParam.id;
          })()
        }
      };
    },
    created() {
      this.$http.get('/api/seller?id=' + this.seller.id).then((response) => {
        response = response.body;
        if (response.errno === ERR_OK) {
          this.seller = Object.assign({}, this.seller, response.data);
        }
      });
    },
    components: {
      'v-header': header
    }
  };              
              
              
              
    <div class="seller" v-el:seller>
        <div class="pic-wrapper" v-el:pic-wrapper>
          <ul class="pic-list" v-el:pic-list>
            <li class="pic-item" v-for="pic in seller.pics">
              <img :src="pic" width="120" height="90">
            </li>
          </ul>
        </div>
    </div>


    import BScroll from 'better-scroll';    
              
                        
    watch: {
      'seller'() {------------由於是非同步獲取資料的,需要監測資料的變化,重新計算better-scroll高度和寬度值
        this._initScroll();
        this._initPics();
      }
    },
    ready() {
      this._initScroll();
      this._initPics();
    },          
              
          
  _initScroll() {
    if (!this.scroll) {
      this.scroll = new BScroll(this.$els.seller, {
        click: true
      });
    } else {
      this.scroll.refresh();
    }
  },
  _initPics() {
    if (this.seller.pics) {
      let picWidth = 120;
      let margin = 6;
      let width = (picWidth + margin) * this.seller.pics.length - margin;
      this.$els.picList.style.width = width + 'px';------------計算圖片區域的寬度,並且賦值給該div
      this.$nextTick(() => {
        if (!this.picScroll) {
          this.picScroll = new BScroll(this.$els.picWrapper, {
            scrollX: true,-------------------------橫向滾動
            eventPassthrough: 'vertical'-----------滾動該圖片區域的時候,外層不進行豎向滾動
          });
        } else {
          this.picScroll.refresh();
        }
      });
    }
  }          
          
              
              
    data() {
      return {
        seller: {
          id: (() => {------------------------seller有一個id屬性
            let queryParam = urlParse();
            return queryParam.id;
          })()
        }
      };
    },
    created() {
      this.$http.get('/api/seller?id=' + this.seller.id).then((response) => {
        response = response.body;
        if (response.errno === ERR_OK) {
          this.seller = Object.assign({}, this.seller, response.data);---------保留id屬性,擴充套件seller的其他屬性
        }
      });
    },          

E:\nodeWork\v0hivb\prod.server.js:
    var express = require('express');-----------------啟動一個express服務
    var config = require('./config/index');

    var port = process.env.PORT || config.build.port;

    var app = express();

    var router = express.Router();

    router.get('/', function (req, res, next) {
        req.url = '/index.html';
        next();
    });    
              
              
    var appData = require('./data.json');------------相對路徑變化,因為所在目錄不一樣了          
              
              
              
E:\nodeWork\v0hivb\config\index.js:          
    productionSourceMap: false,-----------------false:打包生成的檔案中不含sourcemap檔案了
    cssSourceMap: false    
              

vue2.0中過渡效果的設定:
      <transition name="fades" >  </transition>              
                  
      /*動畫*/
      .fades-enter-active,
      .fades-leave-active {
        transition: all .2s linear;------------設定transition效果
        transform: translate3D(0, 0, 0);
      }

      .fades-enter,
      .fades-leave-active {-------------------leave-active而不是leave
        transform: translate3D(100%, 0, 0);
      }              
              
              
vue2.0中transition觸發的函式,用法區別:              
    <transition name="drop" @before-enter="beforeDrop" @enter="dropping" @after-enter="afterDrop">  </transition>                  
              
              
    當只用 JavaScript 過渡的時候,在 enter 和 leave 中必須使用 done 進行回撥。否則,它們將被同步呼叫,過渡會立即完成。          
              
              
    dropping(el, done) {
          /* eslint-disable no-unused-vars */
          let rf = el.offsetHeight;
          this.$nextTick(() => {
            el.style.webkitTransform = 'translate3d(0,0,0)';
            el.style.transform = 'translate3d(0,0,0)';
            let inner = el.getElementsByClassName('inner-hook')[0];
            inner.style.webkitTransform = 'translate3d(0,0,0)';
            inner.style.transform = 'translate3d(0,0,0)';
            el.addEventListener('transitionend', done);------------done進行回撥
          });
        },          

減少order的數量 transition 位移和旋轉:
<div class="cart-decrease" v-show="food.count>0" @click.stop.prevent="decreaseCart"
     transition="move">
  <span class="inner icon-remove_circle_outline"></span>
</div>
.cart-decrease
  display: inline-block
  padding: 6px
  transition: all 0.4s linear
  &.move-transition
    opacity: 1
    transform: translate3d(0, 0, 0)
    .inner
      display: inline-block
      line-height: 24px
      font-size: 24px
      color: rgb(0, 160, 220)
      transition: all 0.4s linear
      transform: rotate(0)
  &.move-enter, &.move-leave
    opacity: 0
    transform: translate3d(24px, 0, 0)
    .inner
      transform: rotate(180deg)

 
新增商品數量小球動畫效果:

addCart(event) {
  if (!event._constructed) {
    return;
  }
  if (!this.food.count) {
    Vue.set(this.food, 'count', 1);
  } else {
    this.food.count++;
  }
  this.$dispatch('cart.add', event.target);------------商品數量增減元件中點選“ + ”,觸發事件
},
events: {
  'cart.add'(target) {---------------------goods父元件監聽到事件,執行相應函式
    this._drop(target);
  }
}
_drop(target) {
  // 體驗優化,非同步執行下落動畫
  this.$nextTick(() => {
    this.$refs.shopcart.drop(target);-------呼叫shopCart元件中的函式完成小球動畫功能
  });
},
<div class="ball-container">
  <div transition="drop" v-for="ball in balls" v-show="ball.show" class="ball">
    <div class="inner inner-hook"></div>
  </div>
</div>
.ball-container
  .ball
    position: fixed
    left: 32px
    bottom: 22px
    z-index: 200
    &.drop-transition
      transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41)
      .inner
        width: 16px
        height: 16px
        border-radius: 50%
        background: rgb(0, 160, 220)
        transition: all 0.4s linear
data() {
  return {
    balls: [
      {
        show: false
      },
      {
        show: false
      },
      {
        show: false
      },
      {
        show: false
      },
      {
        show: false
      }
    ],
    dropBalls: [],
    fold: true
  };
},
methods: {
  drop(el) {
    for (let 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;------------只設置完this.balls[0].show = true直接跳出該函數了。
      }
    }
  },
transitions: {
  drop: {
    beforeEnter(el) {
      let count = this.balls.length;
      while (count--) {
        let ball = this.balls[count];
        if (ball.show) {------------只有this.balls[0].show = true, 迴圈到count = 0為止
          let rect = ball.el.getBoundingClientRect();-----獲取滑鼠點選的位置pos:x,y座標
          let x = rect.left - 32;
          let y = -(window.innerHeight - rect.top - 22);
          el.style.display = '';
          el.style.webkitTransform = `translate3d(0,${y}px,0)`;
          el.style.transform = `translate3d(0,${y}px,0)`;
          let inner = el.getElementsByClassName('inner-hook')[0];
          inner.style.webkitTransform = `translate3d(${x}px,0,0)`;
          inner.style.transform = `translate3d(${x}px,0,0)`;
        }
      }
    },
    enter(el) {
      /* eslint-disable no-unused-vars */
      let rf = el.offsetHeight;
      this.$nextTick(() => {
        el.style.webkitTransform = 'translate3d(0,0,0)';
        el.style.transform = 'translate3d(0,0,0)';
        let inner = el.getElementsByClassName('inner-hook')[0];
        inner.style.webkitTransform = 'translate3d(0,0,0)';
        inner.style.transform = 'translate3d(0,0,0)';
      });
    },
    afterEnter(el) {
      let ball = this.dropBalls.shift();
      if (ball) {
        ball.show = false;
        el.style.display = 'none';
      }
    }
  }
},

相關推薦

Elm仿vuejs app學習筆記

兩端橫線,中間文字 <div class="line"></div> <div class="text"></div> <div class="line"></div> .title  display

仿”訂餐app介面實現

直想做簡單的demo分享給大家。趁著最近專案收尾,時間充裕,便仿照“餓了麼”訂餐app做了個demo,雖然有些瑕疵和bug,但還是希望能給剛入門的新人和有需要的同學帶來幫助吧。以後會不定期在demo里加些新內容,也想請有git賬號的同學們star一下,3q!========

vue高仿APP(三)

一·需求分析   二,製作css字型圖示的製作和使用 前面已經有人做過總結,我就直接引用了 css字型圖示的製作和使用。   三,專案目錄結構設計 1,每一個元件都單獨建立一個資料夾,例如商品頁建立goods資料夾,goods資料夾放商品頁元件,goods.vue以及商品

vue高仿APP(二)

這裡我直接跳過vue-cli的安裝。   一,vue.js程式碼是如何執行的? 1,進入頁面,首先載入index.html和main.js檔案。 ① index.html檔案 <!DOCTYPE html> <html> <head>

】—— Vue2.0高仿核心模組&移動端Web App專案爬坑(一)

前言:學習Vue.js高仿餓了麼課程過程中,總結了這個Web App專案從準備到開發完畢自己覺得很重要的知識點。這一篇主要介紹:專案準備、頁面骨架開發、header元件開發。 專案github地址:https://github.com/66Web/ljq_eleme,歡迎Star。  

】—— Vue2.0高仿核心模組&移動端Web App專案爬坑(二) 【重點突破】—— 當better-scroll 遇見Vue

 前言:上一篇專案總結介紹了頁面骨架的開發、header元件的開發,這一篇主要梳理:商品元件開發、商品詳情頁實現。專案github地址:https://github.com/66Web/ljq_eleme,歡迎Star。 goods

Vue2.0高仿核心模組&移動端Web App專案爬坑(一)

原文https://www.cnblogs.com/ljq66/p/9980372.html 前言:學習Vue.js高仿餓了麼課程過程中,總結了這個Web App專案從準備到開發完畢自己覺得很重要的知識點。這一篇主要介紹:專案準備、頁面骨架開發、header元件開發。 專案github地址:

Vue.js高仿外賣App Vue實戰開發APP 共13章

  講真,JavaScript應用之廣超乎想象JavaScript進階已來,你來不來!搞定JavaScript基礎以後,怎麼辦JavaScript在效能方面堪稱全能,應用領域從基本的前後端開發、到移動開發的Webapp、再到桌面、外掛開發等均可適用。本路徑是JavaScript的

】—— Vue2.0高仿核心模組&移動端Web App專案爬坑(一)

@import "../../common/stylus/mixin" .star .star-item display: inline-block background-repeat: no-repeat &.st

】—— Vue2.0高仿核心模組&移動端Web App專案爬坑(二)

methods: { dropMove(el) { // console.log(el) for(let i=0; i<this.balls.length; i++) { let ball = this.bal

架構學習——移動APP的架構演進

0 引言 時代演進,技術也隨之發展。到今天,APP已然成為絕大多數網際網路企業用來獲取使用者的核心渠道。與此同時,伴隨著業務量的增長,愈來愈大、愈來愈多的APP也在不斷地、持續地挑戰著每一個移動端研發人員的知識深度,而我們的移動端技術人員也在這個不斷接受挑戰的過程中,成

學習筆記之vue高仿課程專案--vue.js篇

歡迎大家來訪問我的github哦:my-github現把專案中學到的知識和遇到的問題做一整理。這篇是vue.js篇vue-clivue-cli是vue的腳手架工具,官方命令列工具,可快速搭建大型單頁應用。下面是使用方法(前提是已經安裝node)全域性安裝cnpm instal

學習筆記之vue高仿課程專案--佈局篇

歡迎大家來訪問我的github哦:my-github現把專案中學到的知識和遇到的問題做一整理。這篇是佈局篇(採用stylus)flex佈局如果一個佈局需要左邊是固定長度,右邊是自適應寬度,隨拉大而大,縮小而小,則可以使用flex佈局。移動端很適合。.wrapper

最新vue2.x仿app 商家頁面 專案總結

前言仿餓了麼app是基於vue2.x最新實戰專案,用到的技術棧vue2 + vue-router2 + vue-cli2 + vue-resource + stylus + flex佈局 + es6 + eslint + webpack2 頁面相對簡單,所以沒有用到vuex

仿,百度外賣這些App的雙ListView列表聯動效果

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content

Vue.js高仿外賣App

第1章 課程簡介介紹課程的學習目標和學習內容。第2章 Vuejs介紹從前端開發趨勢分析開始,引入 MVVM 開發框架和 Vue.js,接著對比流行框架Angular 和 React,最後詳細介紹 Vue.js 的核心思想-資料驅動和元件化。第3章 Vue-cli 開啟 Vue

【慕課網實戰課程筆記】Vue.js高仿外賣App

寫在前面:該課程為慕課網付費課程,筆記內容程式碼居多、內容簡略,僅供自己日後翻閱。如有疑問或者不妥,歡迎提出指正,我看到了會回覆,謝謝! 第1章:課程簡介 第2章:Vuejs介紹 Ctrl+Alt+l 快捷整理程式碼 第3章:Vue-cli開啟Vue

仿【node+webpack】(window部署執行)

為了調通後臺,研究了好幾天的vue專案,遇到各種坑,終於算調通了,現在把整個操作做個記錄: window端:(程式碼:https://github.com/vuejs/vue-devtools) 1.用idea編譯vue專案:   Intellij IDEA搭建vue-cli專

基於vue2+nuxt構建的高仿(2018版)

前言 高仿餓了麼,以nuxt作為vue的服務端渲染,適合剛接觸或者準備上vue ssr的同學參考和學習 專案地址如遇網路不佳,請移步國內映象加速節點 效果演示 檢視demo請戳這裡(請用chrome手機模式預覽) 移動端掃描下方二維碼 API介面文件 介面文件地址(基於apidoc) 技術棧 vue2 +

訂餐外賣網站原始碼模板多使用者帶後臺 仿美團外賣o2o

系統簡介: 網上訂餐系統,是石家莊晟訊網路科技有限公司為滿足眾多餐飲外賣企業的迫切需要,開發定製的一款成熟的“B2C網上訂餐系統”。目前已經運用到全國各地,網上點餐系統致力於幫助專業從事餐飲外賣企業或有外賣業務的餐飲企業快速部署外賣訂餐系統,拓展網路外賣訂餐業務