【JavaScript学习笔记】

本文详述了JavaScript的学习笔记,涵盖了从基本的语法、数据类型、算术运算,到深入的变量作用域、预解析、对象、DOM和BOM操作。讲解了事件处理、节点操作、事件流、动画实现以及移动端特性。此外,还涉及了对象、函数、DOM操作、事件处理、Web API、存储和浏览器对象模型等方面的知识,是全面掌握JavaScript的宝贵资料。
摘要由CSDN通过智能技术生成

表现形式

行内,内嵌,外部引入。
在html中用双引号,在js中用单引号

  • 行内
 <button onclick="alert('月薪过万')">点击我</button>
  • 内嵌(常用)
<script>
	alert('文字');
</script>
  • 外部引入
<script src="my.js"></script>

输入输出语句

<script>
	//这是一个输入框
	prompt('请输入用户名');
	//alert 弹出警示框 输出的 展示给用户的
	alert('计算的结果是');
	//console 控制台输出 给程序员测试用的
	console.log('hello world');
</script>

变量

  1. 定义变量
<script>
	// 1.声明变量
	var age;
	// 2.赋值
	age = 10;
	// 3.输出结果,控制台输出语法  程序员看的
	console.log(age);
	// 4.变量初始化
	var name = 'lala';
	// 5.输出在页面上的内容
	document.write('<h1>我愿意</h1>')
	// 输入语句 prompt,弹出框
    prompt('您今年多大了?')
</script>
  1. 变量
<script>
	// 1.用户输入姓名 存储到一个myname的变量里面
	var myname = prompt('请输入您的名字')
	// 2.输出这个用户名
	alert(myname)
</script>
  1. 扩展
<script>
	// 1.更新变量
	// 2.声明多个变量
	var age=18,
		address='上海',
		gc=888;
	// 3.声明变量的特殊情况
	// 3.1 只声明不赋值,结果是undefined
	// 3.1 不声明不赋值直接使用某个变量会报错
	// 3.2 不声明就赋值,报错
</script>
  1. 变量命名规范
  • 区分大小写
  • 字母,数字,下划线_,美元符号$组成
  • 不能以数字开头
  • 不能是关键字
  • 变量名必须有意义
  • 驼峰命名法,首字母小写,后面单词首字母大写
  • 翻译网站:有道,爱词霸

数据类型

  1. 数据类型同其他语言相同
    • 八进制:数字前加0
    • 十六进制:数字前加0x
<script>
	alert(Number.MAX_VALUE);// javascript 最大值 1.7976931348623157e+308
	alert(Number.MIN_VALUE);// javascript 最小值 5e-324
	alert(Infinity);//无穷大,大于任何数值
	alert(-Infinity);//无穷小,小于任何数值
	alert(NaN);//代表一个非数值
	console.log(isNAN(12)); // isNAN()判断非数字,并返回一个值,如果是数字,返回false,如果部署数字,返回true
</script>
  1. 变量的数据类型,与其他语言不同之处:
    • 根据等号右边的数据类型进行判断的
    • js是动态语言,数据类型可以变化
<script>
	var x = 10;
	x = 'pink'
</script>
  1. 字符串型 String
    转义符\n
    斜杠\\
    缩进\t
    空格\b
    弹出警示框alert('');外单(引号)内双(引号)
    检测获取字符串长度console.log(str.length);
    字符串拼接console.log('你好' + 'pink' + true + '886');
    不同类型的都可以直接拼接;数字相加,字符串相连;变量和字符串相连:引引加加
<script>
	//弹出一个输入框(prompt),让用户输入年龄(用户输入)
	//把用户输入的值用变量保存起来,把刚才输入的年龄与所要输出的字符串拼接(程序内部处理)
	//使用alert语句弹出警示框(输出结果)
	var age = prompt('请输入您的年龄');
	var str = '您今年已经' + age + '岁了';
	alert(str);
</script>
  1. 布尔型
    false(参加加法运算当0来看) or true(参加加法运算当1来看)
    undefined:未定义。和数字相加,最后结果为NaN,和字符串相加为undefined字符串
    null:空值。和数字相加,最后结果为数字,和字符串相加为null字符串
  2. 获取数据类型:console.log(typeof 变量名);
    prompt 取过来的值是字符型的,
<script>
        // 返回的什么类型  string  number Boolean null
        console.log(typeof 123)// number
        console.log(typeof '123')// string
        console.log(typeof true)//boolean
        console.log(typeof undefined)//undefined
        console.log(typeof null)//object对象
        let num = 10
        console.log(typeof num + '11')
        // console.log('number' + '11'),无法相加
</script>
  1. 数据类型转换
  • 转成字符串
<script>
	// 1.toString()转成字符串
	var num = 10;
	var str = num.toString();
	// 2.string()强制转换
	console.log(String(num));
	// 3.利用 + 拼接字符串的方法实现转换效果
	console.log(num + '');
</script>
  • 转成数字型
<script>
	// 1.parseInt(变量)转成数字型。自动取整,并且去掉单位
	var age = prompt('请输入您的年龄');
	console.log(parseInt(age));
	// 2.parsefloat(变量)转成数字型。去掉单位
	console.log(parseFloat('3.14'));
	// 3.利用Number(变量)
	console.log(Number('12'))
	// 4.利用算术运算 + - * / 隐式转换
	console.log('12' + 16);
</script>

算术运算符

//+ - * / %(取余,取模)
// 浮点数 算术运算里边会有问题,不能直接拿浮点数判断是否相等

arguments使用
可以用于输入变量数量不等的情况
不同作用域下变量名字可以相同

变量

局部变量和全局变量:
全局变量:在全局作用域下声明的变量。

  • 全局变量在代码的任何位置都可以使用
  • 在全局作用域下,var声明的变量是全局变量
  • 在函数内不适用var声明的变量也是全局变量(不建议使用)
  • 全局变量只有浏览器关闭的时候才会销毁,比较占内存资源

