JS
1. 获取自定义属性
1.1 自定义属性操作
<div id="demo" index="1"></div>
<script>
var div = document.queryselector('div')
//1.element.属性
console.log(div.id)
//2.element.getAttribute('属性')
console.log(div.getAttribute('id'))
</script>
区别: element.属性 获取内置属性值(元素本身自带属性)
element.getAttribute(‘属性’)主要获得自定义的属性,程序员自定义的属性
1.2 设置属性值
(1)element.属性 = ‘值’
例: div.id = 'test'
(2)element.setAttribute(‘属性’,‘值’) 主要针对于自定义属性
例: div.setAttribute('index',2)
1.3 移除属性值
(1)element.removeAttribute(‘属性’)
案例: tab栏切换
<style>
*{
margin: 0;
padding: 0;
}
li {
list-style: none;
}
.tab {
width: 978px;
margin: 100px auto;
}
.tab_list {
margin-top: 50px;
padding: 0;
height: 39px;
width: 976px;
border: 1px soild #eee;
border-bottom: 1px solid red;
background-color: rgb(247,247,247);
}
.tab_list li {
display: inline-block;
height: 19px;
line-height: 19px;
padding: 10px 20px;
text-align: center;
cursor: pointer;
}
.tab_list .current {
background-color: #c81623;
color: #fff;
}
.item {
display: none;
}
</style>
<div class = "tab">
<div class = "tab_list">
<ul>
<li class = "current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价(50000)</li>
<li>手机社区</li>
</ul>
</div>
<div class = "tab_con">
<div class = "item" style = "display: block;">
商品介绍模块内容
</div>
<div class = "item">
规格与包装模块内容
</div>
<div class = "item">
售后保障模块内容
</div>
<div class = "item">
商品评价模块内容
</div>
<div class = "item">
手机社区模块内容
</div>
</div>
</div>
<script>
var tab_list = document.querySelector('tab_list');
var lis = document.querySelectorAll('li');
var items = document.querySelectorAll('.item');
for(var i = 0; i < lis.length; i++){
//开始给5个li设置索引号
lis[i].setAttribute('index', i);
lis[i].onclick = function(){
for(var i = 0; i < lis.length; i++){
lis[i].className = '';
}
this.className = 'current';
//2.下面的显示内容模块
var index = this.getAttribute('index');
for(var i = 0; i < items.length; i++){
items[i].style.display = 'none';
}
items[index].style.display = 'block';
}
}
</script>
1.4 H5自定义属性
- 自定义属性的目的
保存并保存数据,有些数据可以保存到页面中而不用保存到数据库中
有些自定义属性很容易引起歧义,不容易判断到底是内置属性还是自定义的,所以H5有了规定
- 设置H5自定义属性
H5规定自定义属性data开头作为属性名并且赋值
<div data-index = "1"></>
div.setAttribute('data-index',1); // 或者使用JavaScript设置
- 获取H5自定义属性
(1)兼容性获取:element.getAttribute('属性')
(2)H5新增:element.dateset.index 或者 element.dateset['index']
ie11才开始支持
dateset是一个集合里面存放了所有以date开头的自定义属性
(3)如果自定义属性里面有多个(-)连接的单词,我们获取的时候采取驼峰命名法
<body>
<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
var div = document.querySelector('div');
div.setAttribute('data-time', 20);
// h5新增的获取自定义属性的方法 它只能获取data-开头的
// dataset 是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset); //会有3个data开头的属性
console.log(div.dataset.index); //2
console.log(div.dataset['index']); //2
// 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
console.log(div.dataset.listName);
console.log(div.dataset['listName']);
</script>
</body>
2. 节点操作
元素节点
nodeType
为1
属性节点nodeType
为2
文本节点nodeType
为3(文本节点包括文字,空格,换行等)
2.1. 节点层级(父子兄层级关系)
- 父级节点
node.parentNode
<div class="box">
<span class="erweima">x</span>
</div>
<script>
var erweima = document.queryselector('.erweima')
//得到的是离元素最近的父结点(亲爸爸),如果找不到返回null
console.log(erweima.parentNode)
</script>
- 子节点
parentNode.childNodes
<ul>
<li>...</li>
<li>...</li>
...
</ul>
<ol>
<li>...</li>
<li>...</li>
...
</ol>
<script>
//1.获取ul里面的li
var ul = document.querySelector('ul')
console.log(ul.childNodes)
</script>
- 如果只想获得里面的元素节点,我们可以使用
parentNode.children
获取所有子元素节点 - 我们只想获取第一个或最后一个元素
(1)parentNode.firstElementChild;
(2)parentNode.lastElementChild;
有兼容性问题,ie9以上才支持
解决方案:
第一个:parentNode.children[0]
最后一个:parentNode.children[ol.children.length - 1]
- 下拉菜单案例
<style>
*{
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
a {
text-decoration: none;
font-size: 14px;
}
.nav {
width: 341px;
height: 50px;
margin: 100px auto;
}
.nav > li{
position: relative;
float: left;
width: 80px;
height: 41px;
text-align: center;
}
.nav li a{
display: block;
width: 100%;
height: 100%;
line-height: 40px;
color: #333;
}
.nav>li>a:hover {
background-color: #eee;
}
.nav ul{
display: none;
position: absolute;
top: 41px;
left: 0;
width: 100%;
border-left: 1px solid #FECC5B;
border-right: 1px solid #FECC5B;
}
.nav ul li{
border-bottom: 1px solid #FECC5B;
}
.nav ul li a:hover{
background-color: #FFF5DA;
}
</style>
<ul class = "nav">
<li>
<a href = "#">微博</a>
<ul>
<li>
<a href = "">私信</a>
</li>
<li>
<a href = "">评论</a>
</li>
<li>
<a href = "">@我</a>
</li>
</ul>
</li>
<li>
<a href = "#">微博</a>
<ul>
<li>
<a href = "">私信</a>
</li>
<li>
<a href = "">评论</a>
</li>
<li>
<a href = "">@我</a>
</li>
</ul>
</li>
<li>
<a href = "#">微博</a>
<ul>
<li>
<a href = "">私信</a>
</li>
<li>
<a href = "">评论</a>
</li>
<li>
<a href = "">@我</a>
</li>
</ul>
</li>
<li>
<a href = "#">微博</a>
<ul>
<li>
<a href = "">私信</a>
</li>
<li>
<a href = "">评论</a>
</li>
<li>
<a href = "">@我</a>
</li>
</ul>
</li>
</ul>
<script>
//1.获取元素
var nav = document.querySelector('.nav');
var lis = nav.children;
for(var i = 0; i < lis.length; i++){
lis[i].onmouseover = function(){
this.children[1].style.display = 'block';
}
lis[i].onmouseout = function(){
this.children[1].style.display = 'none';
}
}
</script>
- 兄弟节点
(1)node.nextSibling
返回当前元素的下一个兄弟节点,找不到则返回null
(2)node.previousSibling
返回当前元素的上一个兄弟节点,找不到则返回null
(3)node.nextElementSibling
返回当前元素的下一个兄弟节点,找不到则返回null。有兼容性问题,ie9以上才支持
(4)node.previousElementSibling
返回当前元素的上一个兄弟节点,找不到则返回null。有兼容性问题,ie9以上才支持
<body>
<div>我是div</div>
<span>我是span</span>
<script>
var div = document.querySelector('div');
// 1.nextSibling 下一个兄弟节点 包含元素节点或者 文本节点等等
console.log(div.nextSibling); // #text
console.log(div.previousSibling); // #text
// 2. nextElementSibling 得到下一个兄弟元素节点
console.log(div.nextElementSibling); //<span>我是span</span>
console.log(div.previousElementSibling);//null
</script>
</body>
问:怎样解决兼容性问题?
自己封装一个兼容性的函数
function getNextElementSibling(element) {
var el = element;
while(el = el.nextSibling) {
if(el.nodeType === 1){
return el;
}
}
return null;
}
2.2 创建节点
document.creatElement('tagName')
- 添加节点
node.appendChild(child)
node.appendChild()将一个节点添加到指定父结点的子结点列表末尾,类似于css中的after伪元素
node.insertBefore(child,指定元素)
node.insertBefore()将一个节点添加到指定父结点的子结点列表前面,类似于css中的before伪元素
发布留言案例:
<style>
*{
margin: 0;
padding: 0;
}
body {
padding: 100px;
}
textarea {
width: 200px;
height: 100px;
border: 1px solid pink;
outline: none;
resize: none;
}
ul {
margin-top: 50px;
}
li {
width: 300px;
padding: 5px;
background-color: rgb(245, 209, 243);
color: red;
font-size: 14px;
margin: 15px 0;
}
li a{
float: right;
}
</style>
<textarea name="" id="">123</textarea>
<button>发布</button>
<ul>
</ul>
<script>
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
btn.onclick = function(){
if(text.value == ''){
alert('您没有输入内容');
return false;
}else{
//(1)创建元素
var li = document.createElement('li');
//先有li 才能赋值
li.innerHTML = text.value + "<a href = 'javascript:;'>删除</a>";
//(2)添加元素
//ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
//(3)删除元素
var as = document.querySelectorAll('a');
for(var i = 0; i < as.length; i++){
as[i].onclick = function(){
ul.removeChild(this.parentNode);
}
}
}
}
</script>
- 删除节点
node.removeChild(child)
node.removeChild()方法从 DOM 中删除一个子节点,返回删除的节点
阻止链接跳转<a href='javascript:;'>删除</a>
- 复制节点
node.cloneNode()
如果括号参数为空或者为false,只复制标签,不复制内容,如果为true则为深拷贝。
<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>
动态生成表格案例:
<style>
table {
width: 500px;
margin: 100px auto;
border-collapse: collapse;
text-align: center;
}
td,
th {
border: 1px solid #333;
}
thead tr {
height: 40px;
background-color: #ccc;
}
</style>
<table cellspacing = "0">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
//1.先准备好学生的数据
var datas = [{
name: '张三',
subject: 'JavaScript',
score: 100
},{
name: '李四',
subject: 'JavaScript',
score: 98
},{
name: '王五',
subject: 'JavaScript',
score: 68
},{
name: '小红',
subject: 'JavaScript',
score: 99
}];
//2.往tbody里面创建行:有几个人(通过数组的长度) 我们就创建几行
var tbody = document.querySelector('tbody');
for(var i = 0; i < datas.length; i++){//外面的是行
//创建 tr 行
var tr = document.createElement('tr');
tbody.appendChild(tr);
//行里面创建单元格 td 单元格的数量取决于每个对象里面的属性个数
for(var k in datas[i]){
//里面的for循环时列
//创建单元格
var td = document.createElement('td');
//把对象里面的属性值给 td
td.innerHTML = datas[i][k];
tr.appendChild(td);
}
//3.创建有删除2个字的单元格
var td = document.createElement('td');
td.innerHTML = '<a href = "javascript:;">删除</a>';
tr.appendChild(td);
}
//4.删除操作
var as = document.querySelectorAll('a');
for(var i = 0; i < as.length; i++){
as[i].onclick = function(){
//点击a 删除 当前a 所在的行(链接的爸爸的爸爸)
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>
2.3 三种动态创建元素区别
document.write()
创建元素
直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘innerHTML
创建元素
var inner = document.querySelector('.inner')
inner.innerHTML = '<a href="#">百度</a>'
document.createElement()
创建元素
- innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘
- innerHTML创建多个元素效率更高,结构稍微复杂
- createElement()创建多个元素效率稍微低一点,但是结构更清晰
不同浏览器下,innerHTML效率要比createElement高