JavaScript(WebAPI)

什么是 WebAPI

前面学习的 JS 分成三个大的部分
ECMAScript: 基础语法部分
DOM API: 操作页面结构
BOM API: 操作浏览器
WebAPI 就包含了 DOM + BOM.
这个是 W3C 组织规定的 . ( 和制定 ECMAScript 标准的大佬们不是一伙人 ).

什么是 API

API 是一个更广义的概念 . WebAPI 是一个更具体的概念 , 特指 DOM+BOM
所谓的 API 本质上就是一些现成的函数 / 对象 , 让程序猿拿来就用 , 方便开发 .

DOM 基本概念

什么是 DOM

DOM 全称为 Document Object Model.
W3C 标准给我们提供了一系列的函数 , 让我们可以操作 :
  • 网页内容
  • 网页结构
  • 网页样式

DOM

一个页面的结构是一个树形结构 , 称为 DOM .
树形结构在数据结构阶段会介绍 . 就可以简单理解成类似于 " 家谱 " 这种结构
页面结构形如 :

DOM 树结构形如

重要概念 :
文档 : 一个页面就是一个 文档 , 使用 document 表示 .
元素 : 页面中所有的标签都称为 元素 . 使用 element 表示 .
节点 : 网页中所有的内容都可以称为 节点 ( 标签节点 , 注释节点 , 文本节点 , 属性节点等 ). 使用 node
表示 .
这些文档等概念在 JS 代码中就对应一个个的对象 .
所以才叫 " 文档对象模型 " .

获取元素

这部分工作类似于 CSS 选择器的功能 .

querySelector

这个是 HTML5 新增的 , IE9 及以上版本才能使用 .
前面的几种方式获取元素的时候都比较麻烦 . 而使用 querySelector 能够完全复用前面学过的 CSS 选择 器知识, 达到更快捷更精准的方式获取到元素对象 .
var element = document . querySelector ( selectors );
  • selectors 包含一个或多个要匹配的选择器的 DOM字符串 DOMString 。 该字符串必须是有效的
  • CSS选择器字符串;如果不是,则引发 SYNTAX_ERR 异常
  • 表示文档中与指定的一组CSS选择器匹配的第一个元素的 html元素 Element 对象.
  • 如果您需要与指定选择器匹配的所有元素的列表,则应该使用 querySelectorAll()
  • 可以在任何元素上调用,不仅仅是 document。 调用这个方法的元素将作为本次查找的根元素
正因为参数是选择器 , 所以一定要通过特殊符号指定是哪种选择器 .
例如 .box 是类选择器 , #star id 选择器 等

 <div class="box">abc</div>

<div id = "id" > def </div>
<h3><span><input type = "text" ></span></h3>
<script>
var elem1 = document . querySelector ( '.box' );
console . log ( elem1 );
var elem2 = document . querySelector ( '#id' );
console . log ( elem2 );
var elem3 = document . querySelector ( 'h3 span input' );
console . log ( elem3 );
</script>

querySelectorAll

使用 querySelectorAll 用法和上面类似 .
<div class = "box" > abc </div>
<div id = "id" > def </div>
<script>
var elems = document . querySelectorAll ( 'div' );
console . log ( elems );
</script>

事件初识

基本概念

JS 要构建动态页面 , 就需要感知到用户的行为 .
用户对于页面的一些操作 ( 点击 , 选择 , 修改等 ) 操作都会在浏览器中产生一个个事件 , JS 获取到 , 从而进
行更复杂的交互操作 .
浏览器就是一个哨兵 , 在侦查敌情 ( 用户行为 ). 一旦用户有反应 ( 触发具体动作 ), 哨兵就会点燃烽火台
的狼烟 ( 事件 ), 后方就可以根据狼烟来决定下一步的对敌策略 .

事件三要素

1. 事件源 : 哪个元素触发的
2. 事件类型 : 是点击 , 选中 , 还是修改 ?
3. 事件处理程序 : 进一步如何处理 . 往往是一个回调函数 .

简单示例