局部变量:局部作用域下声明的变量

  • 只能在函数内部使用
  • 在函数内部var声明的变量是局部变量
  • 函数的形参实际上就是局部变量
  • 局部变量是更节省内存变量

js没有块级作用域,js的作用域:全局作用域 局部作用域,js是在ES6的时候新增的块级作用域

作用域链:内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值。

js预解析

  1. js引擎运行js分为两步: 预解析------>代码执行
    (1) 预解析 js引擎会把js里面所有的var还有function提升到当前作用域的最前面
    (2) 代码执行,按照代码书写的顺序从上往下执行
  2. 预解析分为变量预解析和函数预解析
    (1)变量提升就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作
    (2)函数提升 就是把所有的函数声明提升到当前作用域最前面 不调用函数
//经典案例
<script>
	f1();
	console.log(a);
	console.log(b);
	console.log(c);
	function f1() {
		var a = b = c = 9;
		console.log(c);
		console.log(b);
		console.log(a);
	}
//执行过程相当于以下过程:
//预解析,提升声明变量和函数
	function f1() {
		var a;
		a = b = c = 9;
		// 相当于var a = 9; b = 9; c = 9; b和c直接赋值,没有var声明,当全局变量看
		// 集体声明:var a = 9, b = 9, c = 9;
		console.log(a);//9
		console.log(b);//9
		console.log(c);//9
	}
	f1();
	console.log(c);//9
	console.log(b);//9
	console.log(a);//局部变量,报错,变量未被定义
</script>

对象

对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
对象由属性和方法组成。
属性:事物的特征
方法:事物的行为

<script>
// 声明变量
	var obj = {
		uname:'张三',
		age:18,
		sex:'男',
		sayHi:function(){
			console.log('hi~');
		}
	}
	// (1)里面的属性或者方法我们采取键值对的形式 键 属性名 : 值 属性值
	// (2)多个属性或者方法中间用逗号隔开的
	// (3)方法冒号后面跟的是一个匿名函数
	// 2. 使用对象
	// (1).调用对象的属性 我们采取 对象名.属性名
	console.log(obj.uname);
	// (2).调用属性的另外一种方法 对象名['属性名']
	console.log(obj['age']);
</script>

利用 new object创建对象

<script>
	//利用 new object创建对象
	var obj = new Object();//创建一个空对象
	obj.uname = '张丹',
	obj.age = 18;
	obj.sex = '女';
	obj.sayHi = function(){
		console.log('Hi')
	}
	//(1)我们是利用等号赋值的方法 添加对象的属性和方法
	//(2)每个属性和方法之间用分号结束
	console.log(obj.uname);
	console.log(obj['sex']);
	obj.sayHi();
</script>

变量、属性、函数、方法的区别

  1. 变量和属性相同点:都是用来存储数据的
    变量:单独声明并赋值 使用的时候直接写变量名 单独存在
    属性:在对象里面的不需要声明的 使用的时候必须是 对象.属性
  2. 函数和方法的相同点:都是实现某种功能 做某件事
    函数:单独声明并且调用的 函数名() 单独存在的
    方法:在对象里面 调用的时候 对象.方法()

利用构造函数创建对象

  • 构造的函数名字首字母要大写
  • 构造函数不需要return就可以返回结果
  • 调用构造函数必须使用new
  • 我们只要new Star() 调用函数就创建一个对象 ldh {}
  • 我们的属性和方法前面必须添加this
<script>
	/*创建方法*/
	function 构造函数名() {
		this.属性 =;
		this.方法 = function() {}
	}
	new 构造函数名();
	/*创建方法*/
	// 1.构造函数 泛指的某一大类, 它类似于java里面的class
	function Star(uname, age, sex) {
		//相同的属性
		this.name = uname;
		this.age = age;
		this.sex = sex;
		//相同的方法
		this.sing = function(){
			console.log(sang);
		}
	}
	// 2.创建对象 特指 是一个具体的事物
	var ldh = new Star('刘德华',18,'男');
	console.log(ldh.name);
	console.log(ldh.age);
	ldh.sing('冰雨');
	var zxy = new Star('张学友',19,'男');
	console.log(zxy.name);
	console.log(zxy.age);
	//3.我们利用构造函数创建对象的过程我们也称为对象的实例化
</script>

new关键字执行过程:

  1. new构造函数可以在内存中创建一个空对象
  2. this就会指向刚才创建的空对象
  3. 执行构造函数里面的代码 给这个空对象添加属性和方法
  4. 返回这个对象
<script>
	//遍历对象
	var obj = {
		name:'妮妮',
		age:18,
		sex:'女'
	}
	for (var k in obj) {
		console.log(k);//k 变量输出 得到的是 属性名
		console.log(obj[k]);// obj[k] 得到是属性值
	}
	// 我们使用 for in 里面的变量 喜欢用 k 或者 key
</script>

小结:

  • 对象可以让代码结构更清晰
  • 对象复杂数据类型object
  • 本质:对象就是一组无序的相关属性和方法的集合
  • 构造函数泛指某一大类,比如苹果,不管红色苹果还是绿色苹果,都统称为苹果
  • 对象实例特指一个事物,比如这个苹果
  • for in 语句用于对对象的属性进行循环操作

DOM和BOM

Web API

浏览器提供的一套操作浏览器功能和页面元素的API(DOM和BOM)
Web APIs:是JS的应用,大量使用JS基础的课程内容做基础,主要是针对浏览器提供的接口,是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)

API(应用编程接口):是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码或理解内部工作机制的细节。API是给程序员提供的接口,方便实现功能。

DOM

文档对象模型 DOM:W3C组织推荐的处理可扩展标记语言HTML的标准编程接口,可以改变页面样式,内容和结构
文档:document,一个页面就是一个文档
元素:element(页面中所有标签都是元素)
节点:node(网页中所有内容都是节点)
DOM把以上内容都看作是对象

获取元素

