这里写目录标题
一、几个案例:
案例1:如何实现点击一个按钮亮,其余按钮全灭?
这里用到排他思想的算法,也就是点击一个按钮,先把所有的按钮变成原来的颜色,然后再把当前点击的按钮变成亮色。这里用到两个for循环,要好好体会一下。
<!-- 如何实现点击一个按钮亮,其余按钮全灭? -->
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
//通过for循环首先给所有的按钮点击事件
var btns = document.getElementsByTagName('button');
//上面返回的是伪数组,我们对其遍历
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
//1.首先点击一个,先把所有的按钮变成灰色
for (var i = 0; i < btns.length; i++) {
btns[i].style.backgroundColor = '';
}
//2.当前点击的按钮变成粉色,这里写this
this.style.backgroundColor = 'pink';
}
}
</script>
案例2:浏览器换肤效果
思路:点击某个图片,把该图片的地址赋给body
这里的几个注意点:
1.body元素和html元素的获取方法,要多复习复习
2.给多个相同元素添加事件可以用for循环
3.修改样式,赋值要加引号,如果其中有变量,要单独拿出来,用+拼接就欧了
* {
box-sizing: border-box;
}
body {
background: url(./images/1.jpg) no-repeat center top;
}
.box {
text-align: center;
width: 600px;
height: 112px;
line-height: 50px;
margin: 200px auto;
border: 1px solid #ccc;
}
.box img {
margin: 5px 0;
padding: 0 5px;
float: left;
width: 25%;
height: 90%;
border: 1px solid transparent;
}
.box img:hover {
border: 1px solid red;
}
<div class="box">
<img src="./images/1.jpg" alt="">
<img src="./images/2.jpg" alt="">
<img src="./images/3.jpg" alt="">
<img src="./images/4.jpg" alt="">
</div>
<script>
var imgs = document.querySelector('.box').querySelectorAll('img');
var body = document.body;
for (var i = 0; i < imgs.length; i++) {
imgs[i].onclick = function () {
// 别忘了获取body元素的方法,document.body
body.style.backgroundImage = 'url(' + this.src + ')';
}
}
</script>
案例3:表格隔行变色
其实这个效果类似css的hover
1.用到的事件:鼠标经过onmouseover,鼠标离开onmouseout
2.核心思路:鼠标经过当前行,背景颜色改变,鼠标离开当前行就去掉背景颜色
代码:
<table>
<thead>
<tr>
<th>名字</th>
<th>性别</th>
<th>年龄</th>
<th>身高</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>男</td>
<td>21</td>
<td>185cm</td>
</tr>
<tr>
<td>张三</td>
<td>男</td>
<td>21</td>
<td>185cm</td>
</tr>
<tr>
<td>张三</td>
<td>男</td>
<td>21</td>
<td>185cm</td>
</tr>
</tbody>
</table>
<script>
var trs = document.querySelector('tbody').querySelectorAll('tr');
for (var i = 0; i < trs.length; i++) {
//css的hover效果
trs[i].onmouseover = function () {
this.style.backgroundColor = 'pink';
}
trs[i].onmouseout = function () {
this.style.backgroundColor = '';
}
}
</script>
案例4:全选框和复选框(难的一塌糊涂)
先写html
<div class="box">
<table>
<thead>
<tr>
<th>
<input type="checkbox" id="select_all">
</th>
<th>名称</th>
<th>价格</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="checkbox">
</td>
<td>手机</td>
<td>10000</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>手机</td>
<td>9999</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>手机</td>
<td>8888</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>手机</td>
<td>7777</td>
</tr>
</tbody>
</table>
</div>
再写JavaScript
我自己的逻辑:
1.全选框这块儿,点击事件,让所有小弟变成和全选框一样就行,这个比较简单
2.小弟们这里需要点逻辑,所有小弟全选时,全选框全选,有一个小弟不选时,全选框就不选。
首先把所有小弟选出来,给它们一个点击事件,每点击一个小弟,就对所有小弟循环,判断该小弟是否已经打勾,只有四个小弟都打勾,全选框才打勾。
3.小弟这里可以设置一个变量flag,初始置为0,如果小弟有一个打勾的,就加一次1
4.每次循环结束判断flag是否等于全部的小弟数,如果等于,全选框变成true,否则变为false
var s_all = document.getElementById('select_all');
var s_tds = document.querySelector('tbody').querySelectorAll('input');
//1.操作全选框
s_all.onclick = function () {
for (var i = 0; i < s_tds.length; i++) {
// 多选框默认选定状态是checked='checked'
s_tds[i].checked = this.checked;
}
}
//2.操作全选框的小弟们,首先把元素全选出来
for (var i = 0; i < s_tds.length; i++) {
s_tds[i].onclick = function () {
//每次点击一个框,就对所有的框进行循环,判断是全选还是全取消
var flag = 0; //定义一个变量来判断下面是否全部选中
for (var i = 0; i < s_tds.length; i++) {
if (s_tds[i].checked == true) {
flag++;
}
}
if (flag == s_tds.length) {
s_all.checked = true;
}
else {
//这里的true和false不用加引号,因为本身就是boolean类型
//这个地方有点奇怪,上面true加引号不影响,下面这个false就不行
s_all.checked = false;
}
}
}
老师操作小弟的逻辑:
除了操作小弟的逻辑,其他地方都差不多。这个是真的难想,把flag初始值置为true,然后每点击一次就循环
如果有一个没点的,那么就把flag变成false,最后让全选框=flag的值
这里不太好想到的是if里的判断条件,如果有一个没选的,那么s_tds[i].checked肯定就是false,然后取反就是true,当条件为true的时候执行if里的条件执行体,因为只要有一个false全选框就是false,所以如果有一个没选,循环就可以break结束了。如果全选了,if就不会执行,flag还是true。
for (var i = 0; i < s_tds.length; i++) {
s_tds[i].onclick = function () {
//每次点击一个框,就对所有的框进行循环,判断是全选还是全取消
var flag = true; //定义一个变量,默认为true
for (var i = 0; i < s_tds.length; i++) {
//只要有一个没有选中,全选框就不选
if (!s_tds[i].checked) {
flag = false;
break;
}
}
s_all.checked = flag;
}
}
二、自定义属性
这里最需要注意的地方就是,自定义属性只能用第二种方式操作,这个太容易忘了
1.获取属性值的方法:
区别:
比如我这里自定义了一个div,里面id是共有的,my是我自己定义的
<div id="zzy" my='1' class='zzy'></div>
那我使用第一种就不能获取我自定义的my,我用第二种就可以
var div = document.querySelector('div');
console.log(div.id); //zzy
console.log(div.getAttribute('id')); //zzy
console.log(div.getAttribute('my')); //1
console.log(div.my); //undefined
2.修改属性值的方法:
比如还是这个div,我想改变id和class
<div id="zzy" my='1' class='zzy'></div>
使用第一种方法这么改:
注意必须是className
div.id = 'ht';
div.className = 'ht';
使用第二种这么改:
div.setAttribute('id', 'ht');
div.setAttribute('class', 'ht');
但是如果想改自定义属性,只能用第二个:
div.setAttribute('my', '2');
2.移除属性用removeAttribute(‘属性’)
div.removeAttribute('index');
三、tab栏切换(重点中的重点)
先写html,css这里就不写了
这个思路真的是男上加男,强人锁男,且听我细细道来
<div class="box">
<div class="box_hd" id="box_hd">
<ul>
<li class="bhd_first">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价(5000)</li>
<li>手机社区</li>
</ul>
</div>
<div class="box_bd" id="box_bd">
<div class="item" style="display:block">
商品介绍模块内容
</div>
<div class="item">
规格与包装模块内容
</div>
<div class="item">
售后保障模块内容
</div>
<div class="item">
商品评价(5000)模块内容
</div>
<div class="item">
手机社区模块内容
</div>
</div>
</div>
代码逻辑:
1.这里我们要实现的主要功能就是,点击头部的模块,身子能显示到相对应的内容上,这里要分为两步来做,第一步就是头部区域,点谁谁就变红,这里用到排他思想,比较简单不再赘述。第二步就是点击哪块儿头部,就显示哪块儿身子,其他的身子隐藏
2.第二步也是用到排他思想,但是它的难点在于,我怎么保证身子的索引和头部一样呢?That is a question,用i吗?你会发现实际上这里面两个for循环已经改变了i的值,每次循环结束,i都会变为lis或divs的长度(本例中是5),这样的话,如果我们最后一句直接写divs[i].style.display = ‘block’;肯定会报错,因为divs[5]是不存在的,最后一个是divs[4](本例中)
3.在这种情况下,就用到了上面我们提到的自定义属性,在我们准备给每个li添加点击事件时(也就是for循环的开始),可以使用setAttribute给每个li添加一个自定义属性,名字随便取,这里我叫index,属性值就是i的值
4.后面呢再定义一个变量来接收当前点击事件的index,这样就能够有一个值,和头部的值相对应,就可以操作了
//1.先使用排他思想设置头部的区域
var box_hd = document.getElementById('box_hd'); //id选择器别对应class!!
var lis = box_hd.getElementsByTagName('li');
var box_bd = document.getElementById('box_bd');
var divs = box_bd.getElementsByTagName('div');
for (var i = 0; i < lis.length; i++) {
//通过下面这行代码,给每个li添加一个index的自定义属性,让index的值和索引号i对应
lis[i].setAttribute('index', i);
lis[i].onclick = function () {
for (var i = 0; i < lis.length; i++) {
lis[i].className = '';
}
//从上面这个循环出来,i的值变成了5(lis的长度)
this.className = 'bhd_first';
//2.设置点击哪个头部显示哪块儿身子,剩下的身子隐藏
for (var i = 0; i < divs.length; i++) {
divs[i].style.display = 'none';
}
//从上面这个循环出来,i的值也变成了5(divs的长度)
var index = this.getAttribute('index'); //通过自定义属性,得到当前点击事件的index
//这样的话,就可以选择到和当前点击相对应的div,把它的display属性改为block显示
divs[index].style.display = 'block';
}
}
四、H5自定义属性
1.自定义属性的目的
实际上就是把数据保存到页面中而不是保存到数据库中,就像上面这个tab栏切换的例子,一开始其实我是手动给每个li添加了index属性,但是听老师讲后发现,lis[i].setAttribute(‘index’, i);这一句代码就可以直接给每个li添加index属性,而且页面刷新就没了,还是非常不错的。
2.我tm怎么知道哪个是自定义属性,哪个不是自定义属性
H5规定,自定义属性以data-开头作为属性名并赋值
<li data-index="1">规格与包装</li>
也可以用下面这种方式添加
li.setAttribute('data-time', '20');
添加之后就成了:
<li data-index="1" data-time="20">规格与包装</li>
3.H5新增使用dataset对象获取自定义属性
除了li.getAttribute(‘data-index’);获取自定义属性外,H5还新增了li.dataset.index或者li.dataset[‘index’]
这个要注意点后面是index而不是data-index,就是只写data-index后面的部分,很奇怪,记住就行了,而且这个只有ie11及以上才兼容,大多数还是使用getAttribute比较多
<li data-index="1" data-time="20">规格与包装</li>
获取上面这个的data-index:li.dataset.index
如果li.dataset,就是把所有的自定义属性都显示出来(去掉data-),以对象的方式,因为dataset是一个对象。
这里还有个比较恶心的地方就是,如果我属性名叫:data-index-name
那么在获取时就要遵循驼峰命名法,这么写:
li.dataset.indexName