WebAPI基础

WebAPI学习

接下来一些案例 https://download.csdn.net/download/f_felix/11130717

查找对象的方式

//document.getElementById():通过id
//document.getElementsByTagName("标签名"):通过标签名 返回一个伪数组,无论有几个元素,返回都是伪数组
//document.getElementsByClassName("类名") 返回值:伪数组
//document.getElementsByName():通过name属性查找 只适用于表单元素

//通过css选择器来查找,, 如果是id需要加上#id   如果是类名,需要加上.类型
//document.querySelector()   :返回一个对象,如果有多个,会返回第一个
//document.querySelectorAll():返回一个伪数组,
document.querySelector(".class div");
document.querySelector("#id>div");

innerText属性与innerHTML属性

  • innerText属性:设置标签的文本内容,会对标签进行转义,标签不能生效。(尽量多用innerText)
  • innerHTML属性:设置标签的内容,不会对标签进行转义,标签能生效
// 区别
// innerText只会获取标签文本内容,如果有标签会被忽略
// innerHTML会获取到文本内容+标签
// innerText在设置内容的时候,HTML标签不生效,会对所有的标签进行转义  <h1>
// innerHTML在设置内容的时候,HTML会生效
// 注意:尽量少用innerHTML,防止xss攻击,尤其是用来用户的输入内容上
box.innerText = '<h1>我是一个更大的标题</h1>';
box.innerHTML = '<h1>我是一个更大的标题</h1>';

对于a标签来说,默认的行为就是进行页面跳转,如果不想让a标签进行跳转,可以在注册事件中使用return false

var link = document.getElementById("link");
link.onclick = function() {
  alert("呵呵");
  //阻止页面跳转
  return false;
}
//href:如果写了javascript:表示a标签不执行跳转,执行js代码
//javascript:void(0);:可以阻止页面跳转
//javascript:; a标签不跳转

修改标签的样式

同样的DOM对象可以通过className操作样式,也可以通过style属性操作样。 style设置的样式是行内样式,因此优先级要高于className设置的样式

//1. style属性是一个对象,里面存储了所有行内样式对应的键值对。
//2. 如果样式的名字带了-,比如background-color,到了style对象中,变成了驼峰命名法,backgroundColor(因为-在js中不是一个合法的标识符)
//3 style属性只能获取和设置行内样式,在类样式中定义的样式通过style获取不到。

使用cssText可以设置style的属性值

//优点:可以一次性设置多个值
//缺点:会覆盖其他值
var box = document.getElementById("box");
box.style.cssText = "font-size: 20px; width:100px; height:100px;background-color:pink;";

标签的自定义属性

在html页面中,定义一个自定义属性

<div id="box" aa="bb"></div>

在对应的DOM对象中是不存在的,在DOM对象中只会存在固定的那些属性。

var box = document.getElementById("box");
console.log(box.aa);//undefined

对象设置一个自定义的属性

<body>
    <div class="tab">
        <ul>
            <li class="active">国际大牌<span></span></li>
            <li>国妆名牌<span></span></li>
            <li>清洁用品<span></span></li>
            <li>男士精品</li>
        </ul>
        <div class="content">
            <img src="images/guojidapai.jpg" alt="">
            <img src="images/guozhuangmingpin.jpg" alt="" class="hide">
            <img src="images/qingjieyongpin.jpg" alt="" class="hide">
            <img src="images/nanshijingpin.jpg" alt="" class="hide">
        </div>
    </div>
    <script>
        var lis = document.getElementsByTagName("li");
        var imgs = document.getElementsByTagName("img");
        for (var i = 0; i < lis.length; i++) {
            //  这是给对象设置的自定义属性,所以在标签中是不会显示的
            lis[i].index = i;
            // 这是给标签设置属性的,所以在页面上的标签是会有显示的
            // lis[i].setAttribute("aa", i);
            lis[i].onmouseover = function () {
                for (var j = 0; j < lis.length; j++) {
                    lis[j].className = ""
                    imgs[j].className = "hide";
                }
                this.className = "active";
                imgs[this.index].className = "";
                // imgs[this.getAttribute("aa")].className = "";
            }
        }
    </script>
</body>

attribute方法

attribute系列方法用于设置标签的属性,不管是自定义的还是固有的属性。例子参考上面的

//获取标签的属性
box.getAttribute(name);
//设置标签的属性
box.setAttribute(name, value);
//移除标签的属性
box.removeAttribute(name);

排他思想

上述的例子中用到了这个排他思想