获取元素的方法:

  • 根据 ID 获取:document.getElementById('id');
  • 根据标签名获取document.getElementsByTagName('标签名');得到是对象的集合,想要操作里面的元素就需要遍历。
  • 通过 HTML5 新增的方法获取
    1. document.getElementsByClassName(‘类名’);// 根据类名返回元素对象集合
    2. document.querySelector('选择器'); // 根据指定选择器返回第一个元素对象,需要加符号
    3. document.querySelectorAll('选择器'); // 根据指定选择器返回,需要加符号
  • 特殊元素获取
    1. doucumnet.body // 返回body元素对象
    2. document.documentElement // 返回html元素对象
<script>
        // 1.返回的是 获取过来元素对象的集合 以伪数组的形式存储的
        var lis = document.getElementsByTagName('li');
        console.log(lis);
        console.log(lis[0]);

        // 3. 如果页面中只有一个li 返回的还是伪数组的形式 
        // 4. 如果页面中没有这个元素 返回的是空的伪数组的形式
        // 5. element.getElementsByTagName('标签名'); 父元素必须是指定的单个元素
        var ol = document.getElementById('ol');
        console.log(ol.getElementsByTagName('li'));
        
        // 6. getElementsByClassName 根据类名获得某些元素集合
        var boxs = document.getElementsByClassName('box');
        // 7. querySelector 返回指定选择器的第一个元素对象  切记 里面的选择器需要加符号 .box  #nav
        var firstBox = document.querySelector('.box');
        var li = document.querySelector('li');
        // 8. querySelectorAll()返回指定选择器的所有元素对象集合
        var allBox = document.querySelectorAll('#box');
		// 1.获取body 元素
        var bodyEle = document.body;
        // 2.获取html 元素
        var htmlEle = document.documentElement;
</script>
事件

触发响应机制,并执行某些操作

事件三要素:事件源 事件类型 事件处理程序
事件源:事件被触发的对象 谁 对象
事件类型: 如何触发 什么事件 比如鼠标点击 还是鼠标经过 还是键盘按下
事件处理程序:通过一个函数赋值的方式 完成
步骤:

  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 编写事件处理程序(函数赋值)

常见的鼠标事件:
在这里插入图片描述

操作元素*

改变元素内容element.innerText(会去除html标签,同时去掉空格和换行) / element.innerHTML(包含html标签,同时保留空格和换行)
js里面的样式采取驼峰命名法
利用DOM可以操作如下表单元素的属性:type、value、checked、selected、disabled
**样式属性操作:**通过JS修改元素的大小、颜色、位置等样式
element.style :行内样式操作
element.className :类名样式操作,h会直接更改元素的类名,会覆盖原先的类名
js里面的样式采取驼峰命名法
JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高

自定义属性操作:程序员自己添加的属性,称为自定义属性

  1. 获取属性值
    element.属性:获取属性值
    element.getArribute('属性值');
    区别:
    element.属性:获取内置属性值(元素本身自带的属性)
    element.getArribute('属性'):主要获取自定义的属性
  2. 设置属性值
    element.属性 = ‘值’ 设置内置属性值。
    element.setAttribute('属性', '值');

H5自定义属性:规定自定义属性必须以data-开头做为属性名并且赋值
获取H5自定义属性:
兼容性获取 element.getAttribute('data-index');
H5新增element.dataset.index 或者element.dataset['index']

节点操作

获取元素通常使用两种方法,

  1. 利用DOM提供的方法获取元素
  2. 利用节点层级关系获取元素

但是节点操作更简单
界面内所有内容都可以看作是节点。
节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。

  • 元素节点 nodeType 为 1
  • 属性节点 nodeType 为 2
  • 文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)

我们在实际开发中,节点操作主要操作的是元素节点
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。

  • parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
  • 如果指定的节点没有父节点则返回 null

子节点:parentNode.childNodes(标准) ,childNodes 所有的子节点 包含 元素节点 文本节点等等
children 获取所有的子元素节点 也是我们实际开发常用的

<body>
    <ol>
        <li>我是li1</li>
        <li>我是li2</li>
        <li>我是li3</li>
        <li>我是li4</li>
        <li>我是li5</li>
    </ol>
    <script>
        var ol = document.querySelector('ol');
        // 1. firstChild 第一个子节点 不管是文本节点还是元素节点
        console.log(ol.firstChild);
        console.log(ol.lastChild);
        // 2. firstElementChild 返回第一个子元素节点 ie9才支持
        console.log(ol.firstElementChild);
        console.log(ol.lastElementChild);
        // 3. 实际开发的写法  既没有兼容性问题又返回第一个子元素
        console.log(ol.children[0]);
        console.log(ol.children[ol.children.length - 1]);
    </script>
</body>

获取兄弟节点:nextElementSibling 得到下一个兄弟元素节点

<body>
    <div>我是div</div>
    <span>我是span</span>
    <script>
        var div = document.querySelector('div');
        // 1.nextSibling 下一个兄弟节点 包含元素节点或者 文本节点等等
        console.log(div.nextSibling);
        console.log(div.previousSibling);
        // 2. nextElementSibling 得到下一个兄弟元素节点
        console.log(div.nextElementSibling);
        console.log(div.previousElementSibling);
    </script>
</body>

创建节点元素节点:node.appendChild(child)

<body>
    <ul>
        <li>123</li>
    </ul>
    <script>
        // 1. 创建节点元素节点
        var li = document.createElement('li');
        // 2. 添加节点 node.appendChild(child)  node 父级  child 是子级 后面追加元素  类似于数组中的push
        var ul = document.querySelector('ul');
        ul.appendChild(li);
        // 3. 添加节点 node.insertBefore(child, 指定元素);
        var lili = document.createElement('li');
        ul.insertBefore(lili, ul.children[0]);
        // 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素
    </script>
</body>

删除节点: node.removeChild(child)
点击按钮删除元素

