一、offset、client、scroll三大家族介绍
1.1、offset概述
offset翻译过来就是偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
- 获得元素距离带有定位父元素的位置
- 获得元素自身的大小(宽度高度)
- 注意:返回的数值都不带单位
offset系列常用属性:
1.2、offset与style区别
offset
- offset可以得到任意样式表中的样式值
- offset系列获得的数值是没有单位的
- offsetWidth包含padding+border-+width
- offsetWidth等属性是只读属性,只能获取不能赋值
- 所以,我们想要获取元素大小位置,用offset更合话
style
- style只能得到行内样式表中的样式值
- style.width获得的是带有单位的字符串
- style.width获得不包含padding和porder的值
- style.width是可读写属性,可以获取也可以赋值
- 所以,我们想要给元素更改值,则需要用syle改变
1.2、元素可视区client系列
client翻译过来就是客户端,我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
1.3、立刻执行函数
<script>
//1. 第一种写法 (function(){}()) 第二种写法 (function(){})()
(function (a) {
console.log(a); //1
}(1));
(function (a, b) {
console.log(a, b);//3 5
})(3, 5);
</script>
立即执行函数 (function(){}())或者 (function(){})()
主要作用:创建一个独立的作用域。避免了命名冲突问题
1.4、元素scroll系列属性
scroll翻译过来就是滚动的,我们使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离等。
1.4.1、页面被卷去的头部兼容性解决方案
需要注意的是,页面被卷去的头部,有兼容性问题,因此被卷去的头部通常有如下几种写法:
-
1.声明了DrD,使用document.documentElement.scrollTop
-
2.未声明DTD,使用document.body.scrollTop
-
3.新方法window.pageYoffset和window.pagexoffset,IE9开始支持
1.5、offset、client、scroll总结
他们主要用法:
-
1.offset?系列经常用于获得元素位置offsetLeft offsetTop
-
2.client经常用于获取元素大小clientWidth clientHeight
-
3.scroll经常用于获取滚动距离scrollTop scrollLeft
-
4.注意页面滚动的距离通过window.pagexoffset获得
二、缓动动画的原理和封装
2.1、鼠标经过(mouseenter和mouseover的区别)
mouseenter鼠标事件
-
当鼠标移动到元素上时就会触发mouseenter事件
-
类似mouseover,它们两者之间的差别是
-
mouseover鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter只会经过自身盒子触发
-
之所以这样,就是因为mouseenter不会冒泡
-
跟mouseenter搭配鼠标离开mouseleave同样不会冒泡
2.2、动画实现原理
核心原理:通过定时器setinterval()不断移动盒子位置。
实现步骤:
-
1.获得盒子当前位置
-
2.让盒子在当前位置加上1个移动距离
-
3.利用定时器不断重复这个操作
-
4.加一个结束定时器的条件
-
5.注意此元素需要添加定位,才能使用element…style.left
<script>
var div = document.querySelector('div');
var timer = setInterval(function() {
if (div.offsetLeft >= 400) {
// 停止动画 本质是停止定时器
clearInterval(timer);
}
div.style.left = div.offsetLeft + 1 + 'px';
}, 30);
</script>
2.2.1、简单动画函数封装
<script>
// 简单动画函数封装obj目标对象 target 目标位置
function animate(obj, target) {
var timer = setInterval(function() {
if (obj.offsetLeft >= target) {
// 停止动画 本质是停止定时器
clearInterval(timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
// 调用函数
animate(div, 300);
animate(span, 200);
</script>
2.2.2、给不同对象添加不同定时器
<script>
// var obj = {};
// obj.name = 'andy';
// 简单动画函数封装obj目标对象 target 目标位置
// 给不同的元素指定了不同的定时器
function animate(obj, target) {
// 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
// 解决方案就是 让我们元素只有一个定时器执行
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
if (obj.offsetLeft >= target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
var btn = document.querySelector('button');
// 调用函数
animate(div, 300);
btn.addEventListener('click', function() {
animate(span, 200);
})
</script>
2.3、动画实现原理
缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
思路:
- 1.让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
- 2.核心算法:(目标值-现在的位置)/10做为每次移动的距离步长
- 3.停止的条件是:让当前盒子位置等于目标位置就停止定时器
三、移动端常见特效
3.1、触屏事件概述
移动端浏览器兼容性较好,我们不需要考虑以前S的兼容性间题,可以放心的使用原生JS书写效果,但是移动端也有自己独特的地方。比如触屏事件touch(也称摸事件),Android和IOS都有。
touch对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或控笔)对屏幕或者触控板操作。
常见的触屏事件如下:
3.2、触屏事件对象(TouchEvent)
TouchEvent是一类描述手指在摸平面(触摸屏、摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减心,等等touchstart、touchmove、touchend三个事件都会各自有事件对象。
触摸事件对象重点我们看三个常见对象列表:
3.3、移动端拖动元素
- 1.touchstart、touchmove、touchend可以实现拖动元素
- 2.但是拖动元素需要当前手指的坐标值我们可以使用targetTouches[0]里面的pageX和pageY
- 3.移动端拖动的原理:手指移动中,计算出手指移动的距离。然后用盒子原来的位置+手指移动的距离
- 4.手指移动的距离:手指滑动中的位置减去手指钢刚开始触摸的位置 拖动元素三步曲:
- (1)触摸元素touchstart:获取手指初始坐标,同时获得盒子原来的位置
- (2)移动手指touchmove:计算手指的滑动距离,并且移动盒子
- (3)离开手指touchend:
注意:手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动e.preventDefaultO:
3.4、click延时解决方案
移动端click事件会有300ms的诞时,原因是移动端屏幕双击会缩放(double tap to zoom)页面。
解决方案:
- 1.禁用缩放。浏览器禁用默认的双击缩放行为并且去掉300s的点击延迟。
<meta name="viewport" content="user-scalable=no">
- 2.利用touch事件自己封装这个事件解决300ms延迟。
原理就是: - 1.当我们手指触摸屏幕,记录当前触摸时间
- 2.当我们手指离开屏幕,用离开的时间减去触摸的时间
- 3.如果时间小于150s,并且没有滑动过屏幕,那么我们就定义为点击
在这里插入图片描述
3.5、Swiper插件的使用
中文官网地址:https:/www.swiper.com.cn/
- 1.引入插件相关文件。
- 2.按照规定语法使用
3.6、其他移动端常见插件
- superslide:http://www.superslide2.com/
- iscroll:https://github.com/cubiq/iscroll
3.7、插件的使用总结
- 1.确认插件实现的功能
- 2.去官网查看使用说明
- 3.下载插件
- 4.打开demo实例文件,查看需要引入的相关文件,并且引入
- 5.复制demo实例文件中的结构html,样式cssl以及js代码
3.8、移动端视频插件y.media.js
H5给我们提供了video标签,但是浏览器的支持情况不同。
不同的视频格式文件,我们可以通过source解决。但是外观样式,还有暂停,播放,全屏等功能我们只能自己写代码解决。这个时候我们可以使用插件方式来制作。
3.9、框架概述
框架,顾名思义就是一套架构,它会基于自身的特点向用户提供一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照框架所规定的某种规范进行开发。
插件一般是为了解决某个问题而专门存在,其功能弹一,并且比较小。前端常用的框架有Bootstrap、Vue、Angular、.React等。既能开发PC端,也能开发移动端前端常用的移动端插件有swiper、.superslide、iscroll等。
框架:大而全,一整套解决方案
插件:小而专一,某个功能的解决方案
3.10、bootstrap
Bootstrap是一个简洁、直观、强悍的前端开发框架,它让web开发更迅速、简单。它能开发PC端,也能开发移动端
Bootstrap JS插件使用步骤:
- 1.引入相关js文件
- 2.复制HTML结构
- 3.修改对应样式
- 4.修改相应JS参数
四、本地存储导读
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种咯样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。
本地存储特性
- 1、数据存储在用户浏览器中
- 2、设置、读取方便、甚至页面刷新不丢失数据
- 3、容量较大,sessionStorage:约5M、localStorage约20M
- 4、只能存储字符串,可以将对象JSON.stringify()编码后存储
4.1、window.sessionStorage
- 1、生命周期为关闭浏览器窗口
- 2、在同一个窗口页面下数据可以共享
- 3.以键值对的形式存储使用
存储数据:
sessionStorage.setltem(key,value)
获取数据:
sessionStorage.getltem(key)
删除数据:
sessionStorage.removeltem(key)
删除所有数据:
sessionStorage.clear()
4.2、window.localStorage
- 1、生命周期永久生效,除非手动删除否测关闭页面也会存在
- 2、可以多窗口(页面)共享(同一浏览器可以共享)
- 3.以键值对的形式存储使用
存储数据:
localStorage.setltem(key,value)
获取数据:
localStorage.getltem(key)
删除数据:
localStorage.removeltem(key)
删除所有数据:
localStorage.clear()
五、ES6
5.1、什么是ES6呢
ES的全称是ECMAScript,它是由ECMA国际标准化组织,制定的一项脚本语言的标准化规范。
ES6实际上是一个泛指,泛指ES2015及后续的版本。
为什么使用ES6?
每一次标准的诞生都意味着语言的完善,功能的加强。JavaScripti语言本身也有一些令人不满意的地方。
- 变量提升特性增加了程序运行时的不可预测性
- 语法过于松散,实现相同的功能,不同的人可能会写出不同的代码
5.2、ES中新增语法
5.2.1、let
ES6中新增的用于声明变量的关键字。
let声明的变量只在所放处于的块级有效
if(true){
let a =10;
}
console.log(a)//a is not defined
注意:使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性。
不存在变量提升
console.log(a);//a is not defined
let a =20;
暂时性死区
var tmp = 123;
if (true){
tmp =abc‘;
let tmp;
}
5.2.2、const
作用:声明常量,常量就是值(内存地址)不能变化的量。
具有块级作用域
if (true){
const a = 10;
}
console.log(a)//a is not defined
声明常量时必须赋值
const PI;/Missing initializer in const declaration
常量赋值后,值不能修改。
const PI 3.14;
PI 100;/Assignment to constant variable.
const ary 【100,200】;
ary【0】=‘a‘;
ary【1】=‘b‘;
console.log(ary);//【‘a‘,‘b‘】;
ary 【‘a‘,‘b‘】;/Assignment to constant variable.
5.2.3、let、const、var的区别
- 1.使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象。
- 2.使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升。
- 3.使用const声明的是常量,在后面出现的代码中不能再修改该常量的值。
5.2.4、解构赋值
ES6中允许从数组中提取值,按照对应位置,对变量赋值。对像也可以实现解构。
数组解构
let【a,b,c】=【1,2,3】;
console.log(a)
console.log(b)
console.log(c)
如果解构不成功,变量的值为undefined。
let 【foo】【】
let 【bar,foo】=【1】;
对象解构
<script>
let person = { name: 'zhangsan', age: 20 }
let { name, age } = person;
console.log(name);//‘zhangsan‘
console.log(age);//20
let { name: myName, age: myAge } = person;//myName myAge属于别名
console.log(myName);//‘zhangsan‘
console.log(myAge);//20
</script>
5.2.4、箭头函数
ES6中新增的定义函数的方式。
()=>{} const fn =()=>{}
函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
<script>
function sum(){
return num1+num2
}
const sum = (num1, num2) => num1 + num2; sum(5, 6); //11
//在箭头函数中 如果形参只有一个 形参外侧的小括号也是可以省略的
const fn = v => {
alert(v);
} // fn(5); //5
</script>
5.2.4、剩余参数
剩余参数语法允许我们将一个不定数量的参数表示为一个数组。
<script>
function sum(first, ...args) {
console.log(first);//10
console.log(args);//【20,30,40】
}
sum(10, 20, 30, 40);
const fn = (...args) => {
let total = 0;
args.forEach(item => total += item);
return total;
}
console.log(fn(10, 20, 30, 40)); //100
</script>
5.2.5、剩余参数和结构搭配使用
<script>
let arr = ['张三', '李四', '王五'];
let [s1, ...s2] = arr;
console.log(s1);//张三
console.log(s2);//(2) ['李四', '王五']
</script>
5.3、ES的内置对象扩展 ,Array的扩展方法
扩展运算符(展开语法)
5.3.1、扩展运算符可以将数组或者对像转为用逗号分隔的参数序列。
<script>
let arr = [1, 2, 3];
console.log(...arr);//1, 2, 3
console.log(arr);//[1, 2, 3]
</script>
5.3.2、扩展运算符可以用于合并数组
<script>
var arr1 = [1, 2, 3];
var arr2 = [2, 3, 4];
//方法1
var arr3 = [...arr1, ...arr2];
//方法2
arr1.push(...arr2);
console.log(...arr1);//1 2 3 2 3 4
console.log(...arr3);//1 2 3 2 3 4
console.log(arr3);//[1, 2, 3, 2, 3, 4]
</script>
5.3.3、将类数组或可遍历对象转换为真正的数组
<script>
//利用扩展运算符将伪数组转换成真正的数组
var oDivs = document.getElementsByTagName('div');
console.log(oDivs);
var arr = [...oDivs];
arr.push('a');
console.log(arr);
</script>
构造函数方法:Array.from()
方法还可以接受第二个参数,作用类似于数组的mp方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
<script>
let arrayLike = {
"0": 1,
"1": 2,
"length": 2
}
let newAry = Array.from(arrayLike, item => item * 2);
console.log(newAry);//[2, 4]
</script>
</script>
5.3.4、findy()
用于找出第一个符合条件的数组成员,如果没有找到返回undefined
<script>
let arr = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
let target = arr.find((item, index) => item.id == 2);
console.log(target); //{id: 2, name: '李四'}
</script>
5.3.5、findIndex()
用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
<script>
let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9);
console.log(index); //2
</script>
5.3.6、includes()
表示某个数组是否包含给定的值,返回布尔值。
<script>
var arr1 = [1, 2, 3];
console.log(arr1.includes(2)); //true
console.log(arr1.includes(5)); //false
</script>
5.4、ES的内置对象扩展 ,String的扩展方法
模板字符串
ES6新增的创建字符串的方式,使用反引号定义。、、
- 模板字符串中可以解析变量。
- 模板字符串中可以换行
- 在模板字符串中可以调用函数。
<script>
let name = `豆沙包`;
console.log(`你好鸭 ${name}`); //你好鸭 豆沙包 解析变量
let html = `
<div>
<span>${result.name}</span> //换行
<span>${result.age}</span>
</div>
`;
const fn = () => {
return '我是fn函数'
}
let html = `我是模板字符串 ${fn()}`;
console.log(html)
</script>
5.4.1、实例方法:startsWith()和endsWith()
- startsWith():表示参数字符串是否在原字符串的头部,返回布尔值
- endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
<script>
let arr = '豆沙包要加油鸭';
console.log(arr.startsWith('豆'));
console.log(arr.endsWith('鸭'));
</script>
5.4.2、repeat()
repeat方法表赤将原字符串重复n次,返回一个新字符串。
<script>
var x = 'x'.repeat(3); //xxx
var hello = 'hello'.repeat(2); //hellohello
</script>
5.4.3、Set数据结构
ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成Set数据结构。
const s = new Set();
Set函数可以接受一个数组作为参数,用来初始化。
const set = new Set([1,2,3,4,5]);
<script>
const s1 = new Set();
console.log(s1.size); //0
const s2 = new Set(['a','b']);
console.log(s2.size); //2
const s3 = new Set(['a','a','b','b']); //2
console.log(s3.size); //2
</script>
实例方法
- add(value):添加某个值,返回Set结构本身
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示该值是否为Set的成员
- clear():清除所有成品,没有返回值
<script>
const s4 = new Set();
// 向set结构中添加值 使用add方法
s4.add('a').add('b');
console.log(s4.size) //2
// 从set结构中删除值 用到的方法是delete
const r1 = s4.delete('c');
console.log(s4.size)
console.log(r1);//1
// 判断某一个值是否是set数据结构中的成员 使用has
const r2 = s4.has('d');
console.log(r2); //false
// 清空set数据结构中的值 使用clear方法
s4.clear();
console.log(s4.size); //0
</script>
5.4.4、Set 遍历
Set结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。
// 遍历set数据结构 从中取值
const s5 = new Set(['a', 'b', 'c']);
s5.forEach(value => {
console.log(value); // a b c
})