听歌敲代码。没想到吧,这个是jojo哒。
今天想到有些网页上会有那种滑动块导航栏,我还从来没做过这个,就从网上找了一个看看。
它的效果是这样的。但是我后来发现了个很严重的问题。
如果我不点击上面的li标签,直接把我的浏览器窗口缩放的话,他的left值是不会改变的,也就是说这个滑动块的位置在看起来会飘到别的地方。
这样的效果如果是手机的话还能接受,毕竟手机的话应该是不会缩放浏览器的,但是这东西放到pc网站上会被人笑死。
怎么办,快用你无敌的空条承太郎想想办法啊,白金之星!
我看了一下他里面的代码(这个是在html上写的,所以是用挂载的方式。)
<div id="app">
<div id="menu">
<ul>
<li v-for="(item,index) in menulist" @click="movebg(item,index)">
{{item.title}}
</li>
<div class="menubg"></div>
</ul>
</div>
</div>
<style>
html,
body,
ul,
li {
padding: 0;
margin: 0;
list-style: none
}
#menu {
width: 80%;
background: #024067;
box-shadow: 0 2px 3px rgba(0, 0, 0, .2);
padding: 0 10%;
}
#menu ul {
display: flex;
position: relative
}
#menu ul li {
flex: 1;
line-height: 40px;
color: #fff;
font-size: 14px;
cursor: pointer;
text-align: center;
position: relative;
z-index: 2
}
.menubg {
position: absolute;
background: #8f0000;
height: 40px;
top: 0;
z-index: 1;
transition: all .4s;
left: 0
}
</style>
var app = new Vue({
el: '#app',
data: {
menulist: [{title: 'UI',value: 1
}, {title: '输入', value: 2}, {title: '媒体',value: 3
}, {title: '导航',value: 4}, {title: '其他',value: 5
}, {title: '网页模板',value: 6}, { title: '常用代码',value: 7 }]
},
mounted() {
let menuwidth = document.querySelector("#menu ul").offsetWidth//获取menu宽度
let liwidth = document.querySelectorAll("#menu li")//获取li
let bgWidth = document.querySelector(".menubg")//背景
bgWidth.style.width = liwidth[0].offsetWidth + 'px' //设置menubg的宽度
},
methods: {
movebg(item, index) {
let bgWidth = document.querySelector(".menubg")
let selfLeft = document.querySelectorAll("#menu li")[index].offsetLeft
bgWidth.style.left = selfLeft + 'px' //设置menubg的left
this.id = item.value
}
}
})
看好了,他是选择('#menu li') 后面还用了index,这个index是从哪里来的?
是他点击事件里传过来的。如果不点它,那么就没有index这个东西,console.log打印就会为undefined。
而且他设置滑动块 宽度的代码是写死的,无论我们怎么点,他的滑动块宽度始终都是一样的,除非刷新页面。
所以我们还得动态改变他的宽度。
⑧说了,上代码。
首先我们得使用vuex来管理index的问题。(这里如果没有学过vuex的可以先看下去再去学vuex。)
先在
mutation-types.js文件下写上代理的方法名:
export const SETMENULIINDEX = "SETMENULIINDEX"
然后在mutation文件下引入,最后写上我们要使用的方法。
import {SETMENULIINDEX} from './mutation-types'
[SETMENULIINDEX]:(state,number)=>{//存入滑动块导航栏的index的方法。
state.menuLiIndex = number
},
这样我们的vuex就写好了,然后就在vue文件里用它。
在vue文件的script标签下引入vuex中的mapMutation
import {mapMutations} from 'vuex'
最后就是我们的逻辑代码了
mounted() {
this.movebg()
const _that = this;
window.onresize = function(){//这里我们使用window.onresize监听浏览器窗口宽度。
_that.movebg()
};
},
methods: {
...mapMutations([]), //在这里引入映射方法,别忘了‘,’号
movebg(item, index) {
if(index==null||index == undefined){//判断index是否为空
index = 0;
item = this.menulist[0];
}else{
this.$store.commit('SETMENULIINDEX',index)
//如果index不为空,把它存入vuex
}
var bgWidth = document.querySelector('.menubg')
var aLi = document.querySelectorAll('#menu li ')
var liWidth = aLi[index].offsetWidth //获取点击的li标签的宽
bgWidth.style.width = liWidth + 'px';
bgWidth.style.left = liWidth * this.$store.state.menuLiIndex + 'px'
//这里我们让他乘以的是存放在vuex里面的index,这样就不会跟个二愣子一样傻站在原地了。
}
}
然后我们可以用computed来返回一下这个menuLiIndex的数值
computed: {
menuLiIndex() {
return this.$store.state.menuLiIndex
}
},
这样写就能用模板看到了。{{menuLiIndex}}
让我们看一下效果图
我们可以从右侧的数据看到,他的width和left的值已经可以根据可视窗口的改变而动态改变了。
而且我们不点击他,他也会自己根据窗口宽度改变。
就此我们的目的已经达到了。
当然这个方法还是有点问题的。
首先是他的index的问题其实是没有解决的,我虽然在上面设置了一个判断语句,
但是他的index如果没有点击的话,其实还是为undefined,我们用的是之前点击所存入在vuex中的index。
其次,window.onresize这个方法在vue中,如果定义了很多个,那么也只会有一个生效。
而且会让网页很卡很卡,现在我的浏览器的cpu就飙升到35%了
所以这是个需要优化的地方。
目前已经找到了优化方案,不过还没整理,如果有想挑战一下的可以试试。
优化方案网站:https://www.jb51.net/article/135427.htm
感觉我说的应该比较详细了吧,当然有问题还是可以下方留言。我看到了就会回答你的。
(别只打字,附上图,没有医生能够只看病人脸色就知道是啥病的。)
Welcome to Starfish bar,If you have better suggestions or better ideas,
Thank you forleave a message below, see you again.