10.常见页面效果、本地存储
大约 17 分钟学习笔记前端基础JavaScript
一、动画
1. 动画的原理
- 获得盒子当前位置
- 让盒子在当前位置加上 1 个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 意此元素需要添加定位, 才能使用 element.style.left
var div = document.querySelector("div");
var timer = setInterval(function () {
	if (div.offsetLeft >= 400) {
		// 停止动画 本质是停止定时器
		clearInterval(timer);
	}
	div.style.left = div.offsetLeft + 1 + "px";
}, 30);2. 动画函数的封装
 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);3. 给不同的对象添加不同的定时器
详情
<!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>
        div {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
        span {
            position: absolute;
            left: 0;
            top: 200px;
            display: block;
            width: 150px;
            height: 150px;
            background-color: purple;
        }
    </style>
</head>
<body>
    <button>点击夏雨荷才走</button>
    <div></div>
    <span>夏雨荷</span>
    <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>
</body>
</html>案例 --- 滑动动画原理
详情
<!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>
			div {
				position: absolute;
				left: 0;
				width: 100px;
				height: 100px;
				background-color: pink;
			}
			span {
				position: absolute;
				left: 0;
				top: 200px;
				display: block;
				width: 150px;
				height: 150px;
				background-color: purple;
			}
		</style>
	</head>
	<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 = (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>
</html>案例 --- 缓动动画(多个值之间移动)
详情
<!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>
			div {
				position: absolute;
				left: 0;
				width: 100px;
				height: 100px;
				background-color: pink;
			}
			span {
				position: absolute;
				left: 0;
				top: 200px;
				display: block;
				width: 150px;
				height: 150px;
				background-color: purple;
			}
		</style>
	</head>
	<body>
		<button class="btn500">点击夏雨荷到500</button>
		<button class="btn800">点击夏雨荷到800</button>
		<span>夏雨荷</span>
		<script>
			// 缓动动画函数封装obj目标对象 target 目标位置
			// 思路:
			// 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
			// 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
			// 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
			function animate(obj, target) {
				// 先清除以前的定时器,只保留当前的一个定时器执行
				clearInterval(obj.timer);
				obj.timer = setInterval(function() {
					// 步长值写到定时器的里面
					// 把我们步长值改为整数 Math.ceil往上取整 不要出现小数的问题
					// var step = Math.ceil((target - obj.offsetLeft) / 10);
					var step = (target - obj.offsetLeft) / 10;
                    // 如果 step 大于0,则往上取整,否则就往下 取整
					step = step > 0 ? Math.ceil(step) : Math.floor(step);
					if (obj.offsetLeft == target) {
						// 停止动画 本质是停止定时器
						clearInterval(obj.timer);
					}
					// 把每次加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);
			})
			// 匀速动画 就是 盒子是当前的位置 +  固定的值 10
			// 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
		</script>
	</body>
</html>案例 --- 缓动动画(回调函数)
详情
<!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>
        div {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
        span {
            position: absolute;
            left: 0;
            top: 200px;
            display: block;
            width: 150px;
            height: 150px;
            background-color: purple;
        }
    </style>
</head>
<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 大于0,则往上取整,否则就往下 取整
                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>
</html>案例 --- 封装动画函数及引用
详情
<!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>
        .sliderbar {
            position: fixed;
            right: 0;
            bottom: 100px;
            width: 40px;
            height: 40px;
            text-align: center;
            line-height: 40px;
            cursor: pointer;
            color: #fff;
        }
        .con {
            position: absolute;
            left: 0;
            top: 0;
            width: 200px;
            height: 40px;
            background-color: purple;
            z-index: -1;
        }
    </style>
    <script src="animate.js"></script>
</head>
<body>
    <div class="sliderbar">
        <span>←</span>
        <div class="con">问题反馈</div>
    </div>
    <script>
        // 1. 获取元素
        var sliderbar = document.querySelector('.sliderbar');
        var con = document.querySelector('.con');
        // 当我们鼠标经过 sliderbar 就会让 con这个盒子滑动到左侧
        // 当我们鼠标离开 sliderbar 就会让 con这个盒子滑动到右侧
        sliderbar.addEventListener('mouseenter', function() {
            // animate(obj, target, callback);
            animate(con, -160, function() {
                // 当我们动画执行完毕,就把 ← 改为 →
                sliderbar.children[0].innerHTML = '→';
            });
        })
        sliderbar.addEventListener('mouseleave', function() {
            // animate(obj, target, callback);
            animate(con, 0, function() {
                sliderbar.children[0].innerHTML = '←';
            });
        })
    </script>
</body>
</html>详情
// animate.js
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();
			// }
			callback && callback();
		}
		// 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
		obj.style.left = obj.offsetLeft + step + "px";
	}, 15);
}案例 --- 轮播图
HTML
  <div class="banner">
      <div class="left_button banner_button"><a href="javascript:;"></a></div>
      <div class="right_button banner_button"><a href="javascript:;"></a></div>
      <div class="steta">
          <ul>
          </ul>
      </div>
      <div class="img">
          <ul>
              <li><a href="javascript:"><img src="https://img.pupper.cn/img/202112101605182.jpg"></a></li>
              <li><a href="javascript:;"><img src="https://img.pupper.cn/img/202112101605097.jpg"></a></li>
              <li><a href="javascript:;"><img src="https://img.pupper.cn/img/202112101605471.jpg"></a></li>
              <li><a href="javascript:;"><img src="https://img.pupper.cn/img/202112101606060.jpg"></a></li>
          </ul>
      </div>