<button id = "btn" > 点我一下 </button>
<script>
var btn = document . getElementById ( 'btn' );
btn . onclick = function () {
alert ( "hello world" );
}
</script>
  • btn 按钮就是事件源.
  • 点击就是事件类型
  • function 这个匿名函数就是事件处理程序
  • 其中 btn.onclick = function() 这个操作称为 注册事件/绑定事件
注意 : 这个匿名函数相当于一个回调函数 , 这个函数不需要程序猿主动来调用 , 而是交给浏览器 , 由浏览器
自动在合适的时机 ( 触发点击操作时 ) 进行调用 .

操作元素

获取/修改元素内容

1. innerText

Element.innerText 属性表示一个节点及其后代的 渲染 文本内容 
// 读操作
var renderedText = HTMLElement . innerText ;
// 写操作
HTMLElement . innerText = string ;

 不识别 html 标签. 是非标准的(IE发起的). 读取结果不保留html源码中的 换行 和 空格

<div>
<span> hello world </span>
<span> hello world </span>
</div>
<script>
var div = document . querySelector ( 'div' );
// 读取 div 内部内容
console . log ( div . innerText );
// 修改 div 内部内容 , 界面上就会同步修改
div . innerText = 'hello js <span>hello js</span>' ;
</script>
可以看到 , 通过 innerText 无法获取到 div 内部的 html 结构 , 只能得到文本内容 .
修改页面的时候也会把 span 标签当成文本进行设置 .

2. innerHTML

Element.innerHTML 属性设置或获取 HTML 语法表示的元素的后代 .
// 读操作
var content = element . innerHTML ;
// 写操作
element . innerHTML = htmlString ;
1. 先获取到事件源的元素
2. 注册事件
识别 html 标签 . W3C 标准的 . 读取结果保留 html 源码中的 换行 和 空格 .
<div>
<span> hello world </span>
<span> hello world </span>
</div>
<script>
var div = document . querySelector ( 'div' );
// 读取页面内容
console . log ( div . innerHTML );
// 修改页面内容
div . innerHTML = '<span>hello js</span>'
</script>
可以看到 innerHTML 不光能获取到页面的 html 结构 , 同时也能修改结构 . 并且获取到的内容保留的空格
和换行 .
innerHTML 用的场景比 innerText 更多

获取/修改元素属性

可以通过 Element 对象的属性来直接修改 , 就能影响到页面显示效果 .
<img src = "rose.jpg" alt = " 这是一朵花 " title = " 玫瑰花 " >
<script>
var img = document . querySelector ( 'img' );
console . dir ( img );
</script>

此时可以看到 img 这个 Element 对象中有很多属性

 

我们可以在代码中直接通过这些属性来获取属性的值. 

还可以直接修改属性

<img src = "rose.jpg" alt = " 这是一朵花 " title = " 玫瑰花 " >
<script>
var img = document . querySelector ( 'img' );
img . onclick = function () {
if ( img . src . lastIndexOf ( 'rose.jpg' ) !== - 1 ) {
img . src = './rose2.png' ;
} else {
img . src = './rose.jpg' ;
}
}
</script>

此时点击图片就可以切换图片显示状态. (需要提前把两个图片准备好) 

获取/修改表单元素属性

表单 ( 主要是指 input 标签 ) 的以下属性都可以通过 DOM 来修改
  • value: input 的值.
  • disabled: 禁用
  • checked: 复选框会使用
  • selected: 下拉框会使用
type: input 的类型 ( 文本 , 密码 , 按钮 , 文件等 )
代码示例 : 切换按钮的文本 .
假设这是个播放按钮 , " 播放 " - " 暂停 " 之间切换.
<input type = "button" value = " 播放 " >
<script>
var btn = document . querySelector ( 'input' );
btn . onclick = function () {
if ( btn . value === ' 播放 ' ) {
btn . value = ' 暂停 ' ;
} else {
btn . value = ' 播放 ' ;
}
}
</script>
代码示例 : 点击计数
使用一个输入框输入初始值 ( 整数 ). 每次点击按钮 , + 1
<input type = "text" id = "text" value = "0" >
<input type = "button" id = "btn" value = ' 点我 +1' >
<script>
var text = document . querySelector ( '#text' );
var btn = document . querySelector ( '#btn' );
btn . onclick = function () {
var num = + text . value ;
console . log ( num );
num ++ ;
text . value = num ;
}
</script>
  • input 具有一个重要的属性 value, 这个 value 决定了表单元素的内容
  • 如果是输入框, value 表示输入框的内容, 修改这个值会影响到界面显式; 在界面上修改这个值也会影 响到代码中的属性
  • 如果是按钮, value 表示按钮的内容. 可以通过这个来实现按钮中文本的替换