<body>
    <button>删除</button>
    <ul>
        <li>熊大</li>
        <li>熊二</li>
        <li>光头强</li>
    </ul>
    <script>
        // 1.获取元素
        var ul = document.querySelector('ul');
        var btn = document.querySelector('button');
        // 2. 删除元素  node.removeChild(child)
        // ul.removeChild(ul.children[0]);
        // 3. 点击按钮依次删除里面的孩子
        btn.onclick = function() {
            if (ul.children.length == 0) {
                this.disabled = true;
            } else {
                ul.removeChild(ul.children[0]);
            }
        }
    </script>
</body>

克隆节点: node.cloneNode();

<body>
    <ul>
        <li>1111</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        // 1. node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
        // 2. node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容
        var lili = ul.children[0].cloneNode(true);
        ul.appendChild(lili);
    </script>
</body>

三种创建元素方式区别*

  • document.write()
  • element.innerHTML
  • document.createElement()

innerHTML拼接字符串非常耗时,采用数组的方式最省时。

  1. document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
  2. innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
  3. innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
  4. createElement() 创建多个元素效率稍低一点点,但是结构更清晰

总结:不同浏览器下,innerHTML 效率要比 creatElement 高

针对DOM核心操作:创建、增、删、改、查、属性操作、事件操作

创建:document.write,innerHTML,createElement
:appendChild,insertBefore
:removeChild
:主要修改dom的元素属性,dom元素的内容、属性、表单的值

  • 修改元素属性: src、href、title等
  • 修改普通元素内容: innerHTML 、innerText
  • 修改表单元素: value、type、disabled等
  • 修改元素样式: style、className

查:主要获取查询dom的元素

  • DOM提供的API 方法: getElementById、getElementsByTagName 古老用法 不太推荐
  • H5提供的新方法: querySelector、querySelectorAll 提倡
  • 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡

属性操作:主要针对于自定义属性

  • setAttribute:设置dom的属性值
  • getAttribute:得到dom的属性值
  • removeAttribute移除属性

事件操作:给元素注册事件,采取 事件源.事件类型 = 事件处理程序
在这里插入图片描述

注册事件(绑定事件)

两种方式:传统方法和方法监听注册方式

传统注册方法:采用on开头的事件onclick,注册事件的唯一性
方法监听注册方式:同一个元素同一个事件可以注册多个监听器,按照注册顺序依次执行。addEventListener()

<body>
    <button>传统注册事件</button>
    <button>方法监听注册事件</button>
    <button>ie9 attachEvent</button>
    <script>
        var btns = document.querySelectorAll('button');
        // 1. 传统方式注册事件
        btns[0].onclick = function() {
            alert('hi');
        }
        btns[0].onclick = function() {
                alert('hao a u');
            }
            // 2. 事件侦听注册事件 addEventListener 
            // (1) 里面的事件类型是字符串 必定加引号 而且不带on
            // (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
        btns[1].addEventListener('click', function() {
            alert(22);
        })
        btns[1].addEventListener('click', function() {
                alert(33);
            })
            // 3. attachEvent ie9以前的版本支持
        btns[2].attachEvent('onclick', function() {
            alert(11);
        })
    </script>
</body>

注册事件兼容性解决方案

function addEventListener(element, eventName, fn) {
      // 判断当前浏览器是否支持 addEventListener 方法
      if (element.addEventListener) {
        element.addEventListener(eventName, fn);  // 第三个参数 默认是false
      } else if (element.attachEvent) {
        element.attachEvent('on' + eventName, fn);
      } else {
        // 相当于 element.onclick = fn;
        element['on' + eventName] = fn;
 } 

兼容性处理原则:首先照顾大多数浏览器,再处理特殊浏览器

删除事件(解绑事件)

传统注册方式:eventTarget.onclick = null;
方法监听注册方式:
eventTarget.removeEventListener(type, listener[, useCapture]);
eventTarget.detachEvent(eventNameWithOn, callback);

<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs = document.querySelectorAll('div');
        divs[0].onclick = function() {
                alert(11);
                // 1. 传统方式删除事件
                divs[0].onclick = null;
            }
            // 2. removeEventListener 删除事件
        divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号
        function fn() {
            alert(22);
            divs[1].removeEventListener('click', fn);
        }
        // 3. detachEvent
        divs[2].attachEvent('onclick', fn1);

        function fn1() {
            alert(33);
            divs[2].detachEvent('onclick', fn1);
        }
    </script>
</body>
DOM事件流

事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
DOM事件流分为三个阶段

  1. 捕获阶段
  2. 当前目标阶段
  3. 冒泡阶段

dom 事件流 三个阶段

  1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
  2. onclick 和 attachEvent(ie) 只能得到冒泡阶段。
  3. 捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段 document -> html -> body -> father -> son
		//3. 捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段  document -> html -> body -> father -> son
        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
            alert('son');
        }, true);
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, true);
		// 4. 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段  son -> father ->body -> html -> document
        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
            alert('son');
        }, false);
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, false);
        document.addEventListener('click', function() {
            alert('document');
        })
事件对象
  1. event 就是一个事件对象 写到我们侦听函数的 小括号里面 当形参来看
  2. 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
  3. 事件对象 是 我们事件的一系列相关数据的集合 跟事件相关的 比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标啊,如果是键盘事件里面就包含的键盘事件的信息 比如 判断用户按下了那个键
  4. 这个事件对象我们可以自己命名 比如 event 、 evt、 e
  5. 事件对象也有兼容性问题 ie678 通过 window.event 兼容性的写法 e = e || window.event;

兼容性写法:

<body>
    <div>123</div>
    <script>
        // 事件对象
        var div = document.querySelector('div');
        div.onclick = function(e) {
                // console.log(e);
                // console.log(window.event);
                e = e || window.event;
                console.log(e);
            }
    </script>
