三、M端事件
<!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>M端事件</title><style>div {width: 300px;height: 300px;background-color: pink;}</style>
</head><body><div></div><script>// 只有移动端才有效果const div = document.querySelector('div')// 1. 触摸div.addEventListener('touchstart', function () {console.log('开始触摸了')})// 2. 离开div.addEventListener('touchend', function () {console.log('离开了')})// 3. 移动div.addEventListener('touchmove', function () {console.log('移动')})</script>
</body></html>
四、JS插件
在M端做轮播图非常麻烦,为了节省事件,我们一般都是用的JS插件去完成
然后直接在demos 里面打开序号30 的就可以了
样式复制完就复制结构,然后再复制js
<!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>移动端轮播图</title><link rel="stylesheet" href="./css/swiper.min.css"><style>.box {position: relative;width: 800px;height: 300px;background-color: pink;margin: 100px auto;}html,body {position: relative;height: 100%;}body {background: #eee;font-family: Helvetica Neue, Helvetica, Arial, sans-serif;font-size: 14px;color: #000;margin: 0;padding: 0;}.swiper {/* 让它不超出 */overflow: hidden;width: 100%;height: 100%;}.swiper-slide {text-align: center;font-size: 18px;background: #fff;/* Center slide text vertically */display: -webkit-box;display: -ms-flexbox;display: -webkit-flex;display: flex;-webkit-box-pack: center;-ms-flex-pack: center;-webkit-justify-content: center;justify-content: center;-webkit-box-align: center;-ms-flex-align: center;-webkit-align-items: center;align-items: center;}.swiper-slide img {display: block;width: 100%;height: 100%;object-fit: cover;}</style>
</head><body><div class="box"><!-- 结构一定要放到box里面去因为我们轮播图就要box这么大 --><!-- Swiper --><div class="swiper mySwiper"><div class="swiper-wrapper"><div class="swiper-slide">Slide 1</div><div class="swiper-slide">Slide 2</div><div class="swiper-slide">Slide 3</div><div class="swiper-slide">Slide 4</div><div class="swiper-slide">Slide 5</div><div class="swiper-slide">Slide 6</div><div class="swiper-slide">Slide 7</div><div class="swiper-slide">Slide 8</div><div class="swiper-slide">Slide 9</div></div><div class="swiper-pagination"></div></div></div><!-- 引入js --><script src="./js/swiper.min.js"></script><!-- 调用js --><!-- Initialize Swiper --><script>// new swiper 实例化var swiper = new Swiper(".mySwiper", {// 小圆点pagination: {el: ".swiper-pagination",},// 自动播放autoplay: {delay: 1000,//1秒切换一次disableOnInteraction: false, //鼠标点击 触摸之后,自动继续播放},// 可以键盘控制swiperkeyboard: {enabled: true,onlyInViewport: true,},});</script><!-- 我们想要给它添加一个自动播放效果 -->
</body></html>
游乐园案例
第一步引入,一定要将min.js,min.css放在游乐园(FC)的目录下,不能乱放。
复制过来的css代码就不放index.css里面了,直接放在这里,如果要放也是放在less里面,index.css是通过less来写的。把结构复制粘贴到banner盒子里面去。js一定要放在引用的swiper下面,因为这样才能实例化。
小圆点是可以改变掉的,我们可以直接覆盖掉前面的。
发现选中的小圆点颜色也被覆盖掉了。
滑动最后一张轮播图的时候发现有回弹效果
<!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>游乐园移动端</title><!-- 引入favicon图标 --><link rel="shortcut icon" href="favicon.ico" type="image/x-icon"><!-- 引入字体图标 --><link rel="stylesheet" href="./lib/iconfont/iconfont.css"><!-- 引入index.css --><link rel="stylesheet" href="./css/index.css"><link rel="stylesheet" href="./css/swiper.min.css"><style>/* 复制过来的css代码就不放index.css里面了,直接放在这里,如果要放也是放在less里面,index.css是通过less来写的 */html,body {position: relative;height: 100%;}body {background: #eee;font-family: Helvetica Neue, Helvetica, Arial, sans-serif;font-size: 14px;color: #000;margin: 0;padding: 0;}.swiper-container {width: 100%;height: 100%;}.swiper-slide {text-align: center;font-size: 18px;background: #fff;/* Center slide text vertically */display: -webkit-box;display: -ms-flexbox;display: -webkit-flex;display: flex;-webkit-box-pack: center;-ms-flex-pack: center;-webkit-justify-content: center;justify-content: center;-webkit-box-align: center;-ms-flex-align: center;-webkit-align-items: center;align-items: center;}/* 小圆点是可以改变掉的,我们可以直接覆盖掉前面的 */.swiper-pagination-bullet {background: #fff;opacity: .8;}/* 发现高亮也被覆盖掉了 */.swiper-pagination-bullet-active {background: pink;}</style>
</head><body><!-- 页面主体部分 --><div class="main"><!-- 轮播图模块 --><div class="banner"><!-- <ul><li><a href="#"><img src="./uploads/banner_1.png" alt=""></a></li></ul> --><!-- 轮播图模块 --><!-- Swiper --><div class="swiper-container"><div class="swiper-wrapper"><div class="swiper-slide"><!-- 这个已经给我们做了定制,有几张图片就会给我们生成几个小圆点,跟bootstrap不一样,bootstrap的小圆点要跟着一起改变 --><a href="#"><img src="./uploads/banner_1.png" alt=""></a></div><div class="swiper-slide"><a href="#"><img src="./uploads/banner_1.png" alt=""></a></div><div class="swiper-slide"><a href="#"><img src="./uploads/banner_1.png" alt=""></a></div><div class="swiper-slide"><a href="#"><img src="./uploads/banner_1.png" alt=""></a></div><div class="swiper-slide"><a href="#"><img src="./uploads/banner_1.png" alt=""></a></div></div><!-- Add Pagination --><div class="swiper-pagination"></div></div></div><!-- 标题模块 --><div class="title"><h4>乐园活动</h4></div><!-- 活动项目模块 --><div class="item"><!-- 图片模块 --><div class="pic"><!-- 图片 --><a href="#"><img src="./uploads/item_2.png" alt=""></a><!-- 进行模块 --><div class="status">进行中</div><!-- 收藏 --><div class="collect"><i class="iconfont icon-shoucang1"></i></div></div><!-- 信息模块 --><div class="info"><h5>疯狂的红包 不一样的撕名牌 大型家庭亲子户外活动</h5><div class="rest"><span><i class="iconfont icon-qizhi"></i>200人报名</span><span><i class="iconfont icon-shizhong"></i>本周六开始</span></div></div></div><!-- 活动项目模块 --><div class="item"><!-- 图片模块 --><div class="pic"><!-- 图片 --><a href="#"><img src="./uploads/item_2.png" alt=""></a><!-- 进行模块 --><div class="status">进行中</div><!-- 收藏 --><div class="collect"><i class="iconfont icon-shoucang1"></i></div></div><!-- 信息模块 --><div class="info"><h5>疯狂的红包 不一样的撕名牌 大型家庭亲子户外活动</h5><div class="rest"><span><i class="iconfont icon-qizhi"></i>200人报名</span><span><i class="iconfont icon-shizhong"></i>本周六开始</span></div></div></div><!-- 活动项目模块 --><div class="item"><!-- 图片模块 --><div class="pic"><!-- 图片 --><a href="#"><img src="./uploads/item_2.png" alt=""></a><!-- 进行模块 --><div class="status">进行中</div><!-- 收藏 --><div class="collect"><i class="iconfont icon-shoucang1"></i></div></div><!-- 信息模块 --><div class="info"><h5>疯狂的红包 不一样的撕名牌 大型家庭亲子户外活动</h5><div class="rest"><span><i class="iconfont icon-qizhi"></i>200人报名</span><span><i class="iconfont icon-shizhong"></i>本周六开始</span></div></div></div><!-- 活动项目模块 --><div class="item"><!-- 图片模块 --><div class="pic"><!-- 图片 --><a href="#"><img src="./uploads/item_2.png" alt=""></a><!-- 进行模块 --><div class="status">进行中</div><!-- 收藏 --><div class="collect"><i class="iconfont icon-shoucang1"></i></div></div><!-- 信息模块 --><div class="info"><h5>疯狂的红包 不一样的撕名牌 大型家庭亲子户外活动</h5><div class="rest"><span><i class="iconfont icon-qizhi"></i>200人报名</span><span><i class="iconfont icon-shizhong"></i>本周六开始</span></div></div></div></div><!-- 底部盒子 --><footer class="toolbar"><a href="#" class="active"><i class="iconfont icon-index-copy"></i><span>首页</span></a><a href="#"><i class="iconfont icon-youhuiquan"></i><span>卡卷</span></a><a href="#"><i class="iconfont icon-index-copy"></i><span>首页</span></a></footer><!-- 引入js文件 --><script src="./js/flexible.js"></script><script src="./js/swiper.min.js"></script><!-- Initialize Swiper --><script>var swiper = new Swiper('.swiper-container', {pagination: {el: '.swiper-pagination',},autoplay: {delay: 3000,//3秒切换一次},});</script>
</body></html>
五、综合案例
这个案例主要练习的是对数据的操作,虽然频繁地去渲染会耗费性能,但是这种开发我们最后都不是用的dom去开发,而是vue,它就没有这种性能问题。
tbody.appendChild(tr) 因为它是后追加,所以它是数组原来有几条数据,就把几条数据渲染出来,再在原来的基础上往上面放,就会出现下面重复渲染之前的数据的情况。为了解决这样的问题,我们应该把tbody里面的数据清空之后再渲染数据。
删除不是删除的dom元素,而是数组里面的数据。有可能数据很多,所以考虑用事件委托来做,就不用把所有的小a获取过来了。td,tr都很多,再往上找所以事件委托给tbody,tbody只有一个
非空判断:
表单你想要拿数据,必须要有name,这5个表单的特点是就它们有name,其他的标签都没有name属性。
把所有带有name属性的表单获取过来,是一个数组。然后我们挨个遍历,只要有一个它的value值为空,我们就返回错误,中断这次录入。
中断的关键字是return。因为我们的submit是在一个函数里面的,return是退出函数,一退出函数就不再执行了,所以它退出的是函数。
别一点击就开始判断了,按道理一点击应该先阻止默认行为再进行判断。只要几个表单有一个的值为空都不让通过。
写在创建对象的前面,阻止默认行为的后面。
<!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>学生信息管理</title><link rel="stylesheet" href="css/index.css" />
</head><body><h1>新增学员</h1><form class="info" autocomplete="off">姓名:<input type="text" class="uname" name="uname" />年龄:<input type="text" class="age" name="age" />性别:<select name="gender" class="gender"><option value="男">男</option><option value="女">女</option></select>薪资:<input type="text" class="salary" name="salary" />就业城市:<select name="city" class="city"><option value="北京">北京</option><option value="上海">上海</option><option value="广州">广州</option><option value="深圳">深圳</option><option value="曹县">曹县</option></select><button class="add">录入</button></form><h1>就业榜</h1><table><thead><tr><th>学号</th><th>姓名</th><th>年龄</th><th>性别</th><th>薪资</th><th>就业城市</th><th>操作</th></tr></thead><!-- 追加是爸爸追加孩子 追加行就是追加给tbody --><tbody><!-- <tr><td>1001</td><td>欧阳霸天</td><td>19</td><td>男</td><td>15000</td><td>上海</td><td><a href="javascript:">删除</a></td></tr> --></tbody></table><script>// 获取元素const uname = document.querySelector('.uname')const age = document.querySelector('.age')const gender = document.querySelector('.gender')const salary = document.querySelector('.salary')const city = document.querySelector('.city')// 获取tbody元素 标签不需要加.const tbody = document.querySelector('tbody')// 声明一个空的数组, 增加和删除都是对这个数组进行操作const arr = []// 1. 录入模块// 1.1 表单提交事件const info = document.querySelector('.info')// 是提交事件而不是点击事件// 表单有两个按钮,一个提交按钮,一个重置按钮 submit resetinfo.addEventListener('submit', function (e) {// 当点击录入之后,会默认跳转,显示不了打印的内容// 阻止默认行为 不跳转e.preventDefault()// console.log(11)// 非空判断// 这里进行表单验证 如果不通过,直接中断,不需要添加数据// 获取所有带有name属性的元素const items = document.querySelectorAll('[name]')// 一点击就开始遍历循环for (let i = 0; i < items.length; i++) {if (items[i].value === '') {return alert('输入内容不能为空')}}// 点击录入之后我们就可以拿到这些值,拿到值之后就可以把它以对象的形式存到数组里面去// 创建新的对象const obj = {// 序号与数组的长度有关stuId: arr.length + 1,// 第一个uname指的是属性名,第二个uname指的是表单的值,刚好两者的名字一样而已uname: uname.value,age: age.value,gender: gender.value,salary: salary.value,city: city.value}// console.log(obj)// 追加到数组里面arr.push(obj)// console.log(arr)// 输入完点录入之后表单上面还是有数据,正常情况下我们要清空// 清空表单// info就是表单,表单就是它自己// 表单也有提交事件,它有个事件叫做重置(value都为空的方式太麻烦了stuId,uname...都要设置为空)this.reset()// 函数不调用,自己不执行// 调用渲染函数render()})// 数组添加一条要渲染,删除一条要渲染,相同的代码我们可以选择封装函数 // 2. 渲染函数 因为增加和删除都需要渲染function render() {// 为解决这个bug,应该先清空tbody以前的行,再把最新数组里面的数据渲染完毕 // 代码从上往下执行,每次都能清空tbody之后再渲染tbody.innerHTML = ''// 渲染的第一步是把数组拿过来,看看有几条数据就可以渲染了// 遍历arr数组for (let i = 0; i < arr.length; i++) {// 生成 tr tr不能为空// 不能是querySelector 因为页面中没有行,行是生成的const tr = document.createElement('tr')// 这个a是通过for循环遍历出来的,在生成这个标签的时候连着自定义属性一块儿写上// 循环是从上往下去遍历,第一次索引号是0,0我们生成第一条数据,所以它的索引号就是 itr.innerHTML = `<td>${arr[i].stuId}</td><td>${arr[i].uname}</td><td>${arr[i].age}</td><td>${arr[i].gender}</td><td>${arr[i].salary}</td><td>${arr[i].city}</td><td><a href="javascript:" data-id=${i}>删除</a></td>`// 追加元素 父元素.appendChild(子元素)tbody.appendChild(tr) //因为它是后追加,所以它是数组原来有几条数据,就把几条数据渲染出来,再在原来的基础上往上面放}}// 3. 删除操作// 3.1 事件委托 tbodytbody.addEventListener('click', function (e) {// 给a绑定一个自定义属性,绑定它的序号,然后拿到0,1,在数组里面删掉即可// a链接的自定义属性,以前我们是手动一个一个添的,其实真正开发中是生成的// tbody里面的元素有很多,有tr,td,等,我们点aif (e.target.tagName === 'A') {// alert(11)// 当我点完a之后要拿到当前元素的自定义属性 data-id// console.log(e.target.dataset.id)// 删除arr 数组里面对应的数据arr.splice(e.target.dataset.id, 1)console.log(arr)// 不管是添加还是删除,数组都发生变化了,要重新渲染, 渲染函数之后,重新执行遍历,遍历的时候少了一条,所以在页面追加的时候就少追加一条// 重新渲染render()}})</script>
</body></html>