Vue.js仿eleme項(xiàng)目(3)

六,header組件開發(fā)

1. vue-resource

vue-resource 處理前后端請(qǐng)求數(shù)據(jù)交互沽翔。
安裝引入注冊(cè)同vue-router鲜漩,都是第三方插件。

main方法中使用的是全局配置文件诅诱,所以在這里可以配置所有的公共數(shù)據(jù)。在VUE中規(guī)定data是一個(gè)函數(shù)送朱。vue-resource 要將請(qǐng)求成功的數(shù)據(jù)轉(zhuǎn)換為json格式娘荡,要調(diào)用 .body 這個(gè)屬性,如果用json方法返回的是promise對(duì)象驶沼。created 是 Vue 生命周期的鉤子函數(shù)它改,會(huì)在實(shí)例化的過程中自動(dòng)調(diào)用的。

//App.vue
...
created() {
      // 這里只寫成功的方法
      this.$http.get('api/seller').then((response) => {
        response = response.body;
        if (response.errno === ERR_OK) {
          this.seller = response.data;
          console.log(this.seller);
        }
      });
    },
...

2. 外部組件

編寫header代碼商乎,向header中傳ajax獲取的seller央拖。

<v-header :seller="seller"></v-header>

我們數(shù)據(jù)是異步得到的,最開始渲染dom的時(shí)候鹉戚,seller為空對(duì)象鲜戒。加上v-if是因?yàn)檫@里層次嵌套深,如果 seller 是 {}抹凳,那么 seller.supports 為 undefined遏餐,那么 undefined[0] 就報(bào)錯(cuò)了。比如你需要訪問3級(jí)數(shù)據(jù)比如 a.b.c 需要判斷 v-if a.b否則會(huì)報(bào)錯(cuò)赢底。

幾個(gè)不錯(cuò)的QA:

Q: 感覺如果從子組件中的mounted鉤子中發(fā)送ajax然后拿到數(shù)據(jù)渲染失都,也就不用寫v-if判斷了啊?
A: 有些情況,如果是想保持組件的純凈幸冻,只負(fù)責(zé)渲染粹庞,數(shù)據(jù)通過 props 的傳入,對(duì)組件的復(fù)用性也會(huì)更好洽损。有些情況庞溜,如果組件內(nèi)部有一些交互邏輯需要組件閉環(huán)的話,確實(shí)可以把 ajax 請(qǐng)求寫在組件內(nèi)部碑定。

header.vue中的props部分相當(dāng)于要給header組件傳入的參數(shù)流码,對(duì)應(yīng)于App的template中的:seller傳入。

為了消除inline-block由于空白字符產(chǎn)生的空隙延刘,給父元素設(shè)置font-size=0漫试。但是在bulletin中為了顯示省略號(hào)不能用font-size的方式,就直接刪除html中span之間的空格好了碘赖。

white-space:nowrap;overflow: hidden;text-overflow: ellipsis;這三個(gè)屬性組合起來就是單行顯示驾荣,多余文字省略號(hào)表示了

bulletin 的垂直對(duì)齊可以用我自己的方法設(shè)置title圖片middle外构,或者用老師的方法先全部top對(duì)齊然后調(diào)整title圖片的margin-top。

引入不同dpr的圖片秘车,在mixin.styl中定義這樣的函數(shù)典勇。

background的模糊效果圖片背景通過絕對(duì)定位+filter實(shí)現(xiàn)劫哼。注意由于filter的blur效果header底部有溢出的模糊叮趴,所以要在header中添加overflow樣式。

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")

品牌圖片在頁面中被webpack打包成了base64地址权烧。

關(guān)于不用rem em而用px的解釋眯亦,http://coding.imooc.com/learn/questiondetail/3357.html

supports欄的書寫要用class map實(shí)現(xiàn)。展示的是supports[0]般码,但是type是動(dòng)態(tài)的妻率。supports的text中font-size為10px,在chrome下看不出來因?yàn)閏hrome下最小是12px板祝。但是手機(jī)端看得出來宫静。

垂直居中對(duì)齊問題用vertical-align: top 和調(diào)整line-height解決。

header.vue代碼如下