</body>
事件对象阻止默认行为
<body>
    <div>123</div>
    <a href="http://www.baidu.com">百度</a>
    <form action="http://www.baidu.com">
        <input type="submit" value="提交" name="sub">
    </form>
    <script>
        // 常见事件对象的属性和方法
        // 1. 返回事件类型
        var div = document.querySelector('div');
        div.addEventListener('click', fn);
        div.addEventListener('mouseover', fn);
        div.addEventListener('mouseout', fn);

        function fn(e) {
            console.log(e.type);

        }
        // 2. 阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
        var a = document.querySelector('a');
        a.addEventListener('click', function(e) {
                e.preventDefault(); //  dom 标准写法
            })
            // 3. 传统的注册方式
        a.onclick = function(e) {
            // 普通浏览器 e.preventDefault();  方法
            // e.preventDefault();
            // 低版本浏览器 ie678  returnValue  属性
            // e.returnValue;
            // 我们可以利用return false 也能阻止默认行为 没有兼容性问题 特点: return 后面的代码不执行了, 而且只限于传统的注册方式
            return false;
            alert(11);
        }
    </script>
</body>

阻止事件冒泡

e.stopPropagation(); // stop 停止 Propagation 传播,用的更多,不考虑兼容性时用
e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡

<body>
    <div class="father">
        <div class="son">son儿子</div>
    </div>
    <script>
        // 常见事件对象的属性和方法
        // 阻止冒泡  dom 推荐的标准 stopPropagation() 
        var son = document.querySelector('.son');
        son.addEventListener('click', function(e) {
            alert('son');
            e.stopPropagation(); // stop 停止  Propagation 传播
            e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
        }, false);

        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, false);
        document.addEventListener('click', function() {
            alert('document');
        })
    </script>
</body>
事件委托

事件冒泡本身的特性,也会有坏处
原理:不是每个子结点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子结点,
作用:只设置一次DOM程序,提高程序性能

<body>
    <ul>
        <li>知否知否,点我应有弹框在手!</li>
        <li>知否知否,点我应有弹框在手!</li>
        <li>知否知否,点我应有弹框在手!</li>
        <li>知否知否,点我应有弹框在手!</li>
        <li>知否知否,点我应有弹框在手!</li>
    </ul>
    <script>
        // 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
            // alert('知否知否,点我应有弹框在手!');
            // e.target 这个可以得到我们点击的对象
            e.target.style.backgroundColor = 'pink';
        })
    </script>
</body>
鼠标事件
<body>
    我是一段不愿意分享的文字
    <script>
        // 1. contextmenu 我们可以禁用右键菜单
        document.addEventListener('contextmenu', function(e) {
                e.preventDefault();
            })
            // 2. 禁止选中文字 selectstart
        document.addEventListener('selectstart', function(e) {
            e.preventDefault();

        })
    </script>
</body>
鼠标事件对象
<body>
    <script>
        // 鼠标事件对象 MouseEvent
        document.addEventListener('click', function(e) {
            // 1. client 鼠标在可视区的x和y坐标
            console.log(e.clientX);
            console.log(e.clientY);
            console.log('---------------------');

            // 2. page 鼠标在页面文档的x和y坐标
            console.log(e.pageX);
            console.log(e.pageY);
            console.log('---------------------');

            // 3. screen 鼠标在电脑屏幕的x和y坐标
            console.log(e.screenX);
            console.log(e.screenY);

        })
    </script>
</body>
鼠标移动事件

鼠标移动事件:mousemove

<head>
    <style>
        img {
            position: absolute;
            top: 2px;
        }
    </style>
</head>

<body>
    <img src="images/angel.gif" alt="">
    <script>
        var pic = document.querySelector('img');
        document.addEventListener('mousemove', function(e) {
            // 1. mousemove只要我们鼠标移动1px 就会触发这个事件
            // console.log(1);
            // 2.核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 把这个x和y坐标做为图片的top和left 值就可以移动图片
            var x = e.pageX;
            var y = e.pageY;
            console.log('x坐标是' + x, 'y坐标是' + y);
            //3 . 千万不要忘记给left 和top 添加px 单位
            pic.style.left = x - 50 + 'px';
            pic.style.top = y - 40 + 'px';
        });
    </script>
</body>
键盘事件

在这里插入图片描述

<body>
    <script>
        // 常用的键盘事件
        //1. keyup 按键弹起的时候触发 
        // document.onkeyup = function() {
        //         console.log('我弹起了');

        //     }
        document.addEventListener('keyup', function() {
            console.log('我弹起了');
        })
        //3. keypress 按键按下的时候触发  不能识别功能键 比如 ctrl shift 左右箭头啊
        document.addEventListener('keypress', function() {
                console.log('我按下了press');
            })
            //2. keydown 按键按下的时候触发  能识别功能键 比如 ctrl shift 左右箭头啊
        document.addEventListener('keydown', function() {
                console.log('我按下了down');
            })
            // 4. 三个事件的执行顺序  keydown -- keypress -- keyup
    </script>
</body>
键盘事件对象
<body>
    <script>
        // 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
        // 1. 我们的keyup 和keydown事件不区分字母大小写  a 和 A 得到的都是65
        // 2. 我们的keypress 事件 区分字母大小写  a  97 和 A 得到的是65
        document.addEventListener('keyup', function(e) {
            // console.log(e);
            console.log('up:' + e.keyCode);
            // 我们可以利用keycode返回的ASCII码值来判断用户按下了那个键
            if (e.keyCode === 65) {
                alert('您按下的a键');
            } else {
                alert('您没有按下a键')
            }

        })

        document.addEventListener('keypress', function(e) {
            // console.log(e);
            console.log('press:' + e.keyCode);

        })
    </script>
</body>

BOM

BOM:浏览器对象模型,提供了独立于内容而与浏览器窗口进行交互的对象,核心对象为window,访问浏览器的窗口
区别:
DOM:

  • DOM 就是把「文档」当做一个「对象」来看待
  • DOM 的顶级对象是 document
  • DOM 主要学习的是操作页面元素
  • DOM 是 W3C 标准规范