lis[i].onmouseover = function () {
    /*
    	排他思想:
    	只想要选中的标签有特定的效果显示,别的标签保持一致。
    	首先让所有的标签都统一样式(包括自己),然后给自身单独设置特定的样式
    */
    for (var j = 0; j < lis.length; j++) {
        lis[j].className = ""
        imgs[j].className = "hide";
    }
    this.className = "active";
    imgs[this.index].className = "";
    // imgs[this.getAttribute("index")].className = "";
}

this的指向

//关于this
//函数内部的this是window
//方法内部的this,指向当前的对象
//构造函数内部的this,新创建的对象
//事件里面的this,当前对象

节点操作

孩子节点

//childNodes:获取所有的孩子节点(包括了元素节点和其他很多类型的节点,基本不常用)
//children:获取所有的子元素(用途很广泛),兼容性:IE678会把注释节点算上。
//firstChild //第一个子节点
//firstElementChild //第一个子元素 有兼容性问题(IE678)
//lastChild //最后一个节点
//lastElementChild //最后一个子元素 有兼容性问题(IE678)

兄弟节点

//1. nextSibling:下一个兄弟节点
//2. nextElementSibling:下一个兄弟元素(IE678不兼容)
//3. previousSibling//上一个兄弟节点
//4. previousElementSibling //上一个兄弟元素 有兼容性问题 可以封装一个兼容性方法

父节点

//1. parentNode:父节点  没有兼容性问题

appendChild

语法:parent.appendChild(newChild)

parent:调用者,父节点来调用

newChild:需要添加的那个孩子。

作用:把newChild添加到parent的孩子的最后面。

注:如果newChild已经存在于DOM树中,则它会被从原始位置删除。 newchild原来的父节点长度会缩短

var demo = document.getElementById("demo");
var box = document.getElementById("box");
box.appendChild(demo);

insertBefore

语法:parent.insertBefore(newChild, refChild);

parent:必须要父节点来调用

newChild:需要添加的那个节点

refChild:添加到哪一个节点的前面。

var ul = document.getElementById("list");
var li = document.createElement("li");
li.innerHTML = "哈哈";
//就是添加到子节点的最前面。
ul.insertBefore(li, ul.children[0]);

createElement

语法:var element = document.createElement(“tagName”);

作用:在内存里面创建了一个节点

返回:一个元素

用途非常的广泛。

删除节点

语法:parent.removeChild(child);

功能:有父盒子调用,删除里面的一个子元素。

替换节点

语法:parentNode.replaceChild(newChild, oldChild);

  • newChild用来替换 oldChild的新节点,如果newChild已经存在于DOM树中,则它会被从原始位置删除。

pageX (Y)、clientX(Y)和screenX(Y)

// 网页上的坐标
// console.log(event.pageX, event.pageY);
// 屏幕的坐标。和页面的坐标是一致的
// console.log(event.clientX, event.clientY);
// 获取的坐标是包含浏览器的工具栏和地址栏那部分的
// console.log(event.screenX, event.screenY);

注册事件的两种方式

1、on+事件类型

注册事件:

box.onclick = function(){
	//事件处理程序	
}

移除事件:

box.onclick = null;	

on+事件名称注册事件的缺点:

同一个元素同一类型的事件,只能注册一个,如果注册了多个,会出现覆盖问题。

2、addEventListener

// 给一个元素添加一个事件监听, 给元素注册一个事件
// 参数1: 事件的类型 类型中没有on
// 参数2: 事件处理程序
// 参数3: 是否捕获  true 捕获  false 冒泡(常常不写这个参数,默认冒泡)
// 事件源.addEventListener(事件类型, 事件处理程序, 是否捕获)
addEventListener(type, func, useCapture);

tips:如果想要让你注册的事件能够移除,不能使用匿名函数。

function fn1() {
    alert("hehe");
}
//如果想让注册的事件能移除,不能用匿名函数。
box.addEventListener("click", fn1, false);

removeEventListen的语法

//第一个参数:参数类型
//第二个参数:要移除的那个函数
//第三个参数:false(可以不写)
removeEventListener(type, func, useCapture);

事件流

事件冒泡

当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡。

事件捕获

事件的处理将从DOM层次的根开始,而不是从触发事件的目标元素开始,事件被从目标元素的所有祖先元素依次往下传递 (基本上,我们都是用事件冒泡)

// 任何一个事件都会经历3个阶段
// 1. 事件捕获
// 2. 目标阶段
// 3. 事件冒泡
<div class="father">
    <div class="son">
        <div class="sun">
            </div>
    </div>