<template>
  <div class="header">
    <div class="content-wrapper">
      <div class="avatar">
        ![](seller.avatar)
      </div>
      <div class="content">
        <div class="title">
          <span class="brand"></span>
          <span class="name">{{seller.name}}</span>
        </div>
        <div class="description">
          {{seller.description}}/{{seller.deliveryTime}}分鐘到達(dá)
        </div>
        <div v-if="seller.supports" class="supports">
          <span class="icon" :class="classMap[seller.supports[0].type]"></span>
          <span class="text">{{seller.supports[0].description}}</span>
        </div>
      </div>
      <div v-if="seller.supports" class="support-count">
        <span class="count">{{seller.supports.length}}個(gè)</span>
        <i class="icon-keyboard_arrow_right"></i>
      </div>
    </div>
    <div class="bulletin-wrapper">
      <span class="bulletin-title"></span><span class="bulletin-text">{{seller.bulletin}}</span>
      <i class="icon-keyboard_arrow_right"></i>
    </div>
    <div class="background">
      ![](seller.avatar)
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
  export default {
    props: {
      seller: {
        type: Object
      }
    },
    created() {
      this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee'];
    }
  };
</script>

<style lang="stylus" rel="stylesheet/stylus">
  @import "../../common/stylus/mixin"

  .header
    position: relative
    overflow: hidden
    color: white
    background-color: rgba(7, 17, 27, 0.5)
    .content-wrapper
      padding: 24px 12px 18px 24px
      position: relative
      font-size: 0
      .avatar
        display: inline-block
        vertical-align: top
        img
          border-radius: 2px
      .content
        display: inline-block
        margin-left: 16px
        .title
          margin: 2px 0 8px 0
          .brand
            display: inline-block
            vertical-align: top
            width: 30px
            height: 18px
            bg-image(brand)
            background-size: 30px 18px
            background-repeat: no-repeat
          .name
            margin-left: 16px
            font-size: 16px
            line-height: 18px;
            font-weight: bold
        .description
          margin-bottom: 10px
          line-height: 12px
          font-size: 12px
        .supports
          .icon
            display: inline-block
            vertical-align: top
            width: 12px
            height: 12px
            margin-right: 4px
            background-size: 12px 12px
            background-repeat: no-repeat
            &.decrease
              bg-image(decrease_1)
            &.discount
              bg-image(discount_1)
            &.guarantee
              bg-image(guarantee_1)
            &.invoice
              bg-image(invoice_1)
            &.special
              bg-image(special_1)
          .text
            line-height: 12px
            font-size: 10px

      .support-count
        position: absolute
        right: 12px
        bottom: 14px
        padding: 0 8px
        height: 24px
        line-height: 24px
        border-radius: 14px
        background: rgba(0, 0, 0, 0.2)
        text-align: center
        .count
          vertical-align: top
          font-size: 10px
        .icon-keyboard_arrow_right
          line-height: 24px
          margin-left: 2px
          font-size: 10px

    .bulletin-wrapper
      position: relative
      height: 28px
      line-height: 28px
      padding: 0 22px 0 12px
      white-space: nowrap
      overflow: hidden
      text-overflow: ellipsis
      background-color: rgba(7, 17, 27, 0.2)
      .bulletin-title
        display: inline-block
        vertical-align: middle
        width: 22px
        height: 12px
        bg-image(bulletin)
        background-size: 22px 12px
        background-repeat: no-repeat
      .bulletin-text
        margin: 0 4px
        font-size: 10px
      .icon-keyboard_arrow_right
        position: absolute
        right: 12px
        bottom: 8px
        font-size: 10px
    .background
      position: absolute
      top: 0px
      left: 0px
      width: 100%
      height: 100%
      z-index: -1
      filter: blur(10px)
</style>

3. 詳情彈層頁

這一部分也可以單獨(dú)寫一個(gè)組件券时,這里我們繼續(xù)在header中編寫代碼孤里。

3.1. 實(shí)現(xiàn)彈出層

彈出層是一個(gè)叫detail的div。用fixed布局橘洞。在對(duì)應(yīng)的地方添加@click函數(shù)捌袜,并寫入data和methods的vue方法控制點(diǎn)擊出現(xiàn)事件,不需要編寫改變dom事件炸枣,vue非常方便虏等。

<div v-if="seller.supports" class="support-count" @click="showDetail">

    data() {
      return {
        detailShow: false
      };
    },
    methods: {
      showDetail() {
       this.detailShow = true;
      }
    },
    .detail
      position: fixed
      z-index: 100
      top: 0
      left: 0
      width: 100%
      height: 100%
      overflow: auto
      background-color: rgba(7, 17, 27, 0.8)