BOM:

  • 把「浏览器」当做一个「对象」来看待
  • BOM 的顶级对象是 window
  • BOM 学习的是浏览器窗口交互的一些对象
  • BOM 是浏览器厂商在各自浏览器上定义的,兼容性较差
窗口加载事件

window.onload = function() {}或者window.addEventListener("load",function(){});或者
document.addEventListener('DOMContentLoaded',function(){})

window.onload 是窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等), 就调用的处理函数。
注意:

  1. 有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为 onload 是等页面内容全部加载完毕,再去执行处理函数。
  2. window.onload 传统注册事件方式 只能写一次,如果有多个,会以最后一个 window.onload 为准。
  3. 如果使用 addEventListener 则没有限制
  • DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。
  • Ie9以上才支持
  • 如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded 事件比较合适。
调整窗口大小事件

window.onresize = function() {}或者window.addEventListener("resize",function(){});

<body>
    <script>
        window.addEventListener('load', function() {
            var div = document.querySelector('div');
            window.addEventListener('resize', function() {
                console.log(window.innerWidth);

                console.log('变化了');
                if (window.innerWidth <= 800) {
                    div.style.display = 'none';
                } else {
                    div.style.display = 'block';
                }

            })
        })
    </script>
    <div></div>
</body>
定时器

window.setTimeout(调用函数, 延时时间);
setTimeout(function() {}, 2000);

  1. 这个window在调用的时候可以省略
  2. 这个延时时间单位是毫秒 但是可以省略,如果省略默认的是0
  3. 这个调用函数可以直接写函数 还可以写 函数名 还有一个写法 ‘函数名()’
  4. 页面中可能有很多的定时器,我们经常给定时器加标识符 (名字)

setTimeout() 这个调用函数我们也称为回调函数 callback
普通函数是按照代码顺序直接调用。
而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数。
简单理解: 回调,就是回头调用的意思。上一件事干完,再回头再调用这个函数。

自动关闭广告:

<body>
    <img src="images/ad.jpg" alt="" class="ad">
    <script>
        var ad = document.querySelector('.ad');
        setTimeout(function() {
            ad.style.display = 'none';
        }, 5000);
    </script>
</body>

清除setTimeout定时器window.clearTimeout(timeoutID)

<body>
    <button>点击停止定时器</button>
    <script>
        var btn = document.querySelector('button');
        var timer = setTimeout(function() {
            console.log('爆炸了');

        }, 5000);
        btn.addEventListener('click', function() {
            clearTimeout(timer);
        })
    </script>
</body>

每隔一定时间就执行一次:window.setInterval(调用函数, 延时时间);

<body>
    <script>
        setInterval(function() {
            console.log('继续输出');
        }, 1000);
        // 2. setTimeout  延时时间到了,就去调用这个回调函数,只调用一次 就结束了这个定时器
        // 3. setInterval  每隔这个延时时间,就去调用这个回调函数,会调用很多次,重复调用这个函数
    </script>
</body>

清除setInterval定时器window.clearInterval(intervalID);

<body>
    <button class="begin">开启定时器</button>
    <button class="stop">停止定时器</button>
    <script>
        var begin = document.querySelector('.begin');
        var stop = document.querySelector('.stop');
        var timer = null; // 全局变量  null是一个空对象
        begin.addEventListener('click', function() {
            timer = setInterval(function() {
                console.log('ni hao ma');

            }, 1000);
        })
        stop.addEventListener('click', function() {
            clearInterval(timer);
        })
    </script>
</body>
this指向
<body>
    <button>点击</button>
    <script>
        // this 指向问题 一般情况下this的最终指向的是那个调用它的对象
        // 1. 全局作用域或者普通函数中this指向全局对象window( 注意定时器里面的this指向window)
        console.log(this);

        function fn() {
            console.log(this);

        }
        window.fn();
        window.setTimeout(function() {
            console.log(this);

        }, 1000);
        // 2. 方法调用中谁调用this指向谁
        var o = {
            sayHi: function() {
                console.log(this); // this指向的是 o 这个对象

            }
        }
        o.sayHi();
        var btn = document.querySelector('button');
        // btn.onclick = function() {
        //     console.log(this); // this指向的是btn这个按钮对象

        // }
        btn.addEventListener('click', function() {
                console.log(this); // this指向的是btn这个按钮对象

            })
            // 3. 构造函数中this指向构造函数的实例
        function Fun() {
            console.log(this); // this 指向的是fun 实例对象

        }
        var fun = new Fun();
    </script>
</body>

JS执行机制

JS是单线程,同一时间只能做一件事
单线程意味着所有任务需要排队,导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
同步和异步:

同步:前一个任务结束再执行下一个任务
异步:同时做多个任务
同步任务和异步任务:

同步任务:都在主线程上执行,形成一个执行栈
异步任务:JS的异步都是通过回调实现的,

一般而言,异步任务有以下三种类型:

  1. 普通事件,如 click、resize 等
  2. 资源加载,如 load、error 等
  3. 定时器,包括 setInterval、setTimeout 等
    异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。

JS执行机制:

  1. 先执行执行栈中的同步任务。
  2. 异步任务(回调函数)放入任务队列中。
  3. 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop)

location对象

window 对象给我们提供了一个 location 属性用于获取或设置窗体的 URL,并且可以用于解析 URL 。 因为这个属性返回的是一个对象,所以我们将这个属性也称为 location 对象。

URL

统一资源定位符 (Uniform Resource Locator, URL) 是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它

URL 的一般语法格式为:

protocol://host[:port]/path/[?query]#fragment http://www.itcast.cn/index.html?name=andy&age=18#link
在这里插入图片描述
location对象的属性:
在这里插入图片描述
location常见方法
在这里插入图片描述

<body>
    <button>点击</button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click', function() {
            // 记录浏览历史,所以可以实现后退功能
            location.assign('http://www.itcast.cn');
            // 不记录浏览历史,所以不可以实现后退功能
            location.replace('http://www.itcast.cn');
            location.reload(true);
        })
    </script>
