vue導航欄自定義設定帶圖片(選中狀態重新整理不消失)
阿新 • • 發佈:2018-11-24
轉載自https://blog.csdn.net/wang1006008051/article/details/78686451?utm_source=blogxgwz6
Vue導航欄
用Vue寫手機端的專案,經常會寫底部導航欄,我這裡總結一套比較方便實用的底部導航欄方法,並且可以解決瀏覽器重新整理選中狀態消失的問題。也可以選擇自適應螢幕。看一下效果,底部的圖示全是UI給的選中和未選中樣式的圖片,根據公司要求,你也可能會用fontsize去寫。(全部程式碼黏貼到本文的最後面了)1、首先把這些小圖片放到src/assets路徑下面(自動base64編碼)
2、在data()裡邊定義一個選中對應的變數isSelect,和迴圈遍歷的陣列,陣列下面放圖示對應的文字,和選中,未選中的圖片地址。 注意:圖片的地址不要直接寫,直接寫就是字串,不僅會出現顯示不出圖片的情況,而且打包之後,還是這裡地址,不會變。使用webpack提供的require引入圖片地址就可以解決以上問題。
- data () {
- return {
- isSelect: '首頁',
- nav: [
- {title: '首頁', url: require('../../assets/common/首頁@2x.png'), url_one: require('../../assets/common/首頁
[email protected]')},- {title: '店鋪', url: require('../../assets/common/店鋪@2x.png'), url_one: require('../../assets/common/店鋪[email protected]')},
- {title: '創業直播', url: require('../../assets/common/直播@2x.png'), url_one: require('../../assets/common/直播[email protected]')},
- {title: '我的', url: require('../../assets/common/我的@2x.png'), url_one: require('../../assets/common/我的[email protected]')}
- ]
- }
- },
html遍歷這個nav陣列,並且給每個li註冊點選事件selectNav(),引數就是title。
-
<ul>
-
<li v-for="item in nav" @click="selectNav(item.title)">
-
<img :src="isSelect === item.title ? item.url_one : item.url" alt="item.title">
-
<p :class="isSelect === item.title ? 'active' : ''">{{item.title}}
</p>
-
</li>
-
</ul>
在methods中定義這個事件
- methods: {
- selectNav (title) {
- this.isSelect = title
- }
3、這個方法裡還可以根據title的值去跳轉到相應的路由,這樣一個基本的底部導航欄就是實現了。
- methods: {
- selectNav (title) {
- this.isSelect = title
- switch (title) {
- case '首頁': this.$router.push('/index')
- break
- case '店鋪': this.$router.push('/shop')
- break
- case '創業直播': this.$router.push('/live')
- break
- case '我的': this.$router.push('/my')
- break
- }
- sessionStorage.setItem('isSelect', this.isSelect)
- }
- }
但是 電腦除錯的時候會發現,重新整理瀏覽器後,選中的狀態就會消失。(你可能會覺得使用者一般不會在手機端重新整理頁面/或者直接輸入路由跳轉到相應的頁面,如果要追求完美的,請繼續往下看) 比如,我選中的狀態是創業直播:
當我點選重新整理頁面後,就會返回到預設的首頁狀態,如下。
解決辦法: 每次點選切換底部導航的時候,把選中的狀態存入sessStorage裡邊。在mounted鉤子裡把這個狀態取出來賦值給這個isSelect變數就可以實現選中狀態不消失了。
- mounted () {
- this.isSelect = sessionStorage.getItem('isSelect')
- },
- methods: {
- selectNav (title) {
- this.isSelect = title
- sessionStorage.setItem('isSelect', this.isSelect)
- }
- }
經過測試,新的問題又發現了,比如當前在“創業直播”這個狀態上,我在瀏覽器上直接輸入“http://localhost:8080/#/shop”,這樣用上面的辦法就解決不了問題了。最好的辦法就是和路由繫結無論點選,還是瀏覽器上輸入路由改變,都正確顯示選中狀態。
在router/index.js裡邊對映元件路由時,加上對應的name
- routes: [
- {
- path: '/',
- redirect: '/index'
- },
- {
- path: '/index',
- name: '首頁',
- component: index
- },
- {
- path: '/live',
- name: '創業直播',
- component: live
- },
- {
- path: '/my',
- name: '我的',
- component: my
- },
- {
- path: '/shop',
- name: '店鋪',
- component: shop
- }
- ]
mounted鉤子裡邊的程式碼改為:
- mounted () {
- this.isSelect = this.$route.name
- },
methods方法裡邊的程式碼修改為
4、手機端一般要求自適應各種大小的手機端螢幕,你可以選擇用媒體查詢,或者js控制font-size。這裡我用的是js控制font-size,在index.html引入下面的js。
- * rem計算方式:設計圖尺寸px / 100 = 實際rem 【例: 100px = 1rem,32px = .32rem】
- */
- !function (window) {
- /* 設計圖文件寬度 */
- var docWidth = 750;
- var doc = window.document,
- docEl = doc.documentElement,
- resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
- var recalc = (function refreshRem () {
- var clientWidth = docEl.getBoundingClientRect().width;
- /* 8.55:小於320px不再縮小,11.2:大於420px不再放大 */
- docEl.style.fontSize = Math.max(Math.min(20 * (clientWidth / docWidth), 11.2), 8.55) * 5 + 'px';
- return refreshRem;
- })();
- /* 新增倍屏標識,安卓為1 */
- docEl.setAttribute('data-dpr', window.navigator.appVersion.match(/iphone/gi) ? window.devicePixelRatio : 1);
- if (/iP(hone|od|ad)/.test(window.navigator.userAgent)) {
- /* 新增IOS標識 */
- doc.documentElement.classList.add('ios');
- /* IOS8以上給html新增hairline樣式,以便特殊處理 */
- if (parseInt(window.navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/)[1], 10) >= 8)
- doc.documentElement.classList.add('hairline');
- }
- if (!doc.addEventListener) return;
- window.addEventListener(resizeEvt, recalc, false);
- doc.addEventListener('DOMContentLoaded', recalc, false);
- }(window);
使用方法:
把視覺稿中的px轉換成rem;
rem計算方式:設計圖尺寸px / 100 = 實際rem 【例: 100px = 1rem,32px = 0.32rem】;
特別注意:是不需要再除以2的!
無論設計圖什麼尺寸,演算法一致。但需修改js 中 docWidth 變數為設計圖寬度;預設設計圖文件寬度為750px; 一些不使用rem的CSS屬性。包括但不限於:border-width、border-radius、box-shadow、transform、background-size;
附錄底部導航欄的程式碼(樣式使用了less預編譯):
-
<template>
-
<div class="common_foot">
-
<ul>
-
<li v-for="item in nav" @click="selectNav(item.title)">
-
<img :src="isSelect === item.title ? item.url_one : item.url" alt="item.title">
-
<p :class="isSelect === item.title ? 'active' : ''">{{item.title}}
</p>
-
</li>
-
</ul>
-
</div>
-
</template>
-
-
<script>
-
export
default {
-
data () {
-
return {
-
isSelect:
'首頁',
-
nav: [
-
{
title:
'首頁',
url:
require(
'../../assets/common/首頁@2x.png'),
url_one:
require(
'../../assets/common/首頁[email protected]')},
-
{
title:
'店鋪',
url:
require(
'../../assets/common/店鋪@2x.png'),
url_one:
require(
'../../assets/common/店鋪[email protected]')},
-
{
title:
'創業直播',
url:
require(
'../../assets/common/直播@2x.png'),
url_one:
require(
'../../assets/common/直播[email protected]')},
-
{
title:
'我的',
url:
require(
'../../assets/common/我的@2x.png'),
url_one:
require(
'../../assets/common/我的[email protected]')}
-
]
-
}
-
},
-
mounted () {
-
this.isSelect =
this.$route.name
-
},
-
methods: {
-
selectNav (title) {
-
switch (title) {
-
case
'首頁':
this.$router.push(
'/index')
-
break
-
case
'店鋪':
this.$router.push(
'/shop')
-
break
-
case
'創業直播':
this.$router.push(
'/live')
-
break
-
case
'我的':
this.$router.push(
'/my')
-
break
-
}
-
this.isSelect =
this.$route.name
-
}
-
}
-
}
-
</script>
-
-
<style lang="less" scoped>
-
.common_foot>ul{
-
position: fixed;
-
bottom: 0;
-
z-index: 1000;
-
height: 0.98rem;
-
width: 100%;
-
overflow: hidden;
-
background-color: white;
-
li{
-
float: left;
-
width: 25%;
-
height: 100%;
-
text-align: center;
-
cursor: pointer;
-
padding: 0.15rem 0 0.13rem 0;
-
}
-
p{font-size: 0.2rem;color: #7f7f7f;}
-
img{
-
width: 0.48rem;
-
height: 0.45rem;
-
}
-
.active{
-
color: #ffd100;
-
}
-
}
-
</style>