移动端开发现状
- 移动web 开发指的是需要适配移动设备的网页开发
- 移动web开发与pc端web开发没有本质的区别,使用的还是HTML/CSS/JavaScript的技术
移动端与pc端 web开发的区别
1、浏览器不同
移动端的浏览器与pc端不同
谷歌浏览器 苹果浏览器、 UC浏览器 QQ浏览器 百度手机浏览器 360安全浏览器 搜狗浏览器 猎豹浏览器等
国内的手机浏览器都是根据webkit内核修改过来的,国内没有自主研发的内核,国内的操作系统也是基于Android系统修改的。
因此在移动端,css3属性只需要加webkit前缀即可。
2、屏幕尺寸
移动端设备尺寸不一样(尺寸非常多,碎片化很严重)
Android: 320*480 480*800 540*960 720*1280 1080*1920 2k屏 4k屏
iphpne: 640*960 640*1136 750*1334 1242*2208
让页面在不同手机屏幕中进行适配,宽度自适应, 基于手机全屏进行布局;
PC: 要适配所有pc端页面用版心, pc基于版心进行布局的
3、布局方式
移动端的特点
- 手机端的兼容性问题比PC端小很多,因为手机端的浏览器版本比较新(对H5的支持比较好)
- 手机端屏幕比较小,能够放的内容比较少。
问题:布局的时候怎么解决屏幕大小不一致的问题?
- PC端,固定版心(980px,1200px),让所有分辨率的电脑的版心都是一样的,比如京东
- 移动端:移动端无法设置版心,因为移动端的设备屏幕本身就小,设置版心不合适。因此移动端大多会采用流式布局(百分比布局)
流式布局,也叫百分比布局,是移动端开发中经常使用的布局方式之一。
流式布局的特征:
- 宽度自适应,高度固定,并不是百分百还原设计图
流式布局无法做到所有设备都非常逼真的还原设计图,有些设备显示效果不是特别的好看。但是流式布局是移动端非常常用的一种布局方式,比较简单,需要掌握(携程、京东)
【百分比布局】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.box {
width: 80%;
height: 200px;
border: 1px solid #000;
margin:100px auto;
}
.box div {
float: left;
width: 33.33%;
height: 200px;
background-color: #f99;
}
.box div:nth-child(2) {
background-color: deepskyblue;
}
</style>
</head>
<body>
<!-- 百分比布局 流式布局 :用于宽度自适应(在区间变换不大情况) 高度固定 一种布局方式
百分比布局不适合用于高度自适应的布局
宽高都自适应: rem单位
-->
<div class="box">
<div></div>
<div></div>
<div></div>
</div>
</body>
</html>
视口viewport(重要)
问题:一个电脑上的网站,在手机端访问,效果是什么样的?
1. 在手机端,html的大小都是980px,为什么?
这主要是历史原因导致的,因为在移动设备刚流行的时候,网站大多都是pc端的,pc端的页面宽度一般都比较大,
移动设备的宽度比较小,如果pc端页面直接在移动端显示的话,页面就会错乱。
为了解决这个问题,移动端html的大小直接就定死成了980px(因为早起的pc端网站版心就是980px居多)。
2. 视口
在pc端,html的大小默认是继承了浏览器的宽度,即浏览器多宽,html的大小就是多宽,
但是在移动端,多出来了一个视口的概念(乔布斯),视口是移动端一个虚拟的布局区域,
视口的宽度默认定死了980px,因此html的宽度默认就是980px,视口的特点是能够根据设备的宽度进行缩放。
3. 视口设置。
对于现在的移动端页面来说,视口默认为980px肯定不合适,因为设备宽度不够的话,视口会进行缩放,导致页面展示效果不好看。
视口参数设置
//width 设置视口的宽度
//width=device-width 设置视口宽度为设备的宽度(常用)。
//initial-scale 设置初始缩放比例
//initial-scale=1.0 表示不缩放
//user-scalable 设置是否允许用户缩放
//user-scalable=no 不允许用户缩放
//maximum-scale 设置允许的最大缩放比例
//maximum-scale=1.0 可以不设置,因为都禁止用户缩放了。
//minimum-scale 设置允许最小缩放比
//minimum-scale=1.0 不设置,因为都禁用用户缩放了。
//标准写法:
//快捷键: meta:vp + tab键
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
屏幕与分辨率(了解)
移动设备与PC设备最大的差异在于屏幕,这主要体现在屏幕尺寸和屏幕分辨率两个方面。
屏幕尺寸
通常我们所指的屏幕尺寸
,实际上指的是屏幕对角线的长度(一般用英寸来度量)如下图所示:
1英寸 = 2.54厘米
屏幕分辨率
分辨率则一般用像素来度量,表示屏幕水平和垂直方向的像素数,例如1920*1080指的是屏幕垂直方向和水平方向分别有1920和1080个像素点而构成,如下图所示,相同尺寸下分辨率越高,越清晰。
像素
:指计算机显示设备中的最小单位,即一个像素点的大小。
像素是相对长度单位,在屏幕分辨率越高的设备,像素点越小,屏幕分辨率越低,像素点越大。
物理像素 和 css像素
物理像素
设备像素,在同一个设备上,它的物理像素是固定的,这是厂商在出厂时就设置好了的,即一个设备的分辨率是固定的。
css像素
逻辑像素,viewport中的一个小方格,CSS样式代码中使用的是逻辑像素。如果在一个设备中,物理像素与逻辑像素相等,将不会产生任何问题。但是,在iphone 4中,物理像素是640px960px,而逻辑像素数为320px*480px。因此,需要使用大约4个物理像素来显示一个CSS像素。
像素比
物理像素与逻辑像素之间的比例。当像素比为1:1时,使用1个物理像素显示1个逻辑像素;当像素比为2:1时,使用4个物理像素显示1个逻辑像素。
获取设备的像素比
window.devicePixelRatio //物理像素与CSS像素的比值
2倍图与3倍图(重要)
以后同学在工作的过程中,从UI那拿到的设计图通常都是640的设计图或者是750的设计图.
把更多的像素点压缩至一块屏幕里,从而达到更高的分辨率并提高屏幕显示的细腻程度。
设备像素比devicePixelRatio:即像素的压缩比例
结论 :在移动端为了在高清屏手机上显示得更加细腻,通常会使用更大的图片,比如2倍图或者3倍图。
【演示:2倍图】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
width: 180px;
height: 180px;
/* background-color: pink; */
background: url(./img/180x180.jpg) no-repeat;
}
/*设计师一般会给2倍图或者三倍图,所以下面这个需要压缩*/
div:nth-child(2){
background: url(./img/360x360.jpg) no-repeat;
background-size: 180px 180px;
}
</style>
</head>
<body>
<div></div>
<div></div>
</body>
</html>
移动端调试问题
- 模拟器调试
- 真机调试:使用手机进行访问。
手机设备五花八门,屏幕尺寸都大不一样,尤其是安卓端,给我们的页面预览带来了一些麻烦。在实际工作中,作为开发者不可能有足够的设备让我们去测试(除了测试部门 ),即便有,效率也特别的低,因此开发者一般都是通过浏览器的手机模拟器来模拟不同的设备。
JDM
项目结构搭建
样式初始化
@charset "utf-8";
/* css reset 样式重置*/
body, div, ul, li, ol, h1, h2, h3, h4, h5, h6, input, textarea, select, p, dl, dt, dd, a, img, button, form, table, th, tr, td, tbody, article, aside, details, figcaption, figure, footer, header, menu, nav, section span{
margin: 0;
padding: 0;
/*所有盒子布局采用内减模式*/
-webkit-box-sizing: border-box;
/* 兼容-webkit-内核浏览器 */
box-sizing: border-box;
/*去除移动端点击高亮颜色*/
-webkit-tap-highlight-color: transparent;
}
body {
font-size: 14px;
color: #333;
font-family: 'Microsoft YaHei', Arial, sans-serif;
/*后面的都是 备胎*/
}
ol,
ul {
list-style: none;
}
a,
a:hover {
text-decoration: none;
color: #333;
}
input {
border: none;
outline: none;
/* 在 移动端浏览器 表单可能会出现 阴影 高亮 3d效果,需要清除*/
-webkit-appearance: none;
}
/*commom css 公共样式*/
.pull-left {
float: left;
}
.pull-right {
float: right;
}
/* 清除浮动 */
.clearfix::before,
.clearfix::after {
content: "";
display: block;
clear: both;
line-height: 0;
visibility: hidden;
height: 0;
}
自适应版心
.index.less
.layout{
width: 100%;
height: 1000px;
min-width: 320px;
max-width: 640px;
background-color: pink;
margin:0 auto;
}
京东头部
- 两端固定中间自适应:使用padding+定位实现(最佳方案兼容性比较好)
- 定位后元素没有宽度需要内容撑开,所以需要设置宽度
- display:fixed相对浏览器的宽度,所以需要设置最小宽度
- 精灵图设置:
width: 56px;/*75px高度和宽度为图片缩小后的高度和宽度*/
height: 21px;/*40px*/
left:10px;
top:10px;
background: url(../images/jd-sprites.png) no-repeat;
background-size: 200px 200px;/*2倍图,图片大小先缩小一半*/
background-position: 0 -109px;/*写图片坐标的时候这里为负数*/
- 滚动变色
1.滚动事件:window.onscroll= function(){}
2.获取滚动的长度:window.pageYOffset
代码:
// 2-头部滚动变色
// 头部盒子颜色透明度 和页面滚动高度成正比
// 用页面卷曲高度 和 指定的值做对比, 比值设置为头部透明度 400
function setHeader() {
var header = document.querySelector('.jd-header');
//指定目标高度
var target = 360;
//监听页面滚动事件
window.onscroll = function () {
//获取页面卷曲的高度
var top = window.pageYOffset;
// console.log(top);
var value = top / target;
//透明度最大为0.8
if (value > 0.8) {
value = 0.8;
}
console.log(value);
// 设置颜色
header.style.background = 'rgba(222, 24, 27, ' + value + ')';
}
}
各种高:
- clientHeight:元素客户区的大小,指的是元素内容及其边框所占据的空间大小(经过实践取出来的大多是视口大小)
- scrollHeight: 滚动大小,指的是包含滚动内容的元素大小(元素内容的总高度)
- offsetHeight: 偏移量,包含元素在屏幕上所用的所有可见空间(包括所有的内边距滚动条和边框大小,不包括外边距
京东轮播图
轮播图:ul>li>a>img
ul的宽度设置大一点:width:1000%
li宽度设置为十分之一:width:10%
img宽度:100% 这样可以是响应式了
小圆点:ol>li 利用子绝父相实现。
dom类操作:
dom.classList.add(“类名”)
dom.classList.remove(“类名”)
获取元素的宽度:var w = dom.offsetWidth;
思路:
让ul每次移动一个li宽度即可,正好是banner这个大div的宽度
小圆点同步的下标要比index小1;
function banner() {
var banner = document.querySelector(".jd-banner");
var ul = banner.querySelector("ul");
var points = banner.querySelectorAll("ol li");
var w = banner.offsetWidth;//父盒子的宽度就是ul每次移动的距离,dom.offsetWidth获取dom的宽度
var index = 1;
var timer = setInterval(function(){
index ++;
var x = -index * w;
ul.style.transform = 'translateX('+x+'px)';
ul.style.transition = 'transform 0.4s';
},1000)
//每次过渡结束判断index
ul.addEventListener("transitionend",function(){
if(index >= 9){
index = 1;
//移除过渡
ul.style.transition = 'none';
var x = -index * w;
ul.style.transform = 'translateX('+x+'px)';
}
console.log(index);
//小圆点同步
points.forEach(function(v,i){
//移除所有样式
v.classList.remove("current");
});
points[index - 1].classList.add("current");
});
}
京东导航
- ul > li > a >(img和p)
- 图片是2倍图,所以可以给img标签设置宽度
- 每行显示5个,自适应,所以可以设置每个li的宽度为20%
- 利用浮动让li在一行显示。
- 利用text-align:center让li中的a标签居中
京东快报
- 两端用padding撑开,再通过定位去设置两端的元素样式
- 中间是ul li,并用大div把ul包裹起来,大div的的高度固定,ul不设高度由内容撑开,此时用overflow隐藏
- js定时器:var timer = setInterval(function(){},1000); 清除clearInterval(timer )
- 监听过渡结束(transitionend):ul.addEventListener(‘transitionend’, function(){});
实现思路:让ul每隔一段时间向上滚动,并加上动画实现过渡。每次记录index的值
function news() {
var ul = document.querySelector(".jd-news .list ul");
var li = ul.querySelectorAll("li");
var index = 0;
setInterval(function(){
index ++;
var y = -index * 30;
ul.style.transform = 'translateY('+y+'px)';
ul.style.transition = 'transform 0.5s';
},2000);
//过渡结束监听
ul.addEventListener("transitionend",function(){
if(index >= li.length-1){
index = 0;
//ul瞬间调回第一个进行重合
ul.style.transform = 'translateY(0)';
//移除过渡效果
ul.style.transition = 'none';
}
})
}
京东秒杀
秒杀头部
- 整体使用浮动布局
- 倒计时样式使用5个span标签实现
秒杀主体
- ul>li>a>(img p p)
- 宽度设置为880px,这样利用overflow就可以有滚动条效果
京东主会场
a>img 三个图片宽度设置为33.33% 左浮动即可。
商品模块
第一排图片:宽度33.33%,第二排和第三排都为50%
商品分类页
分类页头部
中间自适应两端固定,使用bfc实现
两端的按钮使用精灵图+背景图片原点、背景图片定位、背景图片裁切实现
分类页主体部分
主体部分的布局使用bfc实现
滑动使用IScroll插件实现,原理是大盒子很小,大盒子里面的小盒子很长。
touch事件
移动端新增了4个与手指触摸相关的事件。
//touchstart:手指放到屏幕上时触发
//touchmove:手指在屏幕上滑动式触发(会触发多次)
//touchend:手指离开屏幕时触发
//touchcancel(了解):系统取消touch事件的时候触发,比如电话
每个触摸事件被触发后,会生成一个event对象,event对象中changedTouches
会记录手指滑动的信息。
e.touches;//当前屏幕上的手指
e.targetTouches;//当前dom元素上的手指。(重要)
e.changedTouches;//触摸时发生改变的手指。(重要) 触摸结束后只有此对象可以获取相关信息
这些列表里的每次触摸由touch对象组成,touch对象里包含着触摸信息,主要属性如下
clientX / clientY: //触摸点相对浏览器窗口的位置
pageX / pageY: //触摸点相对于页面的位置
【touch小例子】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
div{
width: 100%;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
</body>
<script>
var div = document.querySelector("div");
var distance = 0;
var startX = 0;
var endX = 0;
div.addEventListener("touchstart",function(e){//开始触摸
console.log("start:"+e.changedTouches[0].clientX);
startX = e.changedTouches[0].clientX;
});
div.addEventListener("touchmove",function(e){//滑动
//console.log("move:"+e.changedTouches[0].clientX);
});
div.addEventListener("touchend",function(e){//触摸结束
console.log("end:"+e.changedTouches[0].clientX);
endX = e.changedTouches[0].clientX;
distance = endX - startX;
if(distance > 0){
console.log("右滑");
}
//distance == 0 说明没有滑动
if(distance < 0){
console.log("左滑");
}
});
</script>
</html>
通过touch滑动轮播图
//1. 给ul注册touch相关的三个事件(注意清除浮动,不然触发不到touchmove事件)
//2. 在touchstart中
//1. 记录开始的位置
//2. 清除定时器
//2. 在touchmove中
//1. 记录移动的距离
//2. 清除过渡
//3. 让ul跟着移动
//3. 在touchend中
//1. 记录移动的距离
//2. 判断移动距离是否超过1/3屏,判断上一屏还是下一屏,或者是吸附
//3. 添加过渡
//4. 执行动画
//5. 开启定时器
//4. 优化:快速滑动的实现逻辑
//5. 优化:重置大小时轮播图错位。
关于tap事件与click事件
- click事件在pc端非常用,但是在移动端会有300ms左右的延迟,比较影响用户的体验,300ms用于判断双击还是长按事件,只有当没有后续的的动作发生时,才会触发click事件
- tap事件只要轻触了,就会触发,体验更好。
/*
* 由于移动端的点击事件click 有300左右的延迟, 用户体验有待提升
* 希望 能用touch事件封装一个相应速度更快的 点击事件 tap
*
* touch判断为点击事件的条件:
*
* 1、触屏开始 到触屏结束 手指没有移动
* 2、接触屏幕的时间 小于指定的值 150ms *
*
* 满足以上两个条件 可以认为是点击事件触发了
* */
/*
* 插件功能:
* 给指定的元素 绑定优化后的移动的点击事件--- tap事件
* 参数:
* obj:要绑定优化后点击事件的元素
* callback: 当点击事件触发 执行什么操作
* */
var itcast={
tap:function(obj,callback){
if(typeof obj=='object'){ //判断传入的obj是否为对象
var startTime=0;//记录起始事件
var isMove=false; //记录是否移动
obj.addEventListener('touchstart',function(){
startTime=Date.now(); //获取当前时间戳
});
obj.addEventListener('touchmove',function(){
isMove=true; //记录移动
});
obj.addEventListener('touchend',function(e){
//判断是否满足点击的条件
if(!isMove&&Date.now()-startTime<150){
//tap点击事件触发
//if(callback){
// callback();
//}
callback&&callback(e);
}
//数据重置
isMove=false;
startTime=0;
});
}
}
}
zepto框架介绍(了解)
Zepto是一个轻量级的针对现代高级浏览器的JavaScript库, 它与jquery有着类似的api。 如果你会用jquery,那么你也会用zepto。
zepto与jquery的区别
- jquery针对pc端,主要用于解决浏览器兼容性问题,zepto主要针对移动端。
- zepto比jquery轻量,文件体积更小
- zepto封装了一些移动端的手势事件
zepto的基本使用
zepto的使用与jquery基本一致,zepto是分模块的,需要某个功能,就需要引入某个zepto的文件。
<script src="zepto/zepto.js"></script>
<script src="zepto/event.js"></script>
<script src="zepto/fx.js"></script>
<script>
$(function () {
$(".box").addClass("demo");
$("button").on("click", function () {
$(".box").animate({width:500}, 1000);
});
});
</script>
zepto手势事件
zepto中根据touchstart touchmove touchend
封装了一些常用的手势事件
tap // 轻触事件,用于替代移动端的click事件,因为click事件在老版本中会有300ms的延迟
//穿透的问题 fastclick:
swipe //手指滑动时触发
swipeLeft //左滑
swipeRight //右滑
swipeUp //上滑
swipeDown //下滑
BFC盒子
BFC 块级格式化上下文
Block Formatting Context: 页面上一个隔离的独立渲染区域
触发成为 BFC 盒子的特点:
触发了 BFC 的盒子, 就成为了页面上的一个隔离的独立容器, 容器里面的子元素不会在布局上影响到外面的元素
应用: 解决塌陷问题, 清除浮动
触发了BFC的普通盒子, 不会与浮动元素重叠
应用: 圣杯布局, 左侧固定右侧自适应
如何触发 BFC
- float: left; float: right;
- overflow的值不为visible。
- position的值absolute, fixed
- display的值为table, table-cell
圣杯布局
圣杯布局实现
1-定位+padding
注意:padding会撑大盒子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圣杯布局</title>
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 100%;
height: 200px;
background-color: skyblue;
padding: 0 50px;
box-sizing: border-box;
}
.box .left,.box .right{
width:50px;
height: 200px;
}
.left{
position:absolute;
background-color: blue;
top:0;
left:0;
}
.right{
position:absolute;
background-color:green;
top:0;
right:0;
}
.center{
width: 100%;
height: 200px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="box">
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</div>
</body>
</html>
2-浮动+BFC
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圣杯布局1</title>
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 100%;
height: 200px;
background-color: skyblue;
box-sizing: border-box;
}
.box .left,.box .right{
width:50px;
height: 200px;
}
.left{
background-color: blue;
float: left;
}
.right{
background-color:green;
float:right;
}
.center{
/* width: 100%; */ /*不能设置100%,设置了就会被挤下去*/
height: 200px;
background-color: yellow;
overflow: auto;
}
</style>
</head>
<body>
<div class="box">
<div class="left"></div>
<div class="right"></div>
<div class="center"></div>
</div>
</body>
</html>
3-伸缩布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圣杯布局1</title>
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 100%;
height: 200px;
background-color: skyblue;
display:flex;
}
.box .left,.box .right{
width:50px;
height: 200px;
}
.left{
background-color: blue;
}
.right{
background-color:green;
}
.center{
height: 200px;
background-color: yellow;
flex:1;
}
</style>
</head>
<body>
<div class="box">
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</div>
</body>
</html>
bootcdn