代码示例 : 全选 / 取消全选按钮

 

1. 点击全选按钮 , 则选中所有选项
2. 只要某个选项取消 , 则自动取消全选按钮的勾选状态 .
<input type = "checkbox" id = "all" > 我全都要 <br>
<input type = "checkbox" class = "girl" > 貂蝉 <br>
<input type = "checkbox" class = "girl" > 小乔 <br>
<input type = "checkbox" class = "girl" > 安琪拉 <br>
<input type = "checkbox" class = "girl" > 妲己 <br>
<script>
// 1. 获取到元素
var all = document . querySelector ( '#all' );
var girls = document . querySelectorAll ( '.girl' );
// 2. all 注册点击事件 , 选中 / 取消所有选项
all . onclick = function () {
for ( var i = 0 ; i < girls . length ; i ++ ) {
girls [ i ]. checked = all . checked ;
}
}
// 3. girl 注册点击事件
for ( var i = 0 ; i < girls . length ; i ++ ) {
girls [ i ]. onclick = function () {
// 检测当前是不是所有的 girl 都被选中了 .
all . checked = checkGirls ( girls );
}
}
// 4. 实现 checkGirls
function checkGirls ( girls ) {
for ( var i = 0 ; i < girls . length ; i ++ ) {
if ( ! girls [ i ]. checked ) {
// 只要一个 girl 没被选中 , 就认为结果是 false( 找到了反例 )
return false ;
}
}
// 所有 girl 中都没找到反例 , 结果就是全选中
return true ;
}
</script>

获取/修改样式属性

CSS 中指定给元素的属性 , 都可以通过 JS 来修改 .

行内样式操作

" 行内样式 ", 通过 style 直接在标签上指定的样式 . 优先级很高 .
适用于改的样式少的情况
代码示例 : 点击文字则放大字体 .
style 中的属性都是使用 驼峰命名 的方式和 CSS 属性对应的 .
例如 : font-size => fontSize, background-color => backgroundColor
这种方式修改只影响到特定样式 , 其他内联样式的值不变 .
<div style = "font-size: 20px; font-weight: 700;" >
哈哈
</div>
<script>
var div = document . querySelector ( 'div' );
div . onclick = function () {
var curFontSize = parseInt ( this . style . fontSize );
curFontSize += 10 ;
this . style . fontSize = curFontSize + "px" ;
}
</script>

类名样式操作 

element.className = [CSS 类名 ];
修改元素的 CSS 类名 . 适用于要修改的样式很多的情况 .
由于 class JS 的保留字 , 所以名字叫做 className

 代码示例: 开启夜间模式

  • 点击页面切换到夜间模式(背景变成黑色)
  • 再次点击恢复日间模式(背景变成白色)
<div class = "container light" >
这是一大段话 . <br>
这是一大段话 . <br>
这是一大段话 . <br>
这是一大段话 . <br>
</div>
* {
margin : 0 ;
padding : 0 ;
}
html ,
body {
width : 100% ;
height : 100% ;
}
.container {
width : 100% ;
height : 100% ;
}
.light {
background-color : #f3f3f3 ;
color : #333 ;
}
.dark {
background-color : #333 ;
color : #f3f3f3 ;
}
var div = document . querySelector ( 'div' );
div . onclick = function () {
console . log ( div . className );
if ( div . className . indexOf ( 'light' ) != - 1 ) {
div . className = 'container dark' ;
} else {
div . className = 'container light' ;
}
}

操作节点

新增节点

分成两个步骤
1. 创建元素节点
2. 把元素节点插入到 dom 树中 .
第一步相当于生了个娃 , 第二步相当于给娃上户口 .

