目录
1.2 .既然和jQuery差不多, 为什么还需要Zepto?
一、Zepto初体验
1.1 什么是Zepto?
Zepto 是一个轻量级的针对现代高级浏览器的 JavaScript库,
它与jQuery有着类似的api, 如果你会用jQuery,那么你也会用Zepto
1.2 .既然和jQuery差不多, 为什么还需要Zepto?
jQuery更多是在PC端被应用,Zepto更多是在移动端被应用
也正是因为jQuery用在PC端, 所以jQuery考虑了很多低级浏览器的的兼容性问题, ,所以代码更多体积更大
也正是因为Zepto用在移动端, 所以Zepto则是直接抛弃了低级浏览器的适配问题 , 所以代码更少体积更小
综上所述: Zepto其实就是专门用于移动端的轻量级的jQuery
1.3 官方网址
英文版:http://zeptojs.com/
中文版:http://www.css88.com/doc/zeptojs_api/
1.4 Zepto的特点
Zepto采用了模块化的开发, 将不同的功能放到了不同的模块中,
在使用的过程中我们可以按需导入, 也就是需要什么功能就导入什么模块
Zepto 模块:
module | default | description |
---|---|---|
zepto | ✔ | 核心模块;包含许多方法 |
event | ✔ | 通过on() & off() 处理事件 |
ajax | ✔ | XMLHttpRequest 和 JSONP 实用功能 |
form | ✔ | 序列化 & 提交web表单 |
ie | ✔ | 增加支持桌面的Internet Explorer 10+和Windows Phone 8。 |
detect | 提供 $.os 和 $.browser 消息 | |
fx | The animate() 方法 | |
fx_methods | 以动画形式的 show , hide , toggle , 和 fade*() 方法. | |
assets | 实验性支持从DOM中移除image元素后清理iOS的内存。 | |
data | 一个全面的 data() 方法, 能够在内存中存储任意对象。 | |
deferred | 提供 $.Deferred promises API. 依赖"callbacks" 模块.当包含这个模块时候, $.ajax() 支持promise接口链式的回调。 | |
callbacks | 为"deferred"模块提供 $.Callbacks 。 | |
selector | 实验性的支持 jQuery CSS 表达式 实用功能,比如 $('div:first') 和 el.is(':visible') 。 | |
touch | 在触摸设备上触发tap– 和 swipe– 相关事件。这适用于所有的`touch`(iOS, Android)和`pointer`事件(Windows Phone)。 | |
gesture | 在触摸设备上触发 pinch 手势事件。 | |
stack | 提供 andSelf & end() 链式调用方法 | |
ios3 | String.prototype.trim 和 Array.prototype.reduce 方法 (如果他们不存在) ,以兼容 iOS 3.x. |
1.5 Zepto注意点
如果是从官方网站下载的, 那么已经包含了默认的一些模块
如果是从github下载的, 那么需要我们自己手动导入每一个模块
当然后续学习了NodeJS后, 我们也可以自己定制
1.6 示例
*{
margin: 0;
padding: 0;
}
div{
width: 200px;
height: 200px;
background: skyblue;
}
<script src="js/zepto.js"></script>
<script src="js/event.js"></script>
<button>我是按钮</button>
<div></div>
$("button").click(function () {
$("div").css({backgroundColor: "red"});
});
二、Zepto选择器
Zepto是模块化开发的, zepto.js核心模块中只包含了基础功能,如果想使用高级的选择器必须引入高级选择器模块
2.1 示例
*{
margin: 0;
padding: 0;
}
div{
width: 200px;
height: 200px;
background: red;
margin-bottom: 20px;
}
.one{
background: green;
}
#two{
background: blue;
}
<script src="js/zepto.js"></script>
<script src="js/event.js"></script>
<script src="js/selector.js"></script>
<button>我是按钮</button>
<div></div>
<div class="one"></div>
<div id="two"></div>
$("button").click(function () {
// $("div").css({backgroundColor: "yellow"});
// $(".one").css({backgroundColor: "yellow"});
// $("#two").css({backgroundColor: "yellow"});
$("div:first").css({backgroundColor: "yellow"});
});
三、Zepto动画
Zepto是模块化开发的, zepto.js核心模块中只包含了基础功能,如果想使用动画必须引入动画模块
3.1 zepto动画注意点
- 由于zepto是一个轻量级的针对现代高级浏览器的 JavaScript库
- 不需要兼容低级浏览器, 所以zepto中的动画是通过CSS3属性来实现动画的,而jQuery中是通过DOM来实现动画的
3.2 示例
*{
margin: 0;
padding: 0;
}
div{
width: 200px;
height: 200px;
background: red;
/*display: none;*/
}
<script src="js/zepto.js"></script>
<script src="js/event.js"></script>
<script src="js/fx.js"></script>
<script src="js/fx_methods.js"></script>
<button>我是按钮</button>
<div></div>
$("button").click(function () {
// $("div").animate({marginLeft: 500}, 2000);
// $("div").hide(2000);
// $("div").show(2000);
$("div").toggle(2000);
});
四、Zepto-tap事件
无论PC端还是移动端都支持click事件,而且不仅仅是jQuery和Zepto支持, 原生的JS也支持
4.1 移动端click事件注意点
- 在企业开发中如果需要在移动端监听点击事件, 一般不会使用click来监听
- 因为移动端的事件很多(单击/双击/轻扫/捏合/拖拽等等)
- 所以如果通过click来监听,系统需要花费100~300毫秒判断到底是什么事件
- 而移动端对事件的响应速度要求很高, 事件响应越快用户体验就越好
- 所以如果需要在移动端监听点击事件, 那么请使用tap事件
4.2 tap事件
tap事件是Zepto自己封装的一个事件, 解决了原生click事件100~300毫秒的延迟问题
4.3 示例
*{
margin: 0;
padding: 0;
}
div{
width: 200px;
height: 200px;
margin: 0 auto;
background: red;
}
<script src="js/zepto.js"></script>
<script src="js/event.js"></script>
<script src="js/touch.js"></script>
<div></div>
$("div").tap(function () {
console.log("被点击了");
});
五、移动端Touch事件
5.1 Zepto是如何实现tap事件的?
虽然tap事件是Zepto自己封装的事件, 但是无论如何封装肯定都是通过原生JS来实现的
在原生的JS中专门为移动端新增了几个事件:
- touchstart: 手指按下
- touchmove: 手指在元素上移动
- touchend : 手指抬起
*{
margin: 0;
padding: 0;
}
div{
width: 200px;
height: 200px;
background: red;
}
<div></div>
let oDiv = document.querySelector("div");
oDiv.ontouchstart = function () {
console.log("手指按下");
}
oDiv.ontouchend = function () {
console.log("手指抬起");
}
oDiv.ontouchmove = function () {
console.log("手指移动");
}
5.2 移动端Touch事件对象
移动端的touch事件也是一个事件, 所以被触发的时候系统也会自动传递一个事件对象给我们
公共部分:
*{
margin: 0;
padding: 0;
}
div{
width: 150px;
height: 150px;
display: inline-block;
background: red;
}
.box2{
background: blue;
}
<div class="box1"></div>
<div class="box2"></div>
a.移动端touch事件对象中比较重要的三个子对象:
touches: 当前屏幕上所有手指的列表
targetTouches: 保存了元素上所有的手指里列表
changedTouches: 当前屏幕上刚刚接触的手指或者离开的手指
let oDiv1 = document.querySelector(".box1");
oDiv1.ontouchstart = function (event) {
console.log("touches1", event.touches);
console.log("targetTouches1", event.targetTouches);
}
let oDiv2 = document.querySelector(".box2");
oDiv2.ontouchstart = function (event) {
console.log("touches2", event.touches);
console.log("targetTouches2", event.targetTouches);
}
touches和targetTouches:
- 如果都是将手指按到了同一个元素上, 那么这两个对象中保存的内容是一样的
- 如果是将手指按到了不同的元素上, 那么这个两个对象中保存的内容不一样
- touches保存的是所有元素中的手指, 而targetTouches保存的是当前元素中的手指
changedTouches:
- 在ontouchstart中保存的是刚刚新增的手指
- 在ontouchend中保存的是刚刚离开的手指
/*
let oDiv1 = document.querySelector(".box1");
oDiv1.ontouchstart = function (event) {
// console.log("touches1", event.touches);
console.log("targetTouches1", event.targetTouches);
}
oDiv1.ontouchend = function (event) {
// console.log("touches1", event.touches);
console.log("targetTouches1", event.targetTouches);
}
*/
let oDiv1 = document.querySelector(".box1");
oDiv1.ontouchstart = function (event) {
console.log("按下", event.changedTouches);
}
oDiv1.ontouchend = function (event) {
console.log("抬起", event.changedTouches);
}
5.3 移动端手指位置
screenX/screenY是相对于屏幕左上角的偏移位
clientX/clientY是相对于可视区域左上角的偏移位
pageX/pageY是相对于内容左上角的偏移位
*{
margin: 0;
padding: 0;
}
div{
width: 1000px;
height: 100px;
margin-left: 50px;
margin-top: 50px;
background: linear-gradient(to right, red, green);
}
<div></div>
let oDiv = document.querySelector("div");
oDiv.ontouchstart = function (event) {
// console.log(event.targetTouches[0]);
// console.log(event.targetTouches[0].screenX);
// console.log(event.targetTouches[0].screenY);
console.log(event.targetTouches[0].clientX); // 11
console.log(event.targetTouches[0].clientY); // 63
console.log(event.targetTouches[0].pageX); // 686
console.log(event.targetTouches[0].pageY); // 63
}
案例:
*{
margin: 0;
padding: 0;
}
div{
width: 100px;
height: 100px;
background: red;
}
<div></div>
/*需求: 通过手指拖拽div*/
let oDiv = document.querySelector("div");
let startX = 0;
let startY = 0;
let flag = false;
oDiv.ontouchstart = function (event) {
if(flag){return}
flag = true;
startX = event.targetTouches[0].clientX;
startY = event.targetTouches[0].clientY;
}
oDiv.ontouchmove = function (event) {
let moveX = event.targetTouches[0].clientX;
let moveY = event.targetTouches[0].clientY;
let offsetX = moveX - startX;
let offsetY = moveY - startY;
oDiv.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
}
5.4 移动端点透问题
1.移动端点透问题
当一个元素放覆盖了另一个元素, 覆盖的元素监听touch事件,而下面的元素监听click事件,并且touch事件触发后覆盖的元素就消失了, 那么就会出现点透问题
2.移动端点透问题出现的原因
当手指触摸到屏幕的时候,系统生成两个事件,一个是touch 一个是click
touch事件先执行,执行完后从文档上消失
click事件有100~300ms延迟, 所以后执行.
但click事件执行的时候触发的元素已经消失了, 对应的位置现在是下面的元素, 所以就触发了下面元素的click事件
3.移动端点透问题解决的几种方案
- 在touch事件中添加event.preverDefault(); 阻止事件扩散
- 使用Zepto, 但是需要注意老版本的Zepto也会出现点透问题
- 使用Fastclick, 最早解决点透问题的插件
*{
margin: 0;
padding: 0;
}
div{
text-align: center;
font-size: 40px;
}
.click{
width: 300px;
height: 300px;
background: red;
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 100px;
}
.tap{
width: 200px;
height: 200px;
background: blue;
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 150px;
}
<div class="click">click</div>
<div class="tap">tap</div>
let oClick = document.querySelector(".click");
let oTap = document.querySelector(".tap");
在touch事件中添加event.preverDefault(); 阻止事件扩散,
oTap.ontouchstart = function (event) {
this.style.display = "none";
event.preventDefault(); // 阻止事件扩散
}
oClick.onclick = function () {
console.log("click");
}
使用Zepto, 但是需要注意老版本的Zepto也会出现点透问题,
<script src="js/zepto.js"></script>
<script src="js/touch.js"></script>
$(oTap).tap(function () {
oTap.style.display = "none";
});
oClick.onclick = function () {
console.log("click");
}
使用Fastclick, 最早解决点透问题的插件,
注意点: 这里的click事件并不是原生的click事件, 是使用的fastclick中的click,这里的click事件已经解决了100~300ms延迟的问题
<script src="js/fastclick.js"></script>
//使用原生的方法
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
let oClick = document.querySelector(".click");
let oTap = document.querySelector(".tap");
oTap.addEventListener("click", function () {
oTap.style.display = "none";
});
oClick.onclick = function () {
console.log("click");
}
5.5 Zepto-swipe事件
什么是轻扫事件?
手指快速的往左边滑动/或者右边滑动/或者上边滑动/或者下边滑动
*{
margin: 0;
padding: 0;
}
div{
width: 100px;
height: 100px;
background: red;
margin-left: 100px;
margin-top: 100px;
}
<script src="js/zepto.js"></script>
<script src="js/event.js"></script>
<script src="js/touch.js"></script>
<script src="js/fx.js"></script>
<div></div>
$("div").swipeLeft(function () {
// console.log("向左边轻扫");
$(this).animate({marginLeft: "0"}, 2000);
});
$("div").swipeRight(function () {
// console.log("向右边轻扫");
$(this).animate({marginLeft: "100px"}, 2000);
});
$("div").swipeUp(function () {
// console.log("向上边轻扫");
$(this).animate({marginTop: "0"}, 2000);
});
$("div").swipeDown(function () {
// console.log("向下边轻扫");
$(this).animate({marginTop: "100px"}, 2000);
});
示例:
*{
margin: 0;
padding: 0;
touch-action: none;
}
.box{
overflow: hidden;
}
.box>.box-top{
height: 50px;
position: relative;
}
.box>.box-top>ul{
list-style: none;
width: 100%;
display: flex;
}
.box>.box-top>ul>li{
height: 50px;
line-height: 50px;
text-align: center;
flex-grow: 1;
background: #6c6c6c;
}
.box>.box-top>ul>.active{
color: #f40;
background: #ccc;
}
.box>.box-top>.line{
width: 50%;
height: 2px;
background: #f40;
position: absolute;
left: 0;
bottom: 0;
}
.box>.box-bottom{
width: 200%;
display: flex;
position: relative;
top: 0;
left: 0;
}
.box>.box-bottom>ul{
list-style: none;
flex-grow: 1;
}
.box>.box-bottom>ul>li{
line-height: 30px;
border-bottom: 1px solid #ccc;
}
<script src="js/zepto.js"></script>
<script src="js/event.js"></script>
<script src="js/touch.js"></script>
<script src="js/fx.js"></script>
<script src="js/selector.js"></script>
<div class="box">
<div class="box-top">
<ul>
<li class="active">新闻</li>
<li>科技</li>
</ul>
<p class="line"></p>
</div>
<div class="box-bottom">
<ul class="list1">
<li>我是新闻1</li>
<li>我是新闻2</li>
<li>我是新闻3</li>
<li>我是新闻4</li>
<li>我是新闻5</li>
<li>我是新闻6</li>
<li>我是新闻7</li>
<li>我是新闻8</li>
<li>我是新闻9</li>
<li>我是新闻10</li>
</ul>
<ul class="list2">
<li>我是军事1</li>
<li>我是军事2</li>
<li>我是军事3</li>
<li>我是军事4</li>
<li>我是军事5</li>
<li>我是军事6</li>
<li>我是军事7</li>
<li>我是军事8</li>
<li>我是军事9</li>
<li>我是军事10</li>
</ul>
</div>
</div>
//将切换的代码全部封装在自定义事件里
$(".box-top li").on("lwg:click",function () { // on 自定义事件
$(this).addClass("active").siblings().removeClass("active");
let currentIndex = $(this).index();
$(".line").animate({left: currentIndex * $(this).width() + "px"}, 500);
$(".box-bottom").animate({left: -currentIndex * $(".list1").width() + "px"}, 500);
});
// 点击切换事件
$(".box-top li").click(function () {
$(this).trigger("lwg:click");
});
// 清扫事件--左滑
$(".box").swipeLeft(function () {
$(".box-top li:last").trigger("lwg:click");
});
// 清扫事件--右滑
$(".box").swipeRight(function () {
$(".box-top li:first").trigger("lwg:click");
});
5.6Zepto实现移动端轮播图
大致思路如下:
- 定义变量保存对当前的索引
- 定义变量保存图片宽度
- 定义变量保存最大的索引
- 监听按钮点击
- 实现自动轮播
- 实现轻扫切换
具体请看代码里的详细注释
*{
margin: 0;
padding: 0;
touch-action: none;
}
div{
width: 100%;
position: relative;
overflow: hidden;
}
ul{
list-style: none;
width: 500%;
display: flex;
justify-content: flex-start;
position: relative;
left: 0;
top: 0;
}
ul>li{
flex: 1;
}
ul>li>img{
width: 100%;
vertical-align: bottom;
}
div>p{
width: 100%;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: space-between;
/*background: deepskyblue;*/
/*
告诉浏览器当前元素不需要接收事件
注意点: 如果父元素不接收事件, 那么默认子元素也不能接收事件
如果子元素需要接收事件, 那么必须单独设置为auto
*/
pointer-events: none;
}
div>p>span{
display: inline-block;
width: 30px;
height: 50px;
line-height: 50px;
text-align: center;
font-weight: bold;
font-size: 30px;
color: #fff;
background: rgba(0,0,0,0.3);
pointer-events: auto;
}
ol{
list-style: none;
position: absolute;
left: 50%;
bottom: 20px;
transform: translateX(-50%);
display: flex;
justify-content: flex-start;
}
ol>li{
width: 20px;
height: 20px;
background: #fff;
border-radius: 50%;
margin: 0 5px;
}
ol>.active{
background: #f40;
}
<script src="js/zepto.js"></script>
<script src="js/selector.js"></script>
<script src="js/event.js"></script>
<script src="js/touch.js"></script>
<script src="js/fx.js"></script>
<div>
<ul>
<li><img src="images/img1.jpg" alt=""></li>
<li><img src="images/img2.jpg" alt=""></li>
<li><img src="images/img3.jpg" alt=""></li>
<li><img src="images/img4.jpg" alt=""></li>
<li><img src="images/img1.jpg" alt=""></li>
</ul>
<p>
<span class="left-btn"><</span>
<span class="right-btn">></span>
</p>
<ol>
<li class="active"></li>
<li></li>
<li></li>
<li></li>
</ol>
</div>
//封装自定义方法
;(function($){
$.extend($.fn, {
//判断是否在做动画
isAnimation: function(){
let time = $("ul").css("transition-duration");
time = parseFloat(time);
return time !== 0;
}
})
})(Zepto)
// 1.定义变量保存对当前的索引
let currentIndex = 0;
// 2.定义变量保存图片宽度
let itemWidth = $("ul>li").width();
// 3.定义变量保存最大的索引
let maxIndex = $("ul>li").length - 1;
// 4.监听按钮点击
// 4.1 点击左按钮
$(".left-btn").click(function () {
//点击的时候关闭自动轮播,点击并切换完后再重新开启自动轮播
clearInterval(timerId);
//判断当前是否有动画在执行
if($(this).isAnimation()){return}
currentIndex--;
//判断当前是否是第一张
if(currentIndex < 0){
$("ul").css({left: -maxIndex * itemWidth});
currentIndex = maxIndex - 1;
}
// 添加动画
$("ul").animate({left: -currentIndex * itemWidth}, 500, function () {// 动画完成之后重新开启自动轮播
autoPlay();
});
// 点击指示点,图片调到对应区域
$("ol>li").eq(currentIndex).addClass("active").siblings().removeClass();
});
// 4.2 点击右按钮
$(".right-btn").click(function () {
//点击的时候关闭自动轮播,点击并切换完后再重新开启自动轮播
clearInterval(timerId);
//判断当前是否有动画在执行
if($(this).isAnimation()){return}
currentIndex++;
//判断当前是否是最后张
if(currentIndex > maxIndex){
$("ul").css({left: 0});
currentIndex = 1;
}
// 添加动画
$("ul").animate({left: -currentIndex * itemWidth}, 500, function () {// 动画完成之后重新开启自动轮播
autoPlay();
});
//
let index = currentIndex === 4 ? 0 : currentIndex;
// 点击指示点,图片调到对应区域
$("ol>li").eq(index).addClass("active").siblings().removeClass();
});
/*
注意点:
在移动端中是没有移入和移出事件的
* */
/*
let oUl = document.querySelector("ul");
oUl.onmouseenter = function () {
console.log("移入");
}
oUl.onmouseleave = function () {
console.log("移出");
}
*/
// 5.实现自动轮播
let timerId = null;
function autoPlay() {
timerId = setInterval(function () {
$(".right-btn").click();
}, 2000);
}
autoPlay();
//手指按下时轮播停止
$("ul").get(0).ontouchstart = function () {
clearInterval(timerId);
};
//手指抬起时轮播继续
$("ul").get(0).ontouchend = function () {
autoPlay();
};
// 6.实现轻扫切换
$("ul").swipeLeft(function () {
$(".right-btn").click();
});
$("ul").swipeRight(function () {
$(".left-btn").click();
});