1.效果介绍
博主首先介绍一下要制作的东西以及要实现的效果.大家打开小米官网,可以看到如img1.png中的这样一个下拉框,当我们鼠标在对象的列表中移动的时候,会出现对应的产品数据,如img2.png 鼠标移入"小米手机"列表中,会出现一个从上至下的滑动效果并出现产品信息.
小米首页下拉框:
鼠标移入"小米手机"列表中:
2.步骤简介
1.在布局上,"小米手机","红米"等等的列表只要写入一个ul就行了,ul(headwrap)中只有一个隐藏的div(class为div_hid),其他所有的信息,我们利用Ajax读取创建进去就行了
2.利用$.get("data.json",function(result){})
从data.json数据中读取到对应的数据(即回调函数中的result),然后再对这些数据进行操作.
3.HTML布局
<ul class = "headwrap">
<div class = "div_hid"></div>
</ul>
3.data.json简介
这里我的data.json数据仅仅只是小米官网下拉框的这一部分,如img3.png所示,json内是一个数组,数组中有10项,每一项都是一个对象,对应着一个列表.
而数组中的每一个对象下又有tittle
和data
俩个属性,其中data属性是一个数组,数组中的每一项对应一个产品信息.如img4.png
4.JS代码
第一步:
可以通过JQuery内置的Ajax调用get方法读取到data.json数据并遍历读取到的数据,所有的操作全部都是在get方法中的函数内执行的,然后创建li标签并向li标签中添加对应的数据内容:
/**
*通过JQuery内置的Ajax的get方法从json中读取数据并初始化下拉框的菜单栏
*/
$.get('data.json', function (result) {
for (let res of result) {
//创建标题li
let $li_top = $(`<li class="li_top"><a class="li_top_a">${res.title}</a></li>`);
//将创建好的每一个li添加到ul中
$li_top.appendTo($('.headwrap'));
见第二步
}
第二步:
先获取到上面创建好的所有li标签,对它们进行遍历,给每个li都添加mouseenter事件,鼠标移入对应的li列表中,创建对应的数据并添加在页面中
$('.li_top').each(function (index, element) {
//利用index()方法获取到当前指向的这个列表li在所有li列表集合中的索引值.
var index1 = $(this).index();
//给每个li列表添加mouseenter事件
$(this).on('mouseenter', function () {
//在给隐藏div添加数据之前,先清空它
$('.div_hid').html('');
//创建一个ul标签,用来盛放所有的产品信息
var $ul_hid = $(`<ul class="a1_con"></ul>`);
//遍历data.json数据中的对应li列表下标的对象的data数组
//res表示的就是数组中的每一项,也就是每一个产品的信息
for (var res of result[index1].data) {
//创建li标签用于添加每一个产品的信息
var li_hid = $(`<li class="a1_con_li">
<div class="a1_con_con">
<a href="#">
<img src=${res.img}>
</a>
</div>
<div class="a1_con_foot">
<a href="">${res.title}</a>
<p>${res.price}</p>
</div></li>`);
//因为产品中有的有"新品","享免息"等标签,有的没有,所以这里要做一个判断
if(res.flag!=""){
$(`<div class="a1_con_top">${res.flag}</div>`).appendTo(li_hid);
}
//将创建好的隐藏的li标签(也就是每个产品信息)添加到隐藏ul中
li_hid.appendTo($ul_hid);
}
//将隐藏的ul添加到隐藏的div中
$ul_hid.appendTo($('.a1'));
});
});
}); //$.get()
第三步:
下拉框的效果实际是分为俩块:
第一块:鼠标移入包裹li列表的ul(class为headwarp)中,隐藏div(div_hid)从上至下滑动出来,鼠标移出包裹li列表的ul,隐藏div从下至上滑动上去.
第二块:鼠标在ul(class为headwarp)内部之间的li列表移动,不会有滑动效果,只有数据的变换.
所以我们可以对ul(class为headwarp)进行事件监听,并让它冒泡到最底层放字的a标签中.(这里有一点要注意的是,最后俩个li列表也就是"服务"和"社区"是没有内容的,所以鼠标移到它们上面应该是不执行隐藏div滑动的效果的).具体代码如下:
$('.headwrap').on({
'mouseover':function(event) {
//判断若冒泡的目标是a标签,则执行之后的代码
if(event.target.nodeName.toLowerCase() == 'a'){
//判断若a标签中的内容是"服务"或者"社区"则让隐藏div回去
if($(event.target).html()=="服务"||$(event.target).html()=="社区"){
$('.div_hid').slideUp(300);
return;
}
//调用slideDown()让隐藏div在300毫秒内滑动下来
$('.div_hid').slideDown(300);
}
},
'mouseleave':function () {
//当鼠标离开时,调用slideDown()让隐藏div在300毫秒内滑动上去
$('.div_hid').slideUp(300);
}
});
面向对象版本
上面博主介绍的是面向过程的版本,这里再来一个面向对象的版本.
面向对象呢,我用的是class类的做法:
1.声明类
先声明一个类TopNav
用来充当构造函数
这个类中有:
1.类的构造函数:constructor();
2.初始化函数:_init();
3.加载创建列表li:loadTopLi();
4.改变隐藏div内的内容:changeHidDiv();
5.加载创建隐藏ul:loadHidUl();
6.加载创建隐藏li:loadHidLi();
2.设计每个函数
面向对象的思想就是将每一个功能都用一个函数来写,各个功能直接互不影响,若是有需要添加的功能直接再添加函数就行了.
class TopNav{
constructor(container){
this.container = container;
this.container.on({
'mouseover':function(event) {
if(event.target.nodeName.toLowerCase() == 'a'){
if($(event.target).html()=="服务"||$(event.target).html()=="社区"){
$('.a1').slideUp(300);
return;
}
$('.a1').slideDown(300);
}
},
'mouseleave':function () {
$('.a1').slideUp(300);
}
});
}
/**
* 初始化函数
* @private
*/
_init(){
$.get('list.json',(result)=>{
this.result = result;
this.loadTopLi();
})
}
/**
* 加载创建上面的列表li
*/
loadTopLi(){
for(let i=0;i<this.result.length;i++){
let $li_top = $(`<li class="li_top"><a class="li_top_a">${this.result[i].title}</a></li>`)
$li_top.on('mouseenter',()=>{
this.changeHidDiv(this.result[i].data);
});
$li_top.appendTo(this.container);
}
}
/**
* 改变隐藏div内的内容
*/
changeHidDiv(res){
let $a1 = $('.a1');
$a1.html('');
this.loadHidUl($a1,res)
}
/**
* 加载创建隐藏ul
*/
loadHidUl(container,res){
let $ul_hid = $(`<ul class="a1_con"></ul>`);
for(let i=0;i<res.length;i++){
this.loadHidLi($ul_hid,res[i])
}
$ul_hid.appendTo(container);
}
/**
* 加载创建隐藏li
*/
loadHidLi(container,res){
let li_hid = $(`<li class="a1_con_li">
<div class="a1_con_con">
<a href="#">
<img src=${res.img}>
</a>
</div>
<div class="a1_con_foot">
<a href="">${res.title}</a>
<p>${res.price}</p>
</div></li>`);
if(res.flag!=""){
$(`<div class="a1_con_top">${res.flag}</div>`).appendTo(li_hid);
}
li_hid.appendTo(container);
}
}
3.声明一个对象并调用类中的初始化函数(_init)
let topNav = new TopNav($('.headwrap_2_2'));
topNav._init();
后文:
小米首页的下拉框主要是有几点要注意的:
1.鼠标移和移出ul(class为headwarp)时,隐藏div(class为div_hid)有滑动效果出来或者消失,但是鼠标在ul内部移动的时候没有滑动效果.这里可以交给事件代理去做.
2.隐藏div内的内容主要是靠Ajax从data.json文件中读取到数据并创建各种标签,然后添加到其中.
3.在每次创建新的数据标签并添加到隐藏div之前,先要将隐藏div清空,而清空常用的一种方式是$('.div_hid').html("")
.