關(guān)于vue的new vue, export default語法的問題http://coding.imooc.com/learn/questiondetail/15435.html

Q: data 與 created 里定義變量的區(qū)別?
A: 如果你想為這個(gè)屬性添加 getter 和 setter适肠,就放在 data 里霍衫,data數(shù)據(jù)是響應(yīng)的。如果不需要就直接掛在當(dāng)前實(shí)例下侯养。

3.2. CSS Sticky Footer

CSS秘密花園有文章介紹sticky footer慕淡。www.w3cplus.com/css3/css-secrets/sticky-footers.html

這里我們用一個(gè)兼容性較好的套路去解決sticky footer。

detail-main中的padding-bottom是必須的沸毁,本例子中用margin-bottom也可以峰髓。然后關(guān)閉icon部分用margin。這里關(guān)鍵點(diǎn)三個(gè): 一息尺、wrapper占據(jù)最小100%尺寸携兵,此時(shí)footer層被擠到屏幕外。 二搂誉、(當(dāng)內(nèi)容不滿一屏?xí)r徐紧,)footer層負(fù)位移從屏幕外層移回來。 三、(當(dāng)內(nèi)容滿一屏?xí)r并级,)main層向外擠拂檩,防止footer疊加在main上。 此方法由于要計(jì)算footer負(fù)位移嘲碧,不可處理變長(zhǎng)div的footer稻励。

如果用w3c鏈接的方法,使用flex布局可省略wrapper層愈涩。 直接給detail賦予display:flex 調(diào)整flex流向即可 望抽,并賦予main部分flex:1。flex:1等價(jià)于flex-grow:1履婉。當(dāng)所有元素排布時(shí)煤篙,該元素自動(dòng)放大。由于flex布局時(shí)毁腿,float辑奈、clear屬性失效,故無需再調(diào)整float相關(guān)屬性已烤。flex布局簡(jiǎn)單鸠窗,且可處理高度變化的footer,vue組件中用flex有預(yù)處理草戈。

本文在detail-wrapper中清除了浮動(dòng)(用clearfix)塌鸯,其實(shí)在本例中也可以不清除,只是為了標(biāo)準(zhǔn)寫法兼容其他場(chǎng)景唐片。注意我們將detail-wrapper設(shè)置成了inline-block丙猬,為了避免垂直外邊距合并問題。

<div v-show="detailShow" class="detail">
      <div class="detail-wrapper clearfix">
        <div class="detail-main">
        </div>
      </div>
      <div class="detail-close">
        <i class="icon-close"></i>
      </div>
    </div>
................................................................
    .detail
      position: fixed
      z-index: 100
      top: 0
      left: 0
      width: 100%
      height: 100%
      overflow: auto
      background-color: rgba(7, 17, 27, 0.8)
      .detail-wrapper
        width: 100%
        min-height: 100%
        .detail-main
          margin-top: 64px
          padding-bottom: 64px
      .detail-close
        position: relative
        width: 32px
        height: 32px
        margin: -64px auto 0 auto
        clear: both
        font-size: 32px

3.3. star組件抽象

實(shí)現(xiàn)detail-main部分费韭。創(chuàng)建star組件茧球。利用v-for指令。星級(jí)評(píng)價(jià)的星星切開單獨(dú)用星持,不用雪碧圖抢埋。有些class是通用css屬性,有些是為了指定單獨(dú)屬性督暂。stylus部分我們?cè)谶@里定義不同的揪垄。

//star.vue

<template>
  <div class="star" :class="starType">
    <span v-for="itemClass in itemClasses" :class="itemClass" class="star-item" track-by="$index">
    </span>
  </div>

</template>

<script type="text/ecmascript-6">
  const LENGTH = 5;
  const CLS_ON = 'on';
  const CLS_HALF = 'half';
  const CLS_OFF = 'off';

  export default {
    props: {
      size: {
        type: Number
      },
      score: {
        type: Number
      }
    },
    computed: {
      starType() {
        return 'star-' + this.size;
      },
      itemClasses() {
        let result = [];
        let score = Math.floor(this.score * 2) / 2;
        let hasDecimal = score % 1 !== 0;
        let integer = Math.floor(score);
        for (let i = 0; i < integer; i++) {
          result.push(CLS_ON);
        }
        if (hasDecimal) {
          result.push(CLS_HALF);
        }
        while (result.length < LENGTH) {
          result.push(CLS_OFF);
        }
        return result;
      }
    }
  };

