項目vue2.0仿外賣APP(五)


header組件

vue-resourse應用

https://github.com/pagekit/vue-resource

vue-resource是Vue.js的一款插件,它可以通過XMLHttpRequest或JSONP發起請求並處理響應。也就是說,$.ajax能做的事情,vue-resource插件一樣也能做到,而且vue-resource的API更為簡潔。另外,vue-resource還提供了非常有用的inteceptor功能,使用inteceptor可以在請求前和請求后附加一些行為,比如使用inteceptor在ajax請求時顯示loading界面。

vue-resource插件具有以下特點:

1. 體積小
vue-resource非常小巧,在壓縮以后只有大約12KB,服務端啟用gzip壓縮后只有4.5KB大小,這遠比jQuery的體積要小得多。
2. 支持主流的瀏覽器
和Vue.js一樣,vue-resource除了不支持IE 9以下的瀏覽器,其他主流的瀏覽器都支持。
3. 支持Promise API和URI Templates
Promise是ES6的特性,Promise的中文含義為“先知”,Promise對象用於異步計算。
URI Templates表示URI模板,有些類似於ASP.NET MVC的路由模板。
4. 支持攔截器
攔截器是全局的,攔截器可以在請求發送前和發送請求后做一些處理。
攔截器在一些場景下會非常有用,比如請求發送前在headers中設置access_token,或者在請求失敗時,提供共通的處理方式。

http://www.cnblogs.com/keepfool/p/5657065.html

Header組件:商家數據,通過異步請求后端的數據接口獲得的,header組件就負責接受這樣的數據並渲染 。那我們就可以在app.vue組件(header的父組件),通過發送一個AJAX請求去獲取商家的相關數據,然后把這些數據通過headerprop屬性傳遞給這個組件。

可以查看:http://cn.vuejs.org/v2/guide/components.html#example-2-5

父子組件間的通信

組件意味着協同工作,通常父子組件會是這樣的關系:組件 A 在它的模版中使用了組件 B 。它們之間必然需要相互通信:父組件要給子組件傳遞數據,子組件需要將它內部發生的事情告知給父組件。然而,在一個良好定義的接口中盡可能將父子組件解耦是很重要的。這保證了每個組件可以在相對隔離的環境中書寫和理解,也大幅提高了組件的可維護性和可重用性。

Vue.js 中,父子組件的關系可以總結為 props down, events up 。父組件通過 props 向下傳遞數據給子組件,子組件通過 events 給父組件發送消息。看看它們是怎么工作的。


使用 Prop 傳遞數據

組件實例的作用域是孤立的。這意味着不能並且不應該在子組件的模板內直接引用父組件的數據。可以使用 props 把數據傳給子組件。
prop 是父組件用來傳遞數據的一個自定義屬性。子組件需要顯式地用 props 選項聲明 “prop”:

Vue.component('child', {
  // 聲明 props
  props: ['message'],
  // 就像 data 一樣,prop 可以用在模板內
  // 同樣也可以在 vm 實例中像 “this.message” 這樣使用
  template: '<span>{{ message }}</span>'
})

然后向它傳入一個普通字符串:

<child message="hello!"></child>

結果輸出“hello”。

回到項目中來

首先我們需要給app.vue定義一個seller的對象:可以通過data()方法。在vue.js中,這個data屬性是一個函數(可查看鏈接),因為組件是可以被復用的,如果定義一個對象然后修改某一個組件的話會影響另外的組件,所以這里定義成一個函數。這個函數return一個對象,對象里面有seller對象,先定為空,然后我們通過發送AJAX請求去拿到一個seller對象,然后send給它。這樣就可以拿到seller對象的數據。

Vue.js社區有個第三方插件:vue-resource,用來處理一些前后端請求數據交互的。

示例:

{
  // GET /someUrl
  this.$http.get('/someUrl').then((response) => {
    // success callback
  }, (response) => {
    // error callback
  });
}

同樣的,在package.json添加它的依賴:

第三方插件import引用時需要注冊,用Vue.use(vueResource)把這個注冊。在main.js注冊

