vue实现导航栏效果(选中状态刷新不消失)

作者:羞羞的铁拳 时间:2024-05-09 15:18:31 

Vue导航栏       

用Vue写手机端的项目,经常会写底部导航栏,我这里总结一套比较方便实用的底部导航栏方法,并且可以解决浏览器刷新选中状态消失的问题。也可以选择自适应屏幕。看一下效果,底部的图标全是UI给的选中和未选中样式的图片,根据公司要求,你也可能会用fontsize去写。(全部代码黏贴到本文的最后面了)

vue实现导航栏效果(选中状态刷新不消失)

1、首先把这些小图片放到src/assets路径下面(自动base64编码)

vue实现导航栏效果(选中状态刷新不消失)
vue实现导航栏效果(选中状态刷新不消失)

2、在data()里边定义一个选中对应的变量isSelect,和循环遍历的数组,数组下面放图标对应的文字,和选中,未选中的图片地址。  注意:图片的地址不要直接写,直接写就是字符串,不仅会出现显示不出图片的情况,而且打包之后,还是这里地址,不会变。使用webpack提供的require引入图片地址就可以解决以上问题。


data () {
return {
isSelect: '首页',
nav: [
{title: '首页', url: require('../../assets/common/首页@2x.png'), url_one: require('../../assets/common/首页_active@2x.png')},
{title: '店铺', url: require('../../assets/common/店铺@2x.png'), url_one: require('../../assets/common/店铺_active@2x.png')},
{title: '创业直播', url: require('../../assets/common/直播@2x.png'), url_one: require('../../assets/common/直播_active@2x.png')},
{title: '我的', url: require('../../assets/common/我的@2x.png'), url_one: require('../../assets/common/我的_active@2x.png')}
]
}
},

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

但是电脑调试的时候会发现,刷新浏览器后,选中的状态就会消失。(你可能会觉得用户一般不会在手机端刷新页面/或者直接输入路由跳转到相应的页面,如果要追求完美的,请继续往下看)比如,我选中的状态是创业直播:

vue实现导航栏效果(选中状态刷新不消失)

当我点击刷新页面后,就会返回到默认的首页状态,如下。

vue实现导航栏效果(选中状态刷新不消失)

解决办法:

每次点击切换底部导航的时候,把选中的状态存入sessStorage里边。在mounted钩子里把这个状态取出来赋值给这个isSelect变量就可以实现选中状态不消失了。


mounted () {
this.isSelect = sessionStorage.getItem('isSelect')
},
methods: {
selectNav (title) {
this.isSelect = title
sessionStorage.setItem('isSelect', this.isSelect)
}
}

经过测试,新的问题又发现了,比如当前在&ldquo;创业直播&rdquo;这个状态上,我在浏览器上直接输入&ldquo;http://localhost:8080/#/shop&rdquo;,这样用上面的办法就解决不了问题了。最好的办法就是和路由绑定无论点击,还是浏览器上输入路由改变,都正确显示选中状态。

在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/首页_active@2x.png')},
{title: '店铺', url: require('../../assets/common/店铺@2x.png'), url_one: require('../../assets/common/店铺_active@2x.png')},
{title: '创业直播', url: require('../../assets/common/直播@2x.png'), url_one: require('../../assets/common/直播_active@2x.png')},
{title: '我的', url: require('../../assets/common/我的@2x.png'), url_one: require('../../assets/common/我的_active@2x.png')}
]
}
},
mounted () {
this.isSelect = this.$route.name
},
methods: {
selectNav (title) {
this.isSelect = this.$route.name
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
}
}
}
}
</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>

本文已被整理到了《Vue.js前端组件学习教程》,欢迎大家学习阅读。

关于vue.js组件的教程,请大家点击专题vue.js组件学习教程进行学习。

更多vue学习教程请阅读专题《vue实战教程》

来源:http://blog.csdn.net/wang1006008051/article/details/78686451

标签:vue,导航栏
0
投稿

猜你喜欢

  • Python快速从注释生成文档的方法

    2022-07-11 04:55:37
  • 提升Go语言开发效率的小技巧实例(GO语言语法糖)汇总

    2023-07-08 10:01:26
  • Python基础第三方模块requests openpyxl

    2023-09-24 04:31:32
  • 超详细Python解释器新手安装教程

    2021-08-14 07:10:01
  • MySQL之主键索引排序失效问题

    2024-01-19 10:38:53
  • 深入浅出SQL教程之SELECT语句的自连接

    2009-08-30 15:17:00
  • Python MySQL 日期时间格式化作为参数的操作

    2024-01-12 23:52:13
  • Python实现Socket通信建立TCP反向连接

    2023-11-13 04:20:19
  • mysql中#{}和${}的区别详解

    2024-01-12 21:37:17
  • Python中删除文件的几种方法实例

    2021-02-02 05:57:13
  • C#简单连接sql数据库的方法

    2024-01-14 09:01:27
  • python和websocket构建实时日志跟踪器的步骤

    2023-08-11 08:28:20
  • 在ASP应用程序中加入智能搜索

    2007-09-18 13:15:00
  • Vue路由切换和Axios接口取消重复请求详解

    2024-04-30 10:28:17
  • Pytorch创建张量的四种方法

    2023-11-20 15:25:36
  • js+css实现换肤效果

    2024-04-17 09:53:54
  • python实现的config文件读写功能示例

    2021-10-11 07:28:04
  • 一个简单的ASP生成HTML分页程序

    2009-07-05 18:32:00
  • Python的Flask站点中集成xhEditor文本编辑器的教程

    2023-04-05 00:41:06
  • MySQL 数据库 source 命令详解及实例

    2024-01-15 10:50:58
  • asp之家 网络编程 m.aspxhome.com