</script>

<style lang="stylus" rel="stylesheet/stylus">
  @import "../../common/stylus/mixin";

  .star
    font-size: 0
    .star-item
      display: inline-block
      background-repeat: no-repeat
    &.star-24
      .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: 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-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')
</style>
//header.vue

      <div class="detail-main">
          <h1 class="name">{{seller.name}}</h1>
          <div class="star-wrapper">
            <star :size="48" :score=seller.score></star>
          </div>
        </div>
...
 components: {
      star
    }
...

3.4. 小標(biāo)題自適應(yīng)flex布局

這里又有面試題了:“優(yōu)惠信息”居中,兩條線自適應(yīng)逻翁,背景還是透明的饥努,不能做成一整條長(zhǎng)線。 解決方法是flex布局八回,參考阮一峰教程酷愧。

          <div class="title">
            <div class="line"></div>
            <div class="text">優(yōu)惠信息</div>
            <div class="line"></div>
          </div>
...
          .title
            display: flex
            width: 80%
            margin: 28px 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
              font-weight: 700

3.5. header剩余部分實(shí)現(xiàn)

知識(shí)點(diǎn)沒有什么新的驾诈,完善了一下剩余部分。給彈出層加了一個(gè)css3動(dòng)畫溶浴。

vue1.0中這樣寫:

 <div v-show="detailShow" class="detail" transition="fade">
...
...
 transition: all 0.5s
      &.fade-transition
        opacity: 1
        background-color: rgba(7, 17, 27, 0.8)
      &.fade-enter, &.fade-leave
        opacity: 0
        background: rgba(7, 17, 27, 0)

注意彈出層下層有毛玻璃效果乍迄,這里就不能用filter屬性了,要用backdrop-filter士败。但是backdrop支持有限基本只有ios safari可以看到闯两,可以看這篇https://hran.me/achieves/css3-backdrop-filter.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拱烁,一起剝皮案震驚了整個(gè)濱河市生蚁,隨后出現(xiàn)的幾起案子噩翠,更是在濱河造成了極大的恐慌戏自,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伤锚,死亡現(xiàn)場(chǎng)離奇詭異擅笔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)屯援,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門猛们,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狞洋,你說我怎么就攤上這事弯淘。” “怎么了吉懊?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵庐橙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我借嗽,道長(zhǎng)态鳖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任恶导,我火速辦了婚禮浆竭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惨寿。我一直安慰自己邦泄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布裂垦。 她就那樣靜靜地躺著顺囊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缸废。 梳的紋絲不亂的頭發(fā)上包蓝,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天驶社,我揣著相機(jī)與錄音,去河邊找鬼测萎。 笑死亡电,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的硅瞧。 我是一名探鬼主播份乒,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼腕唧!你這毒婦竟也來了或辖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤枣接,失蹤者是張志新(化名)和其女友劉穎颂暇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體但惶,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耳鸯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了膀曾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片县爬。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖添谊,靈堂內(nèi)的尸體忽然破棺而出财喳,到底是詐尸還是另有隱情,我是刑警寧澤斩狱,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布耳高,位于F島的核電站,受9級(jí)特大地震影響喊废,放射性物質(zhì)發(fā)生泄漏祝高。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一污筷、第九天 我趴在偏房一處隱蔽的房頂上張望工闺。 院中可真熱鬧,春花似錦瓣蛀、人聲如沸陆蟆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叠殷。三九已至,卻和暖如春诈皿,著一層夾襖步出監(jiān)牢的瞬間林束,已是汗流浹背像棘。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壶冒,地道東北人缕题。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像胖腾,于是被迫代替她去往敵國和親烟零。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 當(dāng)空一天咸作,你是否如我一樣思念著遠(yuǎn)方锨阿,歲月是一杯濁酒,我們是酒中的沉淀物记罚,經(jīng)過時(shí)間的沖刷墅诡,雖然不如上好的美酒,但細(xì)細(xì)...
    蔡籽閱讀 149評(píng)論 0 0
  • 本人自身是一個(gè)運(yùn)營方面的初入者毫胜,最近上了一些有關(guān)于運(yùn)營的課书斜,有了自己的心得體會(huì)诬辈,故來粗淺的抒發(fā)一下酵使。說的不對(duì)之處希...
    大黑兔丶閱讀 357評(píng)論 2 1