</body>

navigator 对象

浏览器会根据navigator判断打开的是浏览器页面还是移动端页面
navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。
下面前端代码可以判断用户那个终端打开页面,实现跳转

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
    window.location.href = "";     //手机
 } else {
    window.location.href = "";     //电脑
 }

history对象(在OA办公系统中常用)

window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的 URL。
在这里插入图片描述
前进:

<body>
    <a href="list.html">点击我去往列表页</a>
    <button>前进</button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click', function() {
            // history.forward();
            history.go(1);
        })
    </script>
</body>

后退:

<body>
    <a href="index.html">点击我去往首页</a>
    <button>后退</button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click', function() {
            // history.back();
            history.go(-1);
        })
    </script>
</body>

PC端网页特效

元素偏移量offset

在这里插入图片描述
offset和style区别:

  • offset 可以得到任意样式表中的样式值
  • offset 系列获得的数值是没有单位的
  • offsetWidth 包含padding+border+width
  • offsetWidth 等属性是只读属性,只能获取不能赋值
  • 所以,我们想要获取元素大小位置,用offset更合适
  • style 只能得到行内样式表中的样式值
  • style.width 获得的是带有单位的字符串
  • style.width 获得不包含padding和border 的值
  • style.width 是可读写属性,可以获取也可以赋值
  • 所以,我们想要给元素更改值,则需要用style改变

在这里插入图片描述
获取鼠标距离盒子左右的距离:

  1. 我们在盒子内点击,想要得到鼠标距离盒子左右的距离。
  2. 首先得到鼠标在页面中的坐标(e.pageX, e.pageY)
  3. 其次得到盒子在页面中的距离 ( box.offsetLeft, box.offsetTop)
  4. 用鼠标距离页面的坐标减去盒子在页面中的距离,得到 鼠标在盒子内的坐标
  5. 如果想要移动一下鼠标,就要获取最新的坐标,使用鼠标移动事件 mousemove
<body>
    <div class="box"></div>
    <script>
        // 我们在盒子内点击, 想要得到鼠标距离盒子左右的距离。
        var box = document.querySelector('.box');
        box.addEventListener('mousemove', function(e) {
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            this.innerHTML = 'x坐标是' + x + ' y坐标是' + y;
        })
    </script>
</body>

元素可视区client系列

在这里插入图片描述
client 宽度 和我们offsetWidth 最大的区别就是 不包含边框
在这里插入图片描述

flexible.js分析

立即执行函数:不需要调用,立马就可以自己执行函数
立即执行函数 (function() {})() 或者 (function(){}())

多个立即执行函数一定要有分号结尾分开

<body>
    <script>
        // 1.立即执行函数: 不需要调用,立马能够自己执行的函数
        function fn() {
            console.log(1);
        }
        fn();
        // 2. 写法 也可以传递参数进来
        // 1.(function() {})()    或者  2. (function(){}());
        (function(a, b) {
            console.log(a + b);
            var num = 10;
        })(1, 2); // 第二个小括号可以看做是调用函数
        (function sum(a, b) {
            console.log(a + b);
            var num = 10; // 局部变量
        }(2, 3));
        // 3. 立即执行函数最大的作用就是 独立创建了一个作用域, 里面所有的变量都是局部变量 不会有命名冲突的情况
    </script>
</body>

下面三种情况都会刷新页面都会触发 load 事件。

  1. a标签的超链接
  2. F5或者刷新按钮(强制刷新)
  3. 前进后退按钮

元素滚动scroll系列

scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。
在这里插入图片描述
在这里插入图片描述

三大系列总结

在这里插入图片描述
他们主要用法:

  1. offset系列 经常用于获得元素位置 offsetLeft offsetTop
  2. client 经常用于获取元素大小 clientWidth clientHeight
  3. scroll 经常用于获取滚动距离 scrollTop scrollLeft
  4. 注意页面滚动的距离通过 window.pageXOffset 获得

mouseenter 和mouseover的区别

当鼠标移动到元素上时就会触发 mouseenter 事件,类似 mouseover,它们两者之间的差别是

  1. mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。
  2. mouseenter 只会经过自身盒子触发
  3. 之所以这样,就是因为mouseenter不会冒泡。跟mouseenter搭配 鼠标离开 mouseleave 同样不会冒泡

轮播图(常见网页特效)

功能需求:

  1. 鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮
  2. 动态生成小圆圈,小圆圈排他思想
  3. 点击小圆圈滚动图片
  4. 点击两侧按钮,图片滚动一次
  5. 克隆第一张图片放到最后
  6. 点击右侧按钮, 小圆圈跟随变化
  7. 自动播放功能

节流阀

节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。

返回顶部

滚动窗口至文档中的特定位置。
window.scroll(x, y)
注意,里面的x和y 不跟单位,直接写数字

动画

动画原理:

  1. 获得盒子当前位置
  2. 让盒子在当前位置加上1个移动距离
  3. 利用定时器不断重复这个操作
  4. 加一个结束定时器的条件
  5. 注意此元素需要添加定位, 才能使用element.style.left
<body>
    <div></div>
    <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>
</body>

简单动画函数封装

函数需要传递两个参数:动画对象和移动到的距离
必须加定位才可以设置动画
function animate(obj, target) {}

<body>
    <div></div>
    <span>夏雨荷</span>
    <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>
</body>

给不同的元素记录不同的定时器:
如果多个元素都使用这个动画函数,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)

<body>
    <button>点击夏雨荷才走</button>
    <div></div>
    <span>夏雨荷</span>
    <script>
        // 简单动画函数封装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>
</body>

缓动效果原理:
缓动动画就是让动画速度有所变化,最常见的就是让动画慢下来
思路:

  1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
  2. 核心算法: (目标值 - 现在的位置 ) / 10 做为每次移动的距离 步长
  3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
  4. 注意步长值需要取整
    向上取整:Math.ceil(step),向下取整:Math.floor(step)