1. 创建元素节点

使用 createElement 方法来创建一个元素 . options 参数暂不关注 .
var element = document . createElement ( tagName [, options ]);

代码示例:

<div class = "container" >
</div>
<script>
var div = document . createElement ( 'div' );
div . id = 'mydiv' ;
div . className = 'box' ;
div . innerHTML = 'hehe' ;
console . log ( div );
</script>
此时发现 , 虽然创建出新的 div , 但是 div 并没有显示在页面上 . 这是因为新创建的节点并没有加入到 DOM 树中 .
上面介绍的只是创建元素节点 , 还可以使用 :
createTextNode 创建文本节点
createComment 创建注释节点
createAttribute 创建属性节点
我们以 createElement 为主即可 .

2. 插入节点到 dom 树中

1) 使用 appendChild 将节点插入到指定节点的最后一个孩子之后

 element.appendChild(aChild)

<div class = "container" >
</div>
<script>
var div = document . createElement ( 'div' );
div . id = 'mydiv' ;
div . className = 'box' ;
div . innerHTML = 'hehe' ;
var container = document . querySelector ( '.container' );
container . appendChild ( div );
</script>

2) 使用 insertBefore 将节点插入到指定节点之前.

var insertedNode = parentNode . insertBefore ( newNode , referenceNode );
  • insertedNode 被插入节点(newNode)
  • parentNode 新插入节点的父节点
  • newNode 用于插入的节点
  • referenceNode newNode 将要插在这个节点之前
如果 referenceNode null newNode 将被插入到子节点的末尾 .
注意 : referenceNode 引用节点 不是 可选参数
<div class = "container" >
<div> 11 </div>
<div> 22 </div>
<div> 33 </div>
<div> 44 </div>
</div>
<script>
var newDiv = document . createElement ( 'div' );
newDiv . innerHTML = ' 我是新的节点 ' ;
var container = document . querySelector ( '.container' );
console . log ( container . children );
container . insertBefore ( newDiv , container . children [ 0 ]);
</script>

 

注意1: 如果针对一个节点插入两次, 则只有最后一次生效(相当于把元素移动了)

<div class = "container" >
<div> 11 </div>
<div> 22 </div>
<div> 33 </div>
<div> 44 </div>
</div>
<script>
var newDiv = document . createElement ( 'div' );
newDiv . innerHTML = ' 我是新的节点 ' ;
var container = document . querySelector ( '.container' );
console . log ( container . children );
// 此处的 children 里有 4 个元素
container . insertBefore ( newDiv , container . children [ 0 ]);
// 此处的 children 里有 5 个元素 ( 上面新插了一个 ), 0 号元素是 新节点 ,
// 1 号元素是 11, 2 号节点是 22, 所以是插入到 22 之前 .
container . insertBefore ( newDiv , container . children [ 2 ]);
</script> 

注意2: 一旦一个节点插入完毕, 再针对刚刚的节点对象进行修改, 能够同步影响到 DOM 树中的内容

<div class = "container" >
<div> 11 </div>
<div> 22 </div>
<div> 33 </div>
<div> 44 </div>
</div>
<script>
var newDiv = document . createElement ( 'div' );
newDiv . innerHTML = ' 我是新的节点 ' ;
var container = document . querySelector ( '.container' );
console . log ( container . children );
container . insertBefore ( newDiv , container . children [ 0 ]);
// 插入完毕后再次修改 newDiv 的内容
newDiv . innerHTML = ' 我是新节点 2' ;
</script>

 

删除节点

使用 removeChild 删除子节点
oldChild = element . removeChild ( child );
  • child 为待删除节点
  • element child 的父节点
  • 返回值为该被删除节点
  • 被删除节点只是从 dom 树被删除了, 但是仍然在内存中, 可以随时加入到 dom 树的其他位置.
  • 如果上例中的 child节点 不是 element 节点的子节点,则该方法会抛出异常.

代码案例: 猜数字

预期效果

 

代码实现 