</div>
<script>
    var son = document.querySelector('.son');
    var sun = document.querySelector('.sun');
    var father = document.querySelector('.father');
    document.addEventListener('click', function() {
        console.log(this);
    }, false);
    document.body.addEventListener('click', function() {
        console.log(this);
    }, true);
    father.addEventListener('click', function() {
        console.log(this);
    }, true);
    son.addEventListener('click', function() {
        console.log(this);
    }, false);
    sun.addEventListener('click', function() {
        console.log(this);
    }, true);
</script>

在这里插入图片描述

事件对象

// 事件对象: 任意一个事件都会有一个事件对象
// 事件对象的作用: 用来获取鼠标的位置, 键盘的按下的键
// 当我们需要获取鼠标的位置   或者按下的键 需要用到事件对象
// 怎么获取事件对象
// 在注册事件的时候,给function提供一个形参,下面的event就是接受事件对象的(这个名字可以随意取)
button.onclick=function(event){console.log();}

兼容性封装(可以不用考虑IE678,后面的框架都是不支持IE678的)

btn.onclick = function(event){
  	//只要用到了事件对象,就要记得处理浏览器兼容性
	event = event || window.event;
}
// 想要获取鼠标的位置
// screenX screenY : 相对于屏幕最左上角的距离(用的不多)
// clientX clientY : 相对于可视区左上角的距离
// pageX pageY:      相当于整个页面左上角的距离 如果有滚动条, pageY是包含滚动条隐藏的那部分高度

这个js中就可以体会client和page两对的差别

阻止浏览器默认行为

// 通过e.preventDefault()可以阻止浏览器的默认行为,不推荐使用return false;
// a标签点击会跳转    img按住了可以拖拽   表单点击提交了也会跳转
// 不推荐使用,  return false优点: ie678也可以用
// 缺点: 1. return false后的代码不会执行,只能写在最后面.
//       2. 将来在react的时候,return false不被支持
// 通过事件对象   e.preventDefault()  1. 后续代码可以执行  2. 标准的阻止浏览器默认行为

阻止事件冒泡

// 通过e.stopPropagation()方法可以阻止事件冒泡

阻止a标签跳转

<!-- 跳锚点, 表示跳到顶部锚点 -->
<!-- javascript:; 表示一个伪协议 href中只要写了javascript: 表示这个a标签不跳转,变成执行js代码了
void(0):等价于undefined -->
<!-- 
阻止a标签跳转
1. 注册点击事件, 阻止浏览器默认行为
2. #           : 一般来说,还是连接
3. javascript:;: 把a当成按钮来用
-->

三大系列

offset系列

// offsetWidth 与 offsetHeight: 用于获取元素真实的高度和高度
// style对应的 标签中的style属性,对应的是行内样式
// 通常来说,我们不会通过style来获取样式,只能获取行内样式。
// 1. 获取到的是盒子的真实的大小, offsetWidth = width + padding + border  
// 2. 获取到的直接数字类型,直接运算
// 3. offsetWidth是只读属性,不允许修改
// offsetParent: 距离自己最近的有定位的父元素, 如果都没有,找body元素
// parentNode: 父元素
// offsetLeft offsetTop: 获取元素真实的位置, 距离offsetParent的距离  offsetLeft = left + margin—left

scroll系列

不常用这个

// scrollWidth scrollHeight : 指的是内容的大小,如果内容超出了,大小会比盒子更大
// scrollLeft scrollTop:获取滚动条滚动的距离

client系列

//client系列  client:客户区,可视区 获取盒子的大小,不包括边框
//clientWidth clientHeight
//clientLeft clientTop
// clientLeft:获取的就是左边框的宽度
// clientTop: 获取的就是上边框的宽度
// client系列: 获取整个window的大小
// window.onload window.onscrll  window.onresize: 当窗口大小发生改变的时候
window.onresize = function() {
    // 获取到窗口的宽度和高度
    // console.log(document.documentElement.clientWidth);  以前是这样获取的
    // console.log(document.documentElement.clientHeight);
    console.log(window.innerWidth);
    console.log(window.innerHeight);
}

client与rem布局

// 一般需要在页面加载前设置html的fontSize的大小
//rem布局: 给不同的屏幕设置不同的html的fontSize
//下面代码写在head标签下的script中,因为页面一进来就要进行加载,不然的话会忽然跳一下
// 等价于我们之前用媒体查询写的那一段
function fn(){
    console.log('哈哈')
    var width = window.innerWidth;
    width = Math.min(width, 750);
    width = Math.max(width , 320);
    document.documentElement.style.fontSize = width/15 + 'px';
}
fn();
window.onresize = fn;