<body>
    <button>点击夏雨荷才走</button>
    <span>夏雨荷</span>
    <script>
        // 缓动动画函数封装obj目标对象 target 目标位置
        // 思路:
        // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
        // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
        // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
        function animate(obj, target) {
            // 先清除以前的定时器,只保留当前的一个定时器执行
            clearInterval(obj.timer);
            obj.timer = setInterval(function() {
                // 步长值写到定时器的里面
                //把步长值取整,避免小数
                var step = Math.ceil((target - obj.offsetLeft) / 10);
                if (obj.offsetLeft == target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(obj.timer);
                }
                // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
                obj.style.left = obj.offsetLeft + step + 'px';

            }, 15);
        }
        var span = document.querySelector('span');
        var btn = document.querySelector('button');

        btn.addEventListener('click', function() {
                // 调用函数
                animate(span, 500);
            })
            // 匀速动画 就是 盒子是当前的位置 +  固定的值 10 
            // 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
    </script>

</body>

给动画函数添加回调函数

<body>
    <button class="btn500">点击小乌龟到500</button>
    <button class="btn800">点击小乌龟到800</button>
    <span>小乌龟</span>
    <script>
        // 缓动动画函数封装obj目标对象 target 目标位置
        // 思路:
        // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
        // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
        // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
        function animate(obj, target, callback) {
            // console.log(callback);  callback = function() {}  调用的时候 callback()

            // 先清除以前的定时器,只保留当前的一个定时器执行
            clearInterval(obj.timer);
            obj.timer = setInterval(function() {
                // 步长值写到定时器的里面
                // 把我们步长值改为整数 不要出现小数的问题
                // var step = Math.ceil((target - obj.offsetLeft) / 10);
                var step = (target - obj.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (obj.offsetLeft == target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(obj.timer);
                    // 回调函数写到定时器结束里面
                    if (callback) {
                        // 调用函数
                        callback();
                    }
                }
                // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
                obj.style.left = obj.offsetLeft + step + 'px';

            }, 15);
        }
        var span = document.querySelector('span');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');

        btn500.addEventListener('click', function() {
            // 调用函数
            animate(span, 500);
        })
        btn800.addEventListener('click', function() {
                // 调用函数
                animate(span, 800, function() {
                    // alert('你好吗');
                    span.style.backgroundColor = 'red';
                });
            })
            // 匀速动画 就是 盒子是当前的位置 +  固定的值 10 
            // 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
    </script>
</body>

克隆节点:cloneNode(true):复制子节点
cloneNode(false):不复制子节点

移动端网页特效

触屏事件

touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。
在这里插入图片描述

触摸事件对象

touches:触摸屏幕的手指列表
targetTouches:触摸DOM元素的手指列表(最常用)
如果监听的是DOM函数,两个是一样的。

var div = document.querySelector('div');
div.addEventListener('touchstart',function(e)) {
	console.log(e.targetTouches[0]);//正在触摸元素的第一个手指信息
});

在这里插入图片描述

移动端拖动元素

touchstart、touchmove、touchend 可以实现拖动元素
拖动元素三步曲:
(1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
(2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子
(3) 离开手指 touchend

PC端常见特效

轮播图

可以自动播放图片
手指可以拖动播放轮播图

classList 属性

classList属性是HTML5新增的一个属性,返回元素的类名
添加类:element.classList.add(’类名’);
移除类:element.classList.remove(’类名’);
切换类:element.classList.toggle(’类名’);

click延时解决方案

移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。
解决方案:

  1. 禁用缩放。 浏览器禁用默认的双击缩放行为并且去掉 300ms 的点击延迟。 <meta name="viewport" content="user-scalable=no">

  2. 利用touch事件自己封装这个事件解决 300ms 延迟。

PC端常用开发插件

JS 插件是 js 文件,它遵循一定规范编写,方便程序展示效果,拥有特定功能且方便调用。如轮播图和瀑布流插件。

特点:它一般是为了解决某个问题而专门存在,其功能单一,并且比较小。

fastclick 插件解决 300ms 延迟。 使用延时

GitHub官网地址https://github.com/ftlabs/fastclick

Swiper 插件—解决轮播图中文官网地址: https://www.swiper.com.cn/
superslide插件的使用http://www.superslide2.com/
** iscroll插件的使用**: https://github.com/cubiq/iscroll

PC端常用开发框架

框架: 大而全,一整套解决方案
插件: 小而专一,某个功能的解决方案

前端常用的框架有 BootstrapVueAngularReact 等。既能开发PC端,也能开发移动端
前端常用的移动端插件有 swipersuperslideiscroll等。

Bootstrap:
Bootstrap 是一个简洁、直观、强悍的前端开发框架,它让 web 开发更迅速、简单。
它能开发PC端,也能开发移动端
Bootstrap JS插件使用步骤

  1. 引入相关js 文件
  2. 复制HTML 结构
  3. 修改对应样式
  4. 修改相应JS 参数

本地存储

本地存储特性

  1. 数据存储在用户浏览器中
  2. 设置、读取方便、甚至页面刷新不丢失数据
  3. 容量较大,sessionStorage约5M、localStorage约20M
  4. 只能存储字符串,可以将对象JSON.stringify() 编码后存储
window.sessionStorage
  1. 生命周期为关闭浏览器窗口
  2. 在同一个窗口(页面)下数据可以共享
  3. 以键值对的形式存储使用

存储数据sessionStorage.setItem(key, value)
获取数据sessionStorage.getItem(key)
删除数据sessionStorage.removeItem(key)
删除所有数据sessionStorage.clear()

window.localStorage
  1. 声明周期永久生效,除非手动删除 否则关闭页面也会存在
  2. 可以多窗口(页面)共享(同一浏览器可以共享)
  3. 以键值对的形式存储使用

存储数据localStorage.setItem(key, value)
获取数据localStorage.getItem(key)
删除数据localStorage.removeItem(key)
删除所有数据localStorage.clear()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值