分类: web前端 | 标签: 移动web

移动web开发

发表于: 2020-12-11 10:25:28 | 字数统计: 5.7k | 阅读时长预计: 28分钟

移动端开发现状

  • 移动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>

移动端调试问题

  1. 模拟器调试
  2. 真机调试:使用手机进行访问。

手机设备五花八门,屏幕尺寸都大不一样,尤其是安卓端,给我们的页面预览带来了一些麻烦。在实际工作中,作为开发者不可能有足够的设备让我们去测试(除了测试部门 ),即便有,效率也特别的低,因此开发者一般都是通过浏览器的手机模拟器来模拟不同的设备。

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: 偏移量,包含元素在屏幕上所用的所有可见空间(包括所有的内边距滚动条和边框大小,不包括外边距

京东轮播图

1607503954234

轮播图: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%

商品分类页

1608519832257

分类页头部

中间自适应两端固定,使用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事件

  1. click事件在pc端非常用,但是在移动端会有300ms左右的延迟,比较影响用户的体验,300ms用于判断双击还是长按事件,只有当没有后续的的动作发生时,才会触发click事件
  2. 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。

github地址

中文文档

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 盒子的特点:

  1. 触发了 BFC 的盒子, 就成为了页面上的一个隔离的独立容器, 容器里面的子元素不会在布局上影响到外面的元素

    应用: 解决塌陷问题, 清除浮动

  2. 触发了BFC的普通盒子, 不会与浮动元素重叠

    应用: 圣杯布局, 左侧固定右侧自适应

如何触发 BFC

  • float: left; float: right;
  • overflow的值不为visible。
  • position的值absolute, fixed
  • display的值为table, table-cell

圣杯布局

圣杯布局实现

1-定位+padding

1607666099556

注意: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

1607666120365

<!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-伸缩布局

1607666142664

<!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

------ 本文结束,感谢您的阅读 ------
本文作者: 贺刘芳
版权声明: 本文采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。