新增一个事件

一般我们不给盒子设置滚动条,但是我们的页面(window)可以有滚动条

// 事件 onscroll 当div的滚动条滚动的时候
element.onscroll = function(){
    console.log(element.scrollTop);
}

BOM

Window对象

// window对象 onload
// window对象常用的有三个事件  load  scroll resize
window.onscroll = function() {
    console.log('哈哈哈');
    // 想要获取到scrollTop值
    // 早期:要么获取html的,要么获取body的
    // 现在直接通过 window.pageYOffset就可以获取
    // 垂直滚动条的距离
    console.log(window.pageYOffset);
    // 水平滚动条的距离
    console.log(window.pageXOffset);
}
// window.onload : 当整个网页加载完成,保证网页依赖的资源(图片)加载完成后才会触发onload事件
// 在window.onload中可以保证页面加载完成,所以肯定能获取到页面中的元素
// 如果将来想要获取页面中图片的宽度和高度, 应该把代码写在window.onload中

setTimeout

setTimeout延时器可以在延迟时间到期后执行一个指定的函数

setInterval

setInterval,方法重复调用一个函数或执行一个代码段,在每次调用之间具有固定的时间延迟。定时器除非清除,否则会一直执行下去。

// timeId是定时器的编号,是一个累加的数字,,,,浏览器只要开启了一个定时器
// 开启一个定时器,就是给浏览器一个任务,让浏览器每隔指定的时间去调用一次函数

轮播图

常用的轮播图插件swiper https://www.swiper.com.cn/

1、封装动画函数

/**
 * 匀速运动
 * @param element 哪个元素运动
 * @param target  目标距离
 * @param num   每一步移动的距离
 */
 function animate(element, target, num) {
    clearInterval(element.timeId);
    element.timeId = setInterval(function () {
    var current = element.offsetLeft;
    var step = current > target ? -num : num;
    if (Math.abs(current - target) > Math.abs(step)) {
        current += step;
        element.style.left = current + "px";
    } else {
        clearInterval(element.timeId);
        element.style.left = target + "px";
    }
    }, 16);
}
/**
 * 变速运动(缓动动画)
 * @param {元素标签} element 
 * @param {需要改变的属性(对象类型)} obj 
 * @param {回调函数} fn
 * obj {width:400, height:400, left:400, top:400, borderRadius:200}
 * 如果传了回调函数,动画就可以呈现阶段变化
 */
function speedAnimation(element, obj, fn) {
    clearInterval(element.timer);
    element.timer = setInterval(function () {
        var flag = true;
        for (var k in obj) {
            var attr = k;
            var target = obj[k];
            //对opacity做特殊处理即可
            //1. parseInt改成parseFloat (获取到的透明度是个小数)
            //2. 把leader和target都放大了1000倍。 算出来的step也是放大了1000倍
            //3. 设置回去的时候,让leader/1000   把px给去掉了
            if (attr == "opacity") {
                var leader = getStyle(element, attr); // 这个方法见下面的获取计算后的样式那一节
                leader = parseFloat(leader) || 0;
                leader = leader * 1000;
                target = target * 1000;
                var step = (target - leader) / 10;
                //step肯定是一个很小的数,Math.ceil就会向上取整,直接会变成1
                // 当为负数的时候就要向下取整了
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                leader += step;
                element.style[attr] = leader / 1000;
                if (leader != target) {
                    flag = false;
                }
            } else if (attr == "zIndex") {
                //层级不需要动画,直接设置即可。
                element.style.zIndex = target;
            } else {
                var leader = getStyle(element, attr);
                leader = parseInt(leader) || 0;
                var step = (target - leader) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                leader += step;
                console.log(step);
                element.style[attr] = leader + "px";
                if (leader != target) {
                    flag = false;
                }
            }
        }
        if (flag) {
            clearInterval(element.timer);
            //如果传了fn,就调用fn,如果没传,就不掉
            //        if(fn) {
            //          fn();
            //        }
            //假值短路
            fn && fn();
        }
    }, 15);
}

2、切割轮播图

扩展知识点

参数描述
function(currentValue, index, arr)必需。 数组中每个元素需要调用的函数。
thisValue可选。传递给函数的值一般用 “this” 值。 如果这个参数为空, “undefined” 会传递给 “this” 值
参数描述
currentValue必需。当前元素
index可选。当前元素的索引值。
arr可选。当前元素所属的数组对象。
// forEach() 方法
// forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
// 注意: forEach() 对于空数组是不会执行回调函数的。
array.forEach(function(currentValue, index, arr), thisValue)
//例子:
var uls = box.querySelectorAll("ul");
uls.forEach(function (ul, index, uls) {
    ul.style.transform = "rotateX(" + -90 * count + "deg)";
    ul.style.transition = "1s " + 0.2 * index + "s";
})