</div>CSS
* {
	padding: 0;
	margin: 0;
}
li {
	list-style: none;
}
a {
	text-decoration: none;
	color: #050505;
}
@font-face {
	font-family: "iconfont";
	/* Project id 2303857 */
	src: url("//at.alicdn.com/t/font_2303857_w55dl274uko.woff2?t=1640252281330")
			format("woff2"), url("//at.alicdn.com/t/font_2303857_w55dl274uko.woff?t=1640252281330")
			format("woff"),
		url("//at.alicdn.com/t/font_2303857_w55dl274uko.ttf?t=1640252281330") format("truetype");
}
.banner {
	position: relative;
	margin: 50px auto;
	border: 1px solid #ccc;
	width: 500px;
	height: 400px;
	overflow: hidden;
}
.banner_button {
	display: none;
	position: absolute;
	font-family: "iconfont";
	top: 50%;
	background: rgba(208, 208, 208, 0.5);
	width: 30px;
	height: 30px;
	line-height: 30px;
	text-align: center;
	transform: translate(0, -50%);
}
.left_button {
	left: 0px;
}
.right_button {
	right: 0px;
}
.steta ul {
	position: absolute;
	top: 93%;
	left: 50%;
	transform: translate(-50%, -50%);
	height: 30px;
	line-height: 30px;
	text-align: center;
}
.steta ul li {
	float: left;
	width: 15px;
	height: 15px;
	border-radius: 50%;
	margin: 0 10px;
	border: 1px solid #ffffff;
}
.colorr {
	background-color: #ffffff;
}
.img {
	position: absolute;
	width: 3000px;
	z-index: -1;
}
.img li {
	float: left;
	width: 500px;
	height: 400px;
}
.img img {
	width: 100%;
	height: 100%;
}JavaScript
var banner = document.querySelector('.banner');
var lb = document.querySelector('.left_button');
var rb = document.querySelector('.right_button');
var img = document.querySelector('.img');
var steta_ul = document.querySelector('.steta').querySelector('ul');
// 图片和小圆点 标识符(以 下标 为参照物)
var num = 0;
// 所有图片
var img_ul = img.querySelector('ul');
// 单个图片的宽度
var img_li_wdith = img_ul.children[0].offsetWidth;
// 鼠标经过 左右按钮显示
banner.addEventListener('mouseenter', function() {
    lb.style.display = 'block';
    rb.style.display = 'block';
    // 清除 自动播放定时器
    clearInterval(timer);
    timer = null;	// 清除定时器变量
})
// 鼠标离开,按钮隐藏
banner.addEventListener('mouseleave', function() {
    lb.style.display = 'none';
    rb.style.display = 'none';
    // 重新添加定时器
    timer = setInterval(function () {
        // 手动调用 点击事件
        rb.click();
    }, 2000);
})
// 根据图片数量添加小圆点
for (var i = 0; i < img_ul.children.length; i++) {
    // 先创建元素,在添加元素
    var li = document.createElement('li');
    // 给元素设置自定义属性,记录索引号
    li.setAttribute('index', i)
    steta_ul.appendChild(li);
    // 小圆圈变色
    li.addEventListener('click', function(){
        // 清除所有小圆圈的颜色
        for (var j = 0; j < steta_ul.children.length; j++) {
            steta_ul.children[j].className = '';
        }
        // 给点击的小圆圈变色(增加类)
        this.className = 'colorr';
        // 点击小圆圈,变更图片
        // 获取 点击圆圈的 index 属性
        var index = this.getAttribute('index');
        // 防止 图片切换错乱
        num = index;
        // 调用 移动函数
        animate(img, -img_li_wdith * index)
    })
}
// 默认显示第一个小圆点
steta_ul.children[0].className = 'colorr';
// 克隆 第一个图片 添加到最后,做无缝转换
//  小圆点已添加完成,克隆图片不会影响 小圆点的数量
var clone_li = img_ul.children[0].cloneNode(true);
img.querySelector('ul').appendChild(clone_li);
// 节流阀(防止多次重复点击)
var flag = true;
// 点击 左右按钮,图片移动(根据 num 值判断)
rb.addEventListener('click', function () {
    if (flag) {
        flag = false;    // 关闭节流阀
        // 无缝衔接
        if (num == img_ul.children.length - 1) {
            img.style.left = 0 + 'px';
            num = 0;
        }
        // 根据 num 值 更变图片
        num++;
        animate(img, -img_li_wdith * num, function () {
            flag = true;	// 动作完成后,打开节流阀
        });
        // 小圆点 跟随 图片 变化
        circleChange();
    }
})
lb.addEventListener('click', function () {
    if (flag){
        flag = false;
        if (num == 0) {
            num = img_ul.children.length - 1;
            img.style.left = -img_li_wdith * (img_ul.children.length - 1) + 'px';
        }
        num--;
        animate(img, -img_li_wdith * num, function(){
            flag = true;
        });
        // 小圆点 跟随 图片 变化
        circleChange();
    }
})
// 自动播放轮播图
var timer = setInterval(function (){
    // 手动调用 点击事件
    rb.click();
},2000)
// 封装 小圆点移动函数
function circleChange() {
    // 清除 所有圆点的 样式
    for (var j = 0; j < steta_ul.children.length; j++) {
        steta_ul.children[j].className = '';
    }
    // 对 操作的圆点 添加 样式
    if (num === img_ul.children.length - 1) {
        // 无缝衔接时,改变第一个圆点样式
        steta_ul.children[0].className = 'colorr';
    } else {
        steta_ul.children[num].className = 'colorr';
    }
}
// 封装 移动函数
function animate(obj, target, callback) {
    // 先清除以前的定时器,只保留当前的一个定时器执行
    clearInterval(obj.timer);
    obj.timer = setInterval(function() {
        // 步长值写到定时器的里面
        // 把我们步长值改为整数 不要出现小数的问题
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            // 停止动画 本质是停止定时器
            clearInterval(obj.timer);
            // 回调函数写到定时器结束里面
            callback && callback();
        }
        // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15);
}案例 --- 返回页面某个位置
详情
<!DOCTYPE html>
<html>
<head lang="en">
	<meta charset="UTF-8">
	<title></title>
	<style>
		* {
			padding: 0px;
			margin: 0px;
		}
		.demo {
			/* position: relative; */
			margin: 5px auto;
			width: 600px;
		}
		.handr {
			width: 100%;
			height: 100px;
			background-color: aquamarine;
		}
		.banner {
			width: 100%;
			height: 500px;
			margin-top: 10px;
			background-color: chocolate;
		}
		.bodyr {
			width: 100%;
			height: 800px;
			margin-top: 10px;
			background-color: #00A4FF;
		}
		.loos {
			position: absolute;
			right: 35px;
			top: 200px;
			width: 50px;
			height: 100px;
			background-color: chartreuse;
		}
		.loos span {
			display: none;
		}
	</style>
</head>
<body>
	<div class="demo">
		<div class="handr"></div>
		<div class="banner"></div>
		<div class="bodyr"></div>
		<div class="loos">
			<span>返回顶部</span>
		</div>
	</div>
	<script>
		var loos = document.querySelector('.loos')
		var banner = document.querySelector('.banner')
		var bodyr = document.querySelector('.bodyr')
		var span = loos.querySelector('span')
		// banner 距离页面顶部的高度
		var bannertop = banner.offsetTop
		// 返回块 停止的位置
		var loostop = loos.offsetTop - bannertop
		// body 距离页面顶部的高度
		var bodyrtop = bodyr.offsetTop;
		// 页面滚动事件
		document.addEventListener('scroll', function () {
			if (window.pageYOffset >= bannertop) {
				// 固定定位 是以 浏览器可视区域为参考的
				// 绝对定位 是以 有定位的父元素 为参考的
				loos.style.position = 'fixed';
				loos.style.top = loostop + 'px';
			} else {
				loos.style.position = 'absolute';
				loos.style.top = '200px';
			}
			if (window.pageYOffset >= bodyrtop) {
				span.style.display = 'block'
			} else {
				span.style.display = 'none'
			}
		})
		span.addEventListener('click', function () {
			// window.scroll(0, 0);
			animate(window, 0);
		})
		// 封装 移动函数
			function animate(obj, target, callback) {
				// 先清除以前的定时器,只保留当前的一个定时器执行
				clearInterval(obj.timer);
				obj.timer = setInterval(function () {
					// 步长值写到定时器的里面
					// 把我们步长值改为整数 不要出现小数的问题
					var step = (target - window.pageYOffset) / 10;
					step = step > 0 ? Math.ceil(step) : Math.floor(step);
					if (window.pageYOffset == target) {
						// 停止动画 本质是停止定时器
						clearInterval(obj.timer);
						// 回调函数写到定时器结束里面
						callback && callback();
					}
					// 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
					window.scroll(0, window.pageYOffset + step);
				}, 15);
			}
	</script>
</body>
</html>封装 移动函数(上下移动)
// 封装 移动函数(上下移动)
function animate(obj, target, callback) {
	// 先清除以前的定时器,只保留当前的一个定时器执行
	clearInterval(obj.timer);
	obj.timer = setInterval(function () {
		// 步长值写到定时器的里面
		// 把我们步长值改为整数 不要出现小数的问题
		var step = (target - window.pageYOffset) / 10;
		step = step > 0 ? Math.ceil(step) : Math.floor(step);
		if (window.pageYOffset == target) {
			// 停止动画 本质是停止定时器
			clearInterval(obj.timer);
			// 回调函数写到定时器结束里面
			callback && callback();
		}
		// 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
		window.scroll(0, window.pageYOffset + step);
	}, 15);
}案例 --- 动态导航背景
详情
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		* {
			padding: 0;
			margin: 0;
		}
		ul {
			list-style: none;
		}
		a {
			text-decoration: none;
			color: #333;
		}
		body {
			background-color: black;
		}
		.demo {
			position: relative;
			width: 900px;
			height: 42px;
			margin: 50px auto;
			background: #fff url(https://img.pupper.cn/img/202201041615500.png) no-repeat right center;
			border-radius: 5px;
		}
		.cloud {
			position: absolute;
			top: 0;
			left: 0;
			width: 83px;
			height: 42px;
			background: url(https://img.pupper.cn/img/202201041616469.gif) no-repeat;
		}
		.demo ul {
			position: absolute;
		}
		.demo li {
			float: left;
			width: 83px;
			line-height: 42px;
			text-align: center;
		}
		.demo a {
			display: inline-block;
			height: 42px;
		}
		.demo ul li a:hover {
			color: #fff;
		}
	</style>
	<script>
		window.addEventListener ('load', function(){
			var cloud = document.querySelector('.cloud');
			var lis = document.querySelector('.demo').querySelectorAll('li');
			// span 起始位置
			var start = 0;
			// 给所有 li 绑定事件
			for (var i = 0; i < lis.length; i++){
				// 鼠标经过,把当前 li 作为目标值
				lis[i].addEventListener('mouseenter', function(){
					animate(cloud, this.offsetLeft);
				});
				// 鼠标离开,把 0 作为目标值
				lis[i].addEventListener('mouseleave', function () {
					animate(cloud, start);
				});
				// 鼠标点击,把当前位置作为目标值
				lis[i].addEventListener('click', function () {
					animate(cloud, this.offsetLeft);
					start = this.offsetLeft;
				});
			}
			// 封装 移动函数
			function animate(obj, target, callback) {
				clearInterval(obj.timer);
				obj.timer = setInterval(function () {
					var step = (target - obj.offsetLeft) / 10;
					step = step > 0 ? Math.ceil(step) : Math.floor(step);
					if (obj.offsetLeft == target) {
						clearInterval(obj.timer);
						callback && callback();
					}
					obj.style.left = obj.offsetLeft + step + 'px';
				}, 15);
			}
		})
	</script>
</head>
<body>
	<div class="demo">
		<span class="cloud"></span>
		<ul>
			<li class="current"> <a href="#">首页新闻</a> </li>
			<li> <a href="#">师资力量</a> </li>
			<li> <a href="#">活动策划</a> </li>
			<li> <a href="#">企业文化</a> </li>
			<li> <a href="#">招聘信息</a> </li>
			<li> <a href="#">公司简介</a> </li>
			<li> <a href="#">你是佩奇</a> </li>
			<li> <a href="#">啥是乔治</a> </li>
		</ul>
	</div>
</body>
</html>二、 本地存储
1. window.sessionStorage
存储数据
sessionStorage.setItem(key, value);获取数据
sessionStorage.getItem(key);删除数据
sessionStorage.removeItem(key);清空所有数据
sessionStorage.clear();特点:
- 生命周期为关闭浏览器窗口
- 在同一页面下,数据可以共享
- 以键值对的形式存储
<div class="demo">
	<input type="text" />
	<button class="set">存储数据</button>
	<button class="get">获取数据</button>
	<button class="remove">删除数据</button>
	<button class="clear">清空所有数据</button>
</div>
<script>
	var inp = document.querySelector("input");
	var set = document.querySelector(".set");
	var get = document.querySelector(".get");
	var rem = document.querySelector(".remove");
	var clear = document.querySelector(".clear");
	set.addEventListener("click", function () {
		var val = inp.value;
		sessionStorage.setItem("uname", val);
	});
	get.addEventListener("click", function () {
		inp.value = sessionStorage.getItem("uname");
	});
	rem.addEventListener("click", function () {
		inp.value = sessionStorage.removeItem("uname");
	});
	clear.addEventListener("click", function () {
		inp.value = sessionStorage.clear();
	});
</script>2. window.localStorage
存储数据
localStorage.setItem(key, value);获取数据
localStorage.getItem(key);删除数据
localStorage.removeItem(key);清空所有数据
localStorage.clear();特点:
- 生命周期永久生效,除非手动删除,否则关闭页面也会存在
- 可以多页面共享(同一浏览器)
- 以键值对的形式存储使用
案例 --- 记住用户名
<div class="demo">
    <input type="text" id="uname">
    <input type="checkbox" id="setUname">记住用户名
</div>
<script>
    var uname = document.querySelector('#uname');
    var cb= document.querySelector('#setUname');
    // 如果有用户名数据,就显示,复选框勾选
    if(localStorage.getItem('uname')){
        uname.value = localStorage.getItem('uname');
        cb.checked = true;
    }
    // 根据复选框状态改变,选择保存数据还是删除数据
    cb.addEventListener('change', function(){
        if(cb.checked){
            var val = uname.value;
            localStorage.setItem('uname', val);
        }else{
            localStorage.removeItem('uname');
        }
    })
</script>