APIs案例及知识点串讲(中)
案例一:tab栏切换
css代码
<style>* {margin: 0;padding: 0;}.tab {width: 590px;height: 340px;margin: 20px;border: 1px solid #e4e4e4;}.tab-nav {width: 100%;height: 60px;line-height: 60px;display: flex;justify-content: space-between;}.tab-nav h3 {font-size: 24px;font-weight: normal;margin-left: 20px;}.tab-nav ul {list-style: none;display: flex;justify-content: flex-end;}.tab-nav ul li {margin: 0 20px;font-size: 14px;}.tab-nav ul li a {text-decoration: none;border-bottom: 2px solid transparent;color: #333;}.tab-nav ul li a.active {border-color: #e1251b;color: #e1251b;}.tab-content {padding: 0 16px;}.tab-content .item {display: none;}.tab-content .item.active {display: block;}</style>
初级版
<body><div class="tab"><div class="tab-nav"><h3>每日特价</h3><ul><li><a class="active" href="javascript:;">精选</a></li><li><a href="javascript:;">美食</a></li><li><a href="javascript:;">百货</a></li><li><a href="javascript:;">个护</a></li><li><a href="javascript:;">预告</a></li></ul></div><div class="tab-content"><div class="item active"><img src="./images/tab00.png" alt="" /></div><div class="item"><img src="./images/tab01.png" alt="" /></div><div class="item"><img src="./images/tab02.png" alt="" /></div><div class="item"><img src="./images/tab03.png" alt="" /></div><div class="item"><img src="./images/tab04.png" alt="" /></div></div></div><script>const as = document.querySelectorAll('.tab-nav a')//注意这里是把所有a都选取过来for (let i = 0; i < as.length; i++) {as[i].addEventListener('mouseenter', function () {document.querySelector('.tab-nav .active').classList.remove('active')this.classList.add('active')//使用this即可//下面五个大盒子一一对应document.querySelector('.tab-content .active').classList.remove('active')//注意这里是i+1document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')})}</script>
</body>
案例叮嘱:
1.css选择器选择匹配的多个元素
参数: 包含一个或多个有效的CSS选择器 字符串
返回值:CSS选择器匹配的NodeList 对象集合
得到的是一个伪数组:有长度有索引号的数组,但是没有pop() push()等数组方法
2.在代码中恰当正确的使用环境对象可以简化代码
环境对象:指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
【谁调用,this就是谁】
3.对大盒子的处理方式与轮播图中对下方小圆点的处理方式大致一致
4.注意书写时E:nth-child(n)里面应该是i+1
优化版
改为事件委托写法
<body><div class="tab"><div class="tab-nav"><h3>每日特价</h3><ul><li><a class="active" href="javascript:;" data-id="0">精选</a></li><li><a href="javascript:;" data-id="1">美食</a></li><li><a href="javascript:;" data-id="2">百货</a></li><li><a href="javascript:;" data-id="3">个护</a></li><li><a href="javascript:;" data-id="4">预告</a></li></ul></div><div class="tab-content"><div class="item active"><img src="./images/tab00.png" alt="" /></div><div class="item"><img src="./images/tab01.png" alt="" /></div><div class="item"><img src="./images/tab02.png" alt="" /></div><div class="item"><img src="./images/tab03.png" alt="" /></div><div class="item"><img src="./images/tab04.png" alt="" /></div></div></div><script>// 采取事件委托的形式 tab栏切换const ul = document.querySelector('.tab-nav ul')ul.addEventListener('click', function (e) {// 我们只有点击了a才会进行添加类和删除类操作 if (e.target.tagName === 'A') {document.querySelector('.tab-nav .active').classList.remove('active')//this 指向ul 不能用this e.target.classList.add('active')//大盒子模块const i = +e.target.dataset.iddocument.querySelector('.tab-content .active').classList.remove('active')document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')}})</script>
</body>
案例叮嘱:
1.事件委托一定是给父元素注册事件
事件委托是利用事件流的特征解决一些开发需求的知识技巧
优点:减少注册次数,可以提高程序性能
原理:事件委托其实是利用事件冒泡的特点。给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件
实现:事件对象.target.tagName可以获得真正触发事件的元素,此时是大写
2.注意这里的this指向ul所以我们不能用this,此时e.target才是我们点击的对象,不需要再用document.querySelector()再获取了
3.首先需要给每个小li添加自定义属性标号,注意这里的e.target.dataset.id得到的是字符串,前面一定要加+隐式转换为数字型,控制台才不会报错
自定义属性
在html5中推出来了专门的data-自定义属性
在标签上一律以data-开头
在DOM对象上一律以dataset对象方式获取
4. 注意书写时E:nth-child(n)里面应该是i+1
案例二:电梯导航
模块1:显示隐藏电梯盒子和返回顶部(放到自执行函数里面,防止变量污染)
(function () {const entry = document.querySelector('.xtx_entry')const elevator = document.querySelector('.xtx-elevator')window.addEventListener('scroll', function () {const n = document.documentElement.scrollTopelevator.style.opacity = n >= entry.offsetTop ? 1 : 0})const backTop = document.querySelector('#backTop')backTop.addEventListener('click', function () {document.documentElement.scrollTop = 0})})();
模块叮嘱:
1.注意立即执行函数的写法
立即执行函数
场景介绍: 避免全局变量之间的污染
注意: 多个立即执行函数要用 ; 隔开,要不然会报错
2.总结页面滚动小技巧
元素滚动事件
滚动条在滚动的时候持续触发的事件
很多网页需要检测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,比如返回顶部
事件名:scroll
监听整个页面滚动:给window或document添加scroll事件
//让页面滚动到对应位置
document.documentElement.scrollTop = e.target.offsetTop
(以下两个模块放到一个自执行函数里面)
模块二:点击每个模块,页面自动滚动到对应模块(使用事件委托方法)
模块三:页面滚动到大盒子位置,电梯导航小盒子对应模块自动处于选中状态
(function () {//点击页面可以滑动const list = document.querySelector('.xtx-elevator-list')list.addEventListener('click', function (e) {if (e.target.tagName === 'A' && e.target.dataset.name) {//排他思想const old = document.querySelector('.xtx-elevator-list .active')//我们需要解决初次获取不到active报错的问题//判断如果原来有active类的对象就移除类,如果开始就没有对象,就不删除,所以不报错if (old) {old.classList.remove('active')}e.target.classList.add('active')//根据小盒子的自定义属性值去选择对应的大盒子const top = document.querySelector(`.xtx_goods_${e.target.dataset.name}`).offsetTopdocument.documentElement.scrollTop = top}})//页面滚动,可以根据大盒子选小盒子添加active类window.addEventListener('scroll', function () {const old = document.querySelector('.xtx-elevator-list .active')//我们需要解决初次获取不到active报错的问题//判断如果原来有active类的对象就移除类,如果开始就没有对象,就不删除,所以不报错if (old) {old.classList.remove('active')}//判断页面当前滑动的位置选择小盒子//获取4个大盒子const news = document.querySelector('.xtx_goods_new')const popular = document.querySelector('.xtx_goods_popular')const brand = document.querySelector('.xtx_goods_brand')const topic = document.querySelector('.xtx_goods_topic')const n = document.documentElement.scrollTopif (n >= news.offsetTop && n < popular.offsetTop) {//选择第一个小盒子 document.querySelector('[data-name=new]').classList.add('active')} else if (n >= popular.offsetTop && n < brand.offsetTop) {document.querySelector('[data-name=popular]').classList.add('active')} else if (n >= brand.offsetTop && n < topic.offsetTop) {document.querySelector('[data-name=brand]').classList.add('active')} else if (n >= topic.offsetTop) {document.querySelector('[data-name=topic]').classList.add('active')}})})();
模块叮嘱:
1.我们需要解决初次获取不到active报错的问题,判断如果原来有active类的对象就移除类,如果开始就没有对象,就不删除,所以不报错。要注意到这些操作是将置顶的小li排除在外的因此if的判断条件不仅仅只有e.target.tagName === 'A'
2.在用document.querySelector获取DOM元素时,如果没有匹配到,则返回null
3.在根据页面当前滑动的位置选择小盒子时,判断依据是document.documentElement.scrollTop和各个小盒子的offsetTop值的大小关系
4.属性选择器
属性选择器可以根据元素特定属性的来选择元素。这样就可以不用借助于类或者id选择器。