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

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/首页_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)
 }
 }

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

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

解决办法:

每次点击切换底部导航的时候,把选中的状态存入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实战教程》

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

(0)

相关推荐

  • vue+elementUI动态生成面包屑导航教程

    效果如下所示: 项目需要动态生成面包屑导航,并且首页可以点击.其余为路径显示 <el-menu :unique-opened="true" router :default-active="$route.path" @select="handleSelect"> <div class="user-menu-box" v-for="menu in menus" :key="menu.

  • vue实现nav导航栏的方法

    每一个网页项目都少不了导航栏,通过原始的方法基本上都是可以写出来的.但是要写出代码量少,冗余度低的代码就要动脑子思考一下了. 最近写了一个百度地图的项目,要求底部有一个导航栏.具体如下图: 首先,拿到了底部导航栏的所有图标图片,图片都有两种.灰色的代表未选中,选中的用带样色的图片替换. 先看一下,组件中 html结构:通过vue提供的v-for方法,进行遍历显示footNav这个数组.数组里边存放着{title:"银行",url:" ",url1:" &q

  • vue2.0 elementUI制作面包屑导航栏

    Main.js var routeList = []; router.beforeEach((to, from, next) => { var index = -1; for(var i = 0; i < routeList.length; i++) { if(routeList[i].name == to.name) { index = i; break; } } if (index !== -1) { //如果存在路由列表,则把之后的路由都删掉 routeList.splice(index

  • Vuex,iView UI面包屑导航使用扩展详解

    本案例是基于Vuex的公共数据库,你在了解本案例之前要了解Vuex的使用方法. https://www.iviewui.com/components/breadcrumb 打开网址我们可以知道这个组件的面包屑导航是基于路由跳转的.但是我们项目中常常用到单页面查询面包屑导航.小生开始为这个纠结好久.然后和小伙伴一起研究出来一套单页面不用路由跳转的使用方法. 先看看效果图 1,首次进来 2,查询结果 3,再次点击面包屑导航 4,查询结果 基本的效果是这样的 下面看代码 <template> <

  • Vue 解决多级动态面包屑导航的问题

    固定路由的面包屑导航 我们在配置router的时候,可以将面包屑数据配置在meta中, 例如 路由配置: { path: '/project/process/:id', name: 'process', component: () => import('@/views/project/process/main.vue'), meta: [ { name: '项目管理列表' }, { name: '项目列表', url: '/project/list' }, { name: '里程碑' }, ],

  • vue 和vue-touch 实现移动端左右导航效果(仿京东移动站导航)

    先给大家展示下效果图,感觉还不错请参考实现代码: 使用技术:vue2.0 webpack vue-touch 一些简单的javascript; (注意:vue-touch 使用的是2.0.0版本 需要与vue2.0.0兼容) vue-touch(地址:https://github.com/vuejs/vue-touch 注意是next 分支) 左侧导航可滑动(右侧视图窗因为和左逻辑一样 就没写) var VueTouch = require('vue-touch') Lib.Vue.use(Vu

  • vue router导航守卫(router.beforeEach())的使用详解

    导航守卫 导航守卫主要用来通过跳转或取消的方式守卫导航.有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的.(记住参数或查询的改变并不会触发进入/离开的导航守卫.你可以通过观察$route对象来应对这些变化,或使用beforeRouteUpdate的组件内守卫.) 好久没写一些东西了,总是感觉有啥缺少的.~~~~恰好碰到最近在写一个移动端项目,遇到了如何使同一个链接在不同条件下跳转到不同路由组件问题,譬如大家经常看到手机中没登录跳转登录页,登陆后跳转个人信息页等.废话不多说了

  • Vue2+element-ui实现面包屑导航

    本文实例为大家分享了Vue2+element-ui实现面包屑导航的具体代码,供大家参考,具体内容如下 1.面包屑导航栏布局 代码: <template>     <!--面包屑导航页签-->     <div style="padding: 25px 0;flex: 1">         <el-breadcrumb separator-class="el-icon-arrow-right">            

  • vue element-ui实现动态面包屑导航

    vue element-ui动态面包屑导航,供大家参考,具体内容如下 直接上代码 一.template代码 // 这是单独的组件 <template> <el-breadcrumb separator-class="el-icon-arrow-right"> // 首页我是写死的,其他的遍历出来 <el-breadcrumb-item :to="{ name: 'home' }">首页</el-breadcrumb-item

  • vue中的面包屑导航组件实例代码

    vue的面包屑导航组件 用来将其放到navbar中: Breadcrumb/index.vue <template> <el-breadcrumb class="app-breadcrumb" separator="/"> <transition-group> <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.pat

随机推荐