1. 程式人生 > >vue導航欄自定義設定帶圖片(選中狀態重新整理不消失)

vue導航欄自定義設定帶圖片(選中狀態重新整理不消失)

轉載自https://blog.csdn.net/wang1006008051/article/details/78686451?utm_source=blogxgwz6

Vue導航欄

        用Vue寫手機端的專案,經常會寫底部導航欄,我這裡總結一套比較方便實用的底部導航欄方法,並且可以解決瀏覽器重新整理選中狀態消失的問題。也可以選擇自適應螢幕。看一下效果,底部的圖示全是UI給的選中和未選中樣式的圖片,根據公司要求,你也可能會用fontsize去寫。(全部程式碼黏貼到本文的最後面了)

1、首先把這些小圖片放到src/assets路徑下面(自動base64編碼)





2、在data()裡邊定義一個選中對應的變數isSelect,和迴圈遍歷的陣列,陣列下面放圖示對應的文字,和選中,未選中的圖片地址。   注意:圖片的地址不要直接寫,直接寫就是字串,不僅會出現顯示不出圖片的情況,而且打包之後,還是這裡地址,不會變。使用webpack提供的require引入圖片地址就可以解決以上問題。

   
  1. data () {
  2. return {
  3. isSelect: '首頁',
  4. nav: [
  5. {title: '首頁', url: require('../../assets/common/首頁@2x.png'), url_one: require('../../assets/common/首頁
    [email protected]
    ')},
  6. {title: '店鋪', url: require('../../assets/common/店鋪@2x.png'), url_one: require('../../assets/common/店鋪[email protected]')},
  7. {title: '創業直播', url: require('../../assets/common/直播@2x.png'), url_one: require('../../assets/common/直播[email protected]')},
  8. {title: '我的', url: require('../../assets/common/我的@2x.png'), url_one: require('../../assets/common/我的[email protected]')}
  9. ]
  10. }
  11. },

html遍歷這個nav陣列,並且給每個li註冊點選事件selectNav(),引數就是title。

   
  1. <ul>
  2. <li v-for="item in nav" @click="selectNav(item.title)">
  3. <img :src="isSelect === item.title ? item.url_one : item.url" alt="item.title">
  4. <p :class="isSelect === item.title ? 'active' : ''">{{item.title}} </p>
  5. </li>
  6. </ul>

在methods中定義這個事件

   
  1. methods: {
  2. selectNav (title) {
  3. this.isSelect = title
  4. }

3、這個方法裡還可以根據title的值去跳轉到相應的路由,這樣一個基本的底部導航欄就是實現了。

   
  1. methods: {
  2. selectNav (title) {
  3. this.isSelect = title
  4. switch (title) {
  5. case '首頁': this.$router.push('/index')
  6. break
  7. case '店鋪': this.$router.push('/shop')
  8. break
  9. case '創業直播': this.$router.push('/live')
  10. break
  11. case '我的': this.$router.push('/my')
  12. break
  13. }
  14. sessionStorage.setItem('isSelect', this.isSelect)
  15. }
  16. }

但是 電腦除錯的時候會發現,重新整理瀏覽器後,選中的狀態就會消失。(你可能會覺得使用者一般不會在手機端重新整理頁面/或者直接輸入路由跳轉到相應的頁面,如果要追求完美的,請繼續往下看微笑 比如,我選中的狀態是創業直播:


當我點選重新整理頁面後,就會返回到預設的首頁狀態,如下。


解決辦法: 每次點選切換底部導航的時候,把選中的狀態存入sessStorage裡邊。在mounted鉤子裡把這個狀態取出來賦值給這個isSelect變數就可以實現選中狀態不消失了。

   
  1. mounted () {
  2. this.isSelect = sessionStorage.getItem('isSelect')
  3. },
  4. methods: {
  5. selectNav (title) {
  6. this.isSelect = title
  7. sessionStorage.setItem('isSelect', this.isSelect)
  8. }
  9. }

經過測試,新的問題又發現了,比如當前在“創業直播”這個狀態上,我在瀏覽器上直接輸入“http://localhost:8080/#/shop”,這樣用上面的辦法就解決不了問題了。最好的辦法就是和路由繫結無論點選,還是瀏覽器上輸入路由改變,都正確顯示選中狀態。
在router/index.js裡邊對映元件路由時,加上對應的name

    
  1. routes: [
  2. {
  3. path: '/',
  4. redirect: '/index'
  5. },
  6. {
  7. path: '/index',
  8. name: '首頁',
  9. component: index
  10. },
  11. {
  12. path: '/live',
  13. name: '創業直播',
  14. component: live
  15. },
  16. {
  17. path: '/my',
  18. name: '我的',
  19. component: my
  20. },
  21. {
  22. path: '/shop',
  23. name: '店鋪',
  24. component: shop
  25. }
  26. ]

mounted鉤子裡邊的程式碼改為:

    
  1. mounted () {
  2. this.isSelect = this.$route.name
  3. },

methods方法裡邊的程式碼修改為

4、手機端一般要求自適應各種大小的手機端螢幕,你可以選擇用媒體查詢,或者js控制font-size。這裡我用的是js控制font-size,在index.html引入下面的js。

   
  1. * rem計算方式:設計圖尺寸px / 100 = 實際rem 【例: 100px = 1rem,32px = .32rem】
  2. */
  3. !function (window) {
  4. /* 設計圖文件寬度 */
  5. var docWidth = 750;
  6. var doc = window.document,
  7. docEl = doc.documentElement,
  8. resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
  9. var recalc = (function refreshRem () {
  10. var clientWidth = docEl.getBoundingClientRect().width;
  11. /* 8.55:小於320px不再縮小,11.2:大於420px不再放大 */
  12. docEl.style.fontSize = Math.max(Math.min(20 * (clientWidth / docWidth), 11.2), 8.55) * 5 + 'px';
  13. return refreshRem;
  14. })();
  15. /* 新增倍屏標識,安卓為1 */
  16. docEl.setAttribute('data-dpr', window.navigator.appVersion.match(/iphone/gi) ? window.devicePixelRatio : 1);
  17. if (/iP(hone|od|ad)/.test(window.navigator.userAgent)) {
  18. /* 新增IOS標識 */
  19. doc.documentElement.classList.add('ios');
  20. /* IOS8以上給html新增hairline樣式,以便特殊處理 */
  21. if (parseInt(window.navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/)[1], 10) >= 8)
  22. doc.documentElement.classList.add('hairline');
  23. }
  24. if (!doc.addEventListener) return;
  25. window.addEventListener(resizeEvt, recalc, false);
  26. doc.addEventListener('DOMContentLoaded', recalc, false);
  27. }(window);

使用方法:

把視覺稿中的px轉換成rem;

 rem計算方式:設計圖尺寸px / 100 = 實際rem 【例: 100px = 1rem,32px = 0.32rem】;

 特別注意:是不需要再除以2的!

無論設計圖什麼尺寸,演算法一致。但需修改js 中 docWidth 變數為設計圖寬度;預設設計圖文件寬度為750px; 一些不使用rem的CSS屬性。包括但不限於:border-widthborder-radiusbox-shadowtransformbackground-size



附錄底部導航欄的程式碼(樣式使用了less預編譯):

   
  1. <template>
  2. <div class="common_foot">
  3. <ul>
  4. <li v-for="item in nav" @click="selectNav(item.title)">
  5. <img :src="isSelect === item.title ? item.url_one : item.url" alt="item.title">
  6. <p :class="isSelect === item.title ? 'active' : ''">{{item.title}} </p>
  7. </li>
  8. </ul>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. data () {
  14. return {
  15. isSelect: '首頁',
  16. nav: [
  17. { title: '首頁', url: require( '../../assets/common/首頁@2x.png'), url_one: require( '../../assets/common/首頁[email protected]')},
  18. { title: '店鋪', url: require( '../../assets/common/店鋪@2x.png'), url_one: require( '../../assets/common/店鋪[email protected]')},
  19. { title: '創業直播', url: require( '../../assets/common/直播@2x.png'), url_one: require( '../../assets/common/直播[email protected]')},
  20. { title: '我的', url: require( '../../assets/common/我的@2x.png'), url_one: require( '../../assets/common/我的[email protected]')}
  21. ]
  22. }
  23. },
  24. mounted () {
  25. this.isSelect = this.$route.name
  26. },
  27. methods: {
  28. selectNav (title) {
  29. switch (title) {
  30. case '首頁': this.$router.push( '/index')
  31. break
  32. case '店鋪': this.$router.push( '/shop')
  33. break
  34. case '創業直播': this.$router.push( '/live')
  35. break
  36. case '我的': this.$router.push( '/my')
  37. break
  38. }
  39. this.isSelect = this.$route.name
  40. }
  41. }
  42. }
  43. </script>
  44. <style lang="less" scoped>
  45. .common_foot>ul{
  46. position: fixed;
  47. bottom: 0;
  48. z-index: 1000;
  49. height: 0.98rem;
  50. width: 100%;
  51. overflow: hidden;
  52. background-color: white;
  53. li{
  54. float: left;
  55. width: 25%;
  56. height: 100%;
  57. text-align: center;
  58. cursor: pointer;
  59. padding: 0.15rem 0 0.13rem 0;
  60. }
  61. p{font-size: 0.2rem;color: #7f7f7f;}
  62. img{
  63. width: 0.48rem;
  64. height: 0.45rem;
  65. }
  66. .active{
  67. color: #ffd100;
  68. }
  69. }
  70. </style>