节流阀
当前一个动作执行的时候,下一个动作需要等前一个动作完成了才可以继续,可以节省资源,参考案例 切割轮播图

移动端的WebAPI

区域滚动

实现页面上常见到的区域滚动效果
开发中常用的 插件 iscroll http://caibaojian.com/iscroll-5/

// 移动端有专属的四个事件
// touchstart: 开始触摸
// touchmove: 触摸移动
// touchend: 触摸结束
// touchcancel: 触摸取消  被系统取消,系统有一些优先级很高的应用,电话

// 同样通过事件对象获取 e.touches[0],可以计算出手指滑动的距离
// touches: 当前屏幕上所有的手指。
// targetTouches: 目标元素上的手指
// changedTouches: 改变的手指 ,在事件touchend 中只能通过这个获取触摸点,在end的手相当于手指已经离开屏幕

// 要获取手指的位置还需要通过三个touches中的PageX和pageY 
// (clientX和clientY在没有滚动条的情况下和page的是一样的) 不考虑使用screenX(Y),前面有解释
var son = document.querySelector('.son');
// 记录开始移动的位置
var startX;
var total = 0;
son.addEventListener('touchstart', function(e) {
    startX = e.touches[0].pageX;
});

// 让son跟着跑
son.addEventListener('touchmove', function(e) {
    var moveX = e.touches[0].pageX - startX ;
    // 让son跟着动,在之前移动的基础上继续移动
    var x = total + moveX;
    console.log(x);
    // 等价于 if(x > 0) x = 0; if(x < -300) x =-300;
    x = Math.min(0, x);
    x = Math.max(x, -300);
    son.style.transform = 'translateX(' + x + 'px)';
    // console.log(moveX);
});
// 记录最终移动的距离
son.addEventListener('touchend', function(e) {
    // 本地移动的最终距离
    var totalX = e.changedTouches[0].pageX - startX;
    total += totalX;
    total = Math.min(0, total);
    total = Math.max(total, -300);
    console.log(total);
    // console.log('total',total);
});

补充

// 经验之谈  手机端  safari浏览器时间不识别 -  2019-04-19 00:00:00
var seckillTime = new Date('2019/04/19 18:30:00');
// 因此时间格式可以写成 2019/04/19 00:00:00
// 位运算符  任何一个小数 | 0  把小数给去了  等价于  parseInt(1.234)  输出 1
var time = 1234 / 1000 | 0;  // 输出 1

自定义播放器

全屏切换API:

// video.requestFullScreen()
// div.webkitRequestFullScreen();
// div.mozRequestFullScreen();
function full(element) {
    // 能力检测
    if ('requestFullScreen' in element) {
        element.requestFullScreen()
    } else if ('webkitRequestFullScreen' in element) {
        element.webkitRequestFullScreen()
    } else if ('mozRequestFullScreen' in element) {
        element.mozRequestFullScreen()
    } else {
        alert('亲,你的浏览器不支持全屏的api,要不换个浏览器??')
    }
}

属性

// currentTime:当前时间
// duration:总长时间
// timeupdate:播放进度更改时触发
// volume:控制音量

classList

类名操作

推荐:classList是一个集合,会存储某个元素上所有的类名,使用classList来替代className操作class类

//添加类
node.classList.add("classname");
//移除类
node.classList.remove("classname");
//切换类
node.classList.toggle("classname");
//判断类
node.classList.contains("classname");

console.log(node.classList)  // 输出的是一个数组,是设置在node上的所有class

获取计算后的样式

通过element.style.xxx只能获取到行内样式
通过offset系列只能获取到特殊的一些样式

获取元素计算后的样式指的是元素经过层叠后真正生效的样式,不管样式写在哪,计算后的样式指的就是最终的样式。

// 现代浏览器:
return window.getComputedStyle(element, null)[attr];
// IE678:
return element.currentStyle[attr];
/**
 * 解决兼容性问题
 * @param {获取哪个标签的属性} element 
 * @param {获取标签的哪个属性} attr 
 */
function getStyle(element, attr) {
    if (window.getComputedStyle) {
        return window.getComputedStyle(element, null)[attr];
    } else {
        return element.currentStyle[attr];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值