然后回到app.vue,在這里我們需要通過一個vue.resource去發送一個AJAX請求,需要在什么時序去發起呢?

我們知道每個vue實例化的時候都有一個生命周期,其中有個鈎子叫created().

關於鈎子:https://segmentfault.com/q/1010000004335505

關於實例的生命周期:https://cn.vuejs.org/v2/guide/instance.html#實例生命周期 

這是它的一個生命周期鈎子函數,就是一個vue實例被生成后調用這個函數。一個vue實例被生成后還要綁定到某個html元素上,之后還要進行編譯,然后再插入到document中。每一個階段都會有一個鈎子函數,方便開發者在不同階段處理不同邏輯。一般可以在created函數中調用ajax獲取頁面初始化所需的數據。

 

能夠看到這里已經發送了:

還有很多字段:每個字段都有getset方法:

到這vue-resource就介紹完了,seller對象已經拿到,接下來就把seller對象傳遞給header組件,讓header渲染即可。

 

外部組件

vue2.0組件間通信:http://blog.csdn.net/qq_24122593/article/details/53509229

上一講從后端的seller API獲得這個seller對象,現在就來把這個seller對象傳給header組件

https://cn.vuejs.org/v2/api/#props

通過v-bind指令去傳,把這個seller這個變量傳給這個header組件。

我們在header組件里面就會通過propS屬性去接受傳過來的seller

有了這個變量就可以來寫它的DOM結構了。

<img width="64" height="64" src="seller.avatar">

這樣不行,不能直接指定src。需要用v-bind,這樣才可以去引用頭像圖片的地址,因為seller.avatar一開始是不存在的

再寫寫樣式

有的層之間會有空隙,需要怎么處理呢?方法有很多,這里使用font-size。可以先把父級的font-size設為0,再設置本身的font-size

圖片的2x3x是對應不同的dpr的。需要用到媒體查詢,代碼比較多,寫在mixin.styl

減價、打折、特價等圖標需要根據后台返回的數據來選擇,所以這里就得根據后台返回的數據修改class,這是需要動態綁定

為了將它的數值對應到各自的含義,可以定義一個classMap:

然后再動態添加class的值:

想要變化:減價變成特價。可以去后台該數據的順序:

接下來寫右下角的“5”:

<i class="icon-keyboard_arrow_right"></i>

這個小圖標用到的是字體圖標。

 

關於公告區:

為了清除間隙還有不影響省略號,我們就不用font-size0了,用其他方法,就是元素緊貼一起。

設置對齊的時候,可以先設置頂部對齊:vertical-align: top,再進行調整

 

背景圖:

Image標簽設置它的容器的filter

背景置於容器的頂部:

position: absolute
top: 0
left: 0
z-index: -1

接下來:內部彈層詳細頁

要求:全屏、模糊、底部還有關閉按鈕,而且,高度可能比手機高度還高,這是就會有滾動條。

關閉按鈕在最下方,如果用普通的布局的話,就會蓋在文字上面,這顯然不行。這時就要用到css striky footers布局。相對窗口做fixed布局

最外層:

.detail
      position: fixed
      z-index: 100
      top: 0
      left: 0
      width: 100%
      height: 100%
      overflow: auto
      background: rgba(7,17,27,0.5)

控制顯示和隱藏,在vue里面可以通過v-show指令去控制,還要給vue的實例里面加一個選項data,它是一個function,因為可能會有多個實例組件。這個functionreturn一個object,會去跟蹤依賴一些變量。

data() {
      return {
        detailShow: false
      };
},

也就是說,我們在new這個vue的時候,它會對data里面的變量去編譯然后給它添加gettersetter,這樣當我們的變量變化的時候,DOM就會跟着變化。

查看元素:

這是就要添加方法了:

showDetail() {
        this.detailShow = true;
      },

也就是說當我們去點擊這個層的時候,會調用這個方法去改變detailShow,由於這個變量是依賴跟蹤的,他就會訪問到data里的detailShow,變化的時候vue也可以檢測到,最后會通知這個DOM的指令,然后更新狀態。

