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


Posted in Javascript onDecember 13, 2017

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

经过测试,新的问题又发现了,比如当前在“创业直播”这个状态上,我在浏览器上直接输入“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/首页_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实战教程》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
innertext , insertadjacentelement , insertadjacenthtml , insertadjacenttext 等区别
Jun 29 Javascript
javascript代码加载优化方法
Jan 30 Javascript
js中的string.format函数代码
Aug 11 Javascript
jquery ajax学习笔记2 使用XMLHttpRequest对象的responseXML
Oct 16 Javascript
js离开或刷新页面检测(且兼容FF,IE,Chrome)
Mar 05 Javascript
jQueryMobile之Helloworld与页面切换的方法
Feb 04 Javascript
jQuery CSS3自定义美化Checkbox实现代码
May 12 Javascript
JSONP原理及简单实现
Jun 08 Javascript
JavaScript数据结构之优先队列与循环队列实例详解
Oct 27 Javascript
Vue2.0用户权限控制解决方案
Nov 29 Javascript
Angular4.x Event (DOM事件和自定义事件详解)
Oct 09 Javascript
vue3自定义dialog、modal组件的方法
Jan 04 Vue.js
仿京东快报向上滚动的实例
Dec 13 #Javascript
Angular2使用vscode断点调试ts文件的方法
Dec 13 #Javascript
vue-router路由懒加载和权限控制详解
Dec 13 #Javascript
JS+canvas画一个圆锥实例代码
Dec 13 #Javascript
JS排序算法之冒泡排序,选择排序与插入排序实例分析
Dec 13 #Javascript
实例分析js事件循环机制
Dec 13 #Javascript
javascript实现QQ空间相册展示源码
Dec 12 #Javascript
You might like
PHP 和 MySQL 开发的 8 个技巧
2006/10/09 PHP
PHP 第一节 php简介
2012/04/28 PHP
通过PHP的内置函数,通过DES算法对数据加密和解密
2012/06/21 PHP
简单的方法让你的后台登录更加安全(php中加session验证)
2012/08/22 PHP
如何利用PHP执行.SQL文件
2013/07/05 PHP
PHP连接局域网MYSQL数据库的简单实例
2013/08/26 PHP
thinkPHP实现基于ajax的评论回复功能
2018/06/22 PHP
ThinkPHP5.1框架数据库链接和增删改查操作示例
2019/08/03 PHP
javascript 星级评分效果(手写)
2012/12/24 Javascript
Javascript算符的优先级介绍
2013/03/20 Javascript
JQuery仿小米手机抢购页面倒计时效果
2014/12/16 Javascript
JavaScript中property和attribute的区别详细介绍
2015/03/03 Javascript
JavaScript使用push方法添加一个元素到数组末尾用法实例
2015/04/06 Javascript
jQuery实现的Div窗口震动效果实例
2015/08/07 Javascript
浅谈javascript函数式编程
2015/09/06 Javascript
详解Javascript百度地图接口开发文档中的类和方法
2017/02/07 Javascript
浅谈在koa2中实现页面渲染的全局数据
2017/10/09 Javascript
在nginx上部署vue项目(history模式)的方法
2017/12/28 Javascript
Vuex的各个模块封装的实现
2020/06/05 Javascript
jQuery实现异步上传一个或多个文件
2020/08/17 jQuery
Python 文件和输入输出小结
2013/10/09 Python
python 性能提升的几种方法
2016/07/15 Python
python3.6.3安装图文教程 TensorFlow安装配置方法
2020/06/24 Python
Python中对数组集进行按行打乱shuffle的方法
2018/11/08 Python
django 2.2和mysql使用的常见问题
2019/07/18 Python
浅谈python出错时traceback的解读
2020/07/15 Python
阳光体育:Sunny Sports(购买露营和远足设备)
2018/08/07 全球购物
什么是.net
2015/08/03 面试题
毕业生的自我鉴定该怎么写
2013/12/02 职场文书
一年级语文教学反思
2014/02/13 职场文书
关爱留守儿童标语
2014/06/18 职场文书
党校学习心得体会范文
2014/09/09 职场文书
干货:我将这样书写我的演讲稿!
2019/05/09 职场文书
Python 中的单分派泛函数你真的了解吗
2021/06/22 Python
纯 CSS 自定义多行省略的问题(从原理到实现)
2021/11/11 HTML / CSS
Hive日期格式转换方法总结
2022/06/25 数据库