<button type = "button" id = "reset" > 重新开始一局游戏 </button>
<br>
请输入要猜的数字: <input type = "text" id = "number" >
<button type = "button" id = "button" > </button>
<br>
已经猜的次数: <span id = "count" > 0 </span>
<br>
结果: <span id = "result" ></span>
<script>
var inputE = document . querySelector ( "#number" );
var countE = document . querySelector ( "#count" );
var resultE = document . querySelector ( "#result" );
var btn = document . querySelector ( "#button" );
var resetBtn = document . querySelector ( "#reset" );
// 随机生成一个 1-100 的数字
var guessNumber = Math . floor ( Math . random () * 100 ) + 1 // 0 - 1 之间的数
var count = 0 ;
// on:
// click: 点击
// 事件驱动( Event-Drive ):只要真正发生了点击事件时,才执行该函数
btn . onclick = function () {
count ++ ;
countE . innerText = count ;
var userGuess = parseInt ( inputE . value );
if ( userGuess == guessNumber ) {
resultE . innerText = " 猜对了 " ;
resultE . style = "color: gray;" ;
} else if ( userGuess < guessNumber ) {
resultE . innerText = " 猜小了 " ;
resultE . style = "color: blue;" ;
} else {
resultE . innerText = " 猜大了 " ;
resultE . style = "color: red;" ;
}
};
resetBtn . onclick = function () {
guessNumber = Math . floor ( Math . random () * 100 ) + 1
count = 0 ;
countE . innerText = count ;
resultE . innerText = "" ;
inputE . value = "" ;
}
</script>

代码案例: 表白墙

预期效果

创建页面布局

创建 表白墙 .html

 

<h1> 表白墙 </h1>
<p> 输入后点击提交 , 会将信息显示在表格中 </p>
<span> : </span>
<input type = "text" >
<span> 对谁 : </span>
<input type = "text" >
<span> 说什么 : </span>
<input type = "text" >
<input type = "button" value = " 提交 " >

此时效果形如

 

调整样式

<div class = "container" >
<h1> 表白墙 </h1>
<p> 输入后点击提交 , 会将信息显示在表格中 </p>
<div class = "row" >
<span> : </span>
<input class = "edit" type = "text" >
</div>
<div class = "row" >
<span> 对谁 : </span>
<input class = "edit" type = "text" >
</div>
<div class = "row" >
<span> 说什么 : </span>
<input class = "edit" type = "text" >
</div>
<div class = "row" >
<input type = "button" value = " 提交 " class = "submit" >
</div>
</div>
<style>
* {
margin : 0 ;
padding : 0 ;
}
.container {
width : 400px ;
margin : 0 auto ;
}
h1 {
text-align : center ;
padding : 20px 0 ;
}
p {
color : #666 ;
text-align : center ;
font-size : 14px ;
padding : 10px 0 ;
}
.row {
height : 40px ;
display : flex ;
justify-content : center ;
align-items : center ;
}
span {
width : 100px ;
line-height : 40px ;
}
.edit {
width : 200px ;
height : 30px ;
}
.submit {
width : 304px ;
height : 40px ;
color : white ;
background-color : orange ;
border : none ;
}

 </style>

 此时效果形如

实现提交

// 给点击按钮注册点击事件
var submit = document . querySelector ( '.submit' );
submit . onclick = function () {
// 1. 获取到编辑框内容
var edits = document . querySelectorAll ( '.edit' );
var from = edits [ 0 ]. value ;
var to = edits [ 1 ]. value ;
var message = edits [ 2 ]. value ;
console . log ( from + "," + to + "," + message );
if ( from == '' || to == '' || message == '' ) {
return ;
}
// 2. 构造 html 元素
var row = document . createElement ( 'div' );
row . className = 'row' ;
row . innerHTML = from + ' ' + to + ' : ' + message ;
// 3. 把构造好的元素添加进去
var container = document . querySelector ( '.container' );
container . appendChild ( row );
// 4. 同时清理之前输入框的内容
for ( var i = 0 ; i < 3 ; i ++ ) {
edits [ i ]. value = '' ;
}
}

此时效果形如:

 

实现点击按钮的动画效果

需要使用伪类选择器 .
伪类选择器种类有很多 . 此处的 :active 表示选中被按下的按钮 .
.submit : active {
background-color : #666 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值