就是這樣,用過vue去操作數據,從而改變DOM的狀態,這過程我們並沒有去操作DOM

 

接下來寫詳情頁里面的內容了,布局是個問題

講一下sticky footershttp://www.tuicool.com/articles/rEbQjaM

Sticky footers可以概括如下:如果頁面內容不夠長的時候,頁腳塊粘貼在視窗底部;如果內容足夠長時,頁腳塊會被內容向下推送。

有很多種方案,這里作者介紹一種比較復雜的但是兼容性好的方案。

定兩層,上一層要清除浮動:

最終套路:

detail-wrapper層要讓它的最小高度撐滿整個屏幕的,按鈕才會定在最下面。內容層有個padding-bottom,關閉層有個margin-top,就是為了向上提。

還要在base.styl添加清楚浮動的代碼。

detail-main是內容區塊,向上需要有margin-top,向下有padding-bottom

detail-close也是用到圖標字體,這里還有一個重要的點:相對定位,然后向上的負margin-top,還要清除浮動。不管內容再多,關閉按鈕仍然能夠定在底部,padding-bottom很關鍵。

 

接下來添加內容

不可能這樣整張圖吧,因為如果評分多的話,有100分呢,那么這樣的圖片不得有上百行。而且項目也多處有星星,所以這樣可以弄一個組件star.vue。而且把圖片都單獨切開,這樣不管什么狀態都只有這么多圖片。

為了有更好的擴展性,並且足夠靈活,我們要利用vue里面的v-for的指令,根據我們定的星星個數去遍歷它。

並且,由於這里的star有不同尺寸,所以也有不同樣式,所以就用一個v-bind綁定class

首先,star有不同的尺寸,這個尺寸的大小是由外部數據傳進來的,所以需要對外提供接口,可以傳過來變量,告訴你star的尺寸是多少,得分又是多少。

這個過程主要還是兩方面:根據得分給星星,星星尺寸也不同。

這里還需要一個公式來根據傳過來的尺寸分數映射一個類型。

 

就比如傳進來的size是24,那么計算之后就得到star-24,這是就可以設置size-24的相關樣式了。

再添加不同類型尺寸的star的樣式。

 

接下來就是star的遍歷了,它是一個數組,要得出需要多少個star。取整再除2,再取整數部分和小數部分。

因為半星只會有一個,所以只需一次push

長度不到5就補全。

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;
      }

接下來回到header組件去引入了,然后注冊。注冊之后就可以在DOM用這個標簽了。

Star標簽它是要傳兩個參數的。

Tract-byhttps://segmentfault.com/q/1010000005143763

查看元素:

還要在header.vue組件中設置他們的樣式,比如邊距什么的,當然不能放在組件里面,如果這樣就受限了。我們可以在在外層去包裝它的容器,然后在定義它的內邊距啊、高度等等

 

優惠公告:

這也是一個經典的布局問題:線的寬度是自適應,文字居中。文字與線之間的空隙也要有半透明的背景,這里會用移動端常見的布局flex。

Flex布局:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool

一般有兩層,父元素displayflex子元素指定flex

這里為什么子元素用div呢?因為用span的話在Android某些瀏覽器會有問題。

 

 

關於代碼中CSS的樣式兼容問題:我們並無需全部寫出,因為有工具幫忙完成:

接下來寫優惠信息詳細內容:

這塊內容跟我們外層的.support是相似的。

但是vue2.0中的index這樣用,請查看:http://cn.vuejs.org/v2/guide/list.html#v-for

接下來再添加詳細介紹,添加按鈕的關閉功能。

還可以添加動畫,我還沒添加。

https://vuefe.cn/v2/guide/migration.html#過渡

https://segmentfault.com/q/1010000007738500

還有一點就是:在設計稿上可以看到,它的背景是模糊的,和剛剛圖片模糊是完全不一樣的。這個模糊只有在IOS上才能實現,它的實現是通過一個backdrop-filter: blur(10px)

 

下一張就到了商品這個組件了,這個組件才是大大發揮vue的優勢。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM