前端框架Vue自學之Vue router小案例TabBar(七)


內容:TabBar設計與實現

正文:

TabBar

零、前言(源碼

  可以結合源碼來看,最后自己實現。源碼在我的GitHub上:TabBar源碼(Vue-router小案例)。

一、tabbar的基本結構的搭建

  1、需求

  tabbar就是類似下圖的東西。可以讓我們傳入一些組件,圖片,文字等。當我們點擊“首頁”,顯示首頁的相關東西;當我們點擊‘分類’,顯示分類的相關東西等。其實,這就是相當於把項目的結構搭建好了,之后我們做的項目中,就是往每個不同的選項構建對應的組件。

  

    2、實現思路(后續,就按照這個思路去一步步實現)

  首先,如果在下方有一個單獨的TabBar組件,你如何封裝?自定義TabBar組件,在App中使用;讓TabBar處於底部,並且設置相關的樣式。 

  接着,TabBar中顯示的內容由外界決定:定義插槽;flex布局平分TabBar。

  接着,自定義TabBarItem,可以傳入圖片和文字:定義TabBarItem,並且定義兩個插槽:圖片和文字;給兩個插槽外層包裝div,用於設置樣式;填充插槽,實現底部TabBar的效果。

  接着, 傳入高亮圖片。定義另外一個插槽,插入active-icon的數據。定義一個變量isActive,通過v-show來決定是否顯示對應的icon。

  接着,TabBarItem綁定路由數據。安裝路由(npm install vue-router --save);完成router/index,js的內容,以及創建對應的組件;main.js中注冊router;App中加入<router-view>組件。

  接着,點擊item跳轉到對應路由,並且動態決定isActive。監聽item的點擊,通過this.$router.replace()替換路由路徑;通過this.$route.path.indexOf(this.link)!== -1來判斷是否是active。

  接着,動態計算active樣式。封裝新的計算屬性:this.isActive?{'color':'red'}:{}。

  3、VScode下,搭建tabbar的基本結構

   首先,用Vue CLI2創建項目(Vue CLI3也可以)。目錄終端輸入vue init webpack tabbar。選項中注意使用runtimeonly(之前博客有分析過),安裝路由(沒安裝也沒關系,后面我們手動安裝)。

  我們先把默認安裝的一些東西刪除,如自帶的HelloWorld.vue,App.vue的對應HelloWorld的引入,樣式等。(此時,npm run dev ,頁面應該是一片空白的)

  注意,我們要用封裝的思想,近可能多使用插槽,多復用一些公共的組件的思想。

  在src/assets創建img和css文件夾,在css文件夾下創建base.css(初始樣式),並在App.vue中的style便簽內用@import這個文件。

  

  

   接着我們添加tabbarItem,並且讓tab-bar水平分布,給背景色,邊緣設置陰影,並且讓其處於頁面底部。tab-bar-item居中均等分,高度一般為49px(移動開發的經驗值)。

  (App.vue)

  (App.vue)

  (結果預覽)

二、TabBar和TabBarItem組件封裝

  之前我們寫的TabBarItem非常不好,如果我們別的項目也要用時,要復制的代碼太多了(HTML代碼還有其樣式代碼等),我們要將其封裝成獨立的組件。這樣就方便復用了。

  1、基本實現

  首先在components文件夾創建tabbar文件夾,里面放置關於tabbar功能的組件。在該文件夾下,創建TabBar.vue組件,然后將原來在App.vue寫關於tabbar功能的部分對應寫到TabBar.vue。如<template>的內容和<style>的內容。

  並且在App.vue導入、注冊和使用TabBar組件。

   

   頁面顯示的結果和之前一樣。但是我們把TabBar封裝成組件了。

  接着,我們把tabbaritem相關圖片放置在之前創建的img文件夾中(放在創建一個tabbar文件夾中)。(如果想在VScode里面預覽SVG圖片,可以安裝SVG Viewer插件)

  

  可以發現我們的圖標每種分為兩類,一類是未激活,一類是激活狀態。

  

   然后,在TabBarItem里面使用img便簽,引入對應圖片。並且在style中設置大小。注意此時的img和我們的div內容如“首頁”等都是行內標簽,可以再用div把內容包含。

  

  

  (顯示效果)

  2、用組件化的思路重構之前的代碼

  上面寫的代碼,雖然最終可以實現我們想要的效果,但是我們可以發現,代碼邏輯已經是嵌套在一起了,我們希望,tabbar應該只關心自己大的組件的邏輯(tabbar的布局和tabbar的樣式),至於小的元素怎么布局不應該涉及,不然最后封裝的組件亂七八糟,令人煩惱。

  所以,tabbar封裝完之后,放入插槽slot即可。

   

   然后在App.vue使用的tabbar組件中把內容填進去(即插入了插槽),注意最后我們不會如下圖這么用,因為App.vue多了插槽內容的HTML代碼和樣式代碼,很亂。所以我們再創建一個組件。

  

  (頁面效果沒問題)

  所以我們再創建一個組件TabBarItem.vue組件(components/tabbar內),然后把屬於TabBarItem的template和style放到對應部分去,之后在到App.vue中導入、注冊、使用TabBarItem.vue組件。TabBarItem.vue組件的使用是放在之前使用的TabBar組件中的,就是把TabBarItem.vue組件插入TabBar組件的插槽。

 

   

    (頁面顯示4個item,因為插入4個組件)

  現在先暫時不管填充的內容,因為后面我們會動態填充。到此,我們必須理解的是:定義封裝了獨立邏輯(獨立的template和獨立的style)的大組件TabBar和其中小組件TabBarItem,並且可以通過slot插槽把小組件插入到大組件中。這樣做的好處是使用組件,不用再考慮樣式的問題,因為內部寫好了。

  現在又出現了新的問題,剛剛TabBarItem里面填充的內容不能寫死,不然在我們最后的頁面顯示的item都是一樣的了。所以,我們繼續在TabBarItem組件中使用slot插槽(有name屬性,分別放圖標和文字)。

  

  然后在App.vue使用這個組件的插槽。

   (頁面展示)

  此時,由於寫成小組件+插槽的形式,假如說我們需要5個tabbaritem,直接復用組件,往組件插槽填內容,即可。非常方便!(即使用<TabBarItem>組件,里面填內容)

  (組件隨意復用)

三、給TabBarItem傳入active圖片

  上一章中,我們只使用了未激活的圖片,我們想當item處於活躍狀態的時候顯示另一張圖片(對應的活躍的圖片)。

  所以在TabBarItem里面還需要一個插槽,用於放置圖片(未激活與激活)。注意,是一開始把兩張未激活與激活的圖片傳入到組件,然后通過狀態決定顯示哪一張,而不是根據狀態插一張,另一個狀態插一張。

  首先在TabBarItem組件中,假如一個slot。

  

   然后,在App.vue中插入激活圖片(一共傳兩個圖片)。

   但此時,沒有根據狀態確定顯示激活圖片還是未激活圖片,此時同時顯示兩張圖,這是不對的。

  

   我們很容易想到使用v-if和v-else,加上一個激活變量isActive,來做。此外,如果我們想激活時,對應的item-text文字部分也變紅(變個樣式),也要設定一個有激活變量控制的樣式。注意,插槽內容渲染時,會替換插槽slot的代碼,如果我們想在插槽設定樣式(包括剛剛說的v-if,v-else等屬性),必須用div包裹其中,把本想寫在插槽的樣式寫在這個div中

   

   此時,可以通過isActive為true還是false(狀態),來控制顯示的圖標和文字是否處於激活狀態。

  (isActive: true)

  (isActive: false)

四、TabBarItem和路由結合效果

  我們希望點擊具體的item,頁面主題得顯示對應item的“主頁內容”,即我們先點擊“首頁”,在主頁內容中顯示“首頁”的東西(其實也是一個組件,即關於首頁的組件)。現在我們就想讓小組件TabBarItem與大組件頁面主體一一對應(映射關系)。這就使用到我們的vue-router了(終於回歸了主題,組件化思想的開發)。

  首先,我們先安裝路由(如果之前沒有在項目安裝的話)。l路徑終端輸入npm install vue-router --save (運行時依賴)。在src下創建router文件夾,並在router文件夾下建立index.js。在index.js導入vue,VueRouter;安裝VueRouter插件,創建路由對象,配置路由映射關系,導出路由,導入路由(main.js中),在vue實例掛載路由(在我前一個博客里有具體說明)。

  (index.js)

  (main.js)

  由於我們有四個TabBarItem,所以要配置四個路由映射。當然也要創建四個大的組件啦(都是視圖/大頁面方面的組件)。通常,先在src文件夾下創建views文件夾(通常放置視圖、大的頁面的組件),然后在views文件夾內在創建四個我們關於TabBarItem對應的大組件的文件夾:home文件夾,category文件夾,cart文件夾,profile文件夾。每個文件夾就是放置關於這個視圖的組件文件。我們簡單在里面創建對應大組件(先簡單顯示一些文字內容即可)。

  補充:通常src/components放置的是公共組件。

  

    然后,來到index.js配置我們的映射關系。要注意使用懶加載哦。

  (注意是component不是components,這個小失誤害我調試半天)

     接着,我們需要監聽某個TabBarItem的點擊,從而對應渲染出某個視圖組件。

  我們完全可以在子組件TabBarItem.vue進行監聽(而不是具體使用組件的那里監聽,不然就得監聽4次了),方法中使用綁定的path屬性修改當前路徑,即使用props往組件綁定屬性(path屬性)。然后在使用組件的時候(App.vue),傳入路徑path。路由模式也可以使用為history。

    (注意寫上<router-view>不然不會顯示組件)

  (點擊購物車,路由跳轉到購物車組件,主頁顯示購物車組件(里面只是簡單的內容:購物車車),點擊其他item也是有路由跳轉到對應組件)

五、TabBarItem的顏色動態控制

  第三章,我們只講到了狀態isActive控制圖片和文字是否處於激活狀態的圖片和文字。但我們通常是點擊(激活)某個具體的item,讓其處於激活,其他的item處於未激活。

  所以,狀態isActive變量不能寫死,需要動態傳遞。使用計算屬性。通過結合$route(活躍路由對象,只有一個)及判斷item路徑和活躍路徑對比來實現狀態控制。注意取反哦。

  (TabBarItem.vue)

  (點擊首頁,首頁被激活;點其他的也一樣)

   現在還有一個問題(需求)。我們之前寫的代碼,點擊的TabBarItem的文字部分的樣式是直接寫死的,即都是只能在活躍的時候顯示紅色,這個封裝也是不夠合理的。合理的組件封裝應該不需要使用者修改組件源碼的。

  所以我們希望別人在使用TabBarItem組件(App.vue中),就能自由選擇想選的顏色。類似於下圖用法,這樣別人就不需要知道我們在TabBarItem組件設計時的源碼是怎么寫的了。

  

   首先,我們在props中寫activeColor對象,里面有類型type和默認的顏色。

   

   然后用計算屬性activeStyle,綁定動態的style。

   

    最后,在使用TabBarItem組件時,可以選擇使用一些想選的顏色。也可以選擇不選,則為默認顏色。

   (字體顯示默認顏色)

  (字體,顯示設定的藍色)

六、進一步組件化

  我們可以看到,之前我們寫了一大推代碼在App.vue里面,其實還是可以進一步簡化的。  

   首先,發現tab-bar組件內很多代碼,我們可以把其封裝成一個組件,最后在App.vue里面使用這個組件即可。這就是組件化開發,形成了組件樹,根組件為App.vue,App.vue所引用的的組件是其子組件,子組件可能還引用了別的組件等。

  大致步驟:先在components/tabbar下創建MainTabBar.vue組件。然后把剛剛在App.vue里面寫關於Tabbar的template和組件全部放在這個MainTabBar.vue組件內封裝,注意修改文件的路徑(或者使用本博客最后一點知識:給路徑起別名的方式)。

  

   然后在App.vue中使用這個封裝的MainTabBar.vue組件。這樣App.vue的代碼結構就很清晰好看了。

   最終的頁面效果也是不變的。

  補充:給路徑起別名。(webpack配置中的resolve對象的alias屬性)

  之前發現,我們在復制一些代碼到別的目錄下時,一些資源文件的路徑需要重新配置,非常的不方便。

  由於我們是用腳手架vue CLI來構建項目的,在build文件夾webpack.base.conf.js(公共基礎配置)中,已經是有一些解決方案(resolve),如:

  

   其中,extensions的意思是,我們在引用一些文件、資源時,可以省略的擴展名。例如我們引用Home.vue這個組件,可以直接寫成引用Home即可。

  alias是別名的意思。這里是給src起別名(src是源文件目錄),起為@,意思是說在使用路徑時,可以通過@代替src。也就是說當我們想使用某個文件資源時,以src(@)為路徑去引用。這樣的好處就是可以把某個組件使用到的路徑直接復制使用到別的組件中,確保引入文件的路徑是正確的。

  類似道理,我們把一些常用資源的文件路徑給起別名,然后每次用的時候就方便很多了。常用的起別名有:

  (注意)

   當然還有其他路徑,后面我們用到在添加。也就是說方便我們寫項目代碼的,就可以添加。

  但注意,import所導入的路徑可以使用這種起別名的路徑。而HTML標簽內,如src屬性,則需要在別名前加~(波浪號),不然找不到路徑。


免責聲明!

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



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