陈晓萍 發表於 2022-12-8 13:26:00

JavaScript入门⑧-事件总结大全

<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114204631596-1622810398.png" alt="image.png" loading="lazy"></p>
<p><strong>JavaScript入门系列目录</strong></p>
<ul>
<li>JavaScript入门①-基础知识筑基</li>
<li>JavaScript入门②-函数(1)基础{浅出}</li>
<li>JavaScript入门③-函数(2)原理{深入}执行上下文</li>
<li>JavaScript入门④-万物皆对象:Object</li>
<li>JavaScript入门⑤-欲罢不能的对象、原型与继承</li>
<li>JavaScript入门⑥-WEB浏览器API</li>
<li>JavaScript入门⑦-DOM操作大全</li>
<li>JavaScript入门⑧-事件总结大全</li>
<li>JavaScript入门⑨-异步编程●异世界之旅</li>
<li>JavaScript入门⑩-ES6归纳总结</li>
</ul>
<h1 id="01事件基础">01、事件基础</h1>
<h2 id="11事件简介">1.1、事件简介</h2>
<p><strong>事件</strong>(Event)是JavaScript的心脏,触发各种交互,让网页动起来。事件是浏览器网页可以监测到的行为,如页面加载、鼠标点击、键盘按键等。在这些事件中可以自定义事件处理程序,用于实现各种业务需求。</p>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114205009811-1010267403.png" alt="image" loading="lazy"></p>
<p>事件对象的继承关系:</p>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114205021899-1949868717.png" alt="image" loading="lazy"></p>
<p>常见的事件类型、事件如下:</p>
<table>
<thead>
<tr>
<th>⚡<strong>鼠标事件</strong>(event)</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>click</strong>(event)</td>
<td>点击触发,通常是鼠标左键在一个元素上被按下并放开时</td>
</tr>
<tr>
<td>dblclick</td>
<td>双击触发事件</td>
</tr>
<tr>
<td>contextmenu</td>
<td>鼠标右键点击触发</td>
</tr>
<tr>
<td><strong>mousedown</strong>、<strong>mouseup</strong></td>
<td>鼠标按下、弹起时触发</td>
</tr>
<tr>
<td><strong>mousemove</strong></td>
<td>鼠标在元素上移动时触发</td>
</tr>
<tr>
<td><strong>onmouseover</strong>、<strong>mouseout</strong></td>
<td>鼠标移入、移出元素区域时触发</td>
</tr>
<tr>
<td>mouseenter、mouseleave</td>
<td>鼠标移入、移出元素区域时触发,与上面不同的是不会冒泡</td>
</tr>
<tr>
<td>dragstart、dragend</td>
<td>拖放事件(drag/dræɡ/拖)</td>
</tr>
<tr>
<td>⚡<strong>键盘事件</strong>(event)</td>
<td><br></td>
</tr>
<tr>
<td><strong>keydown</strong><strong>、keyup</strong></td>
<td>键盘按键按下、松开时触发</td>
</tr>
<tr>
<td>⚡<strong>表单事件</strong>(event)</td>
<td><br></td>
</tr>
<tr>
<td><strong>blur</strong>(event)、focusout()</td>
<td>元素失去焦点,<strong>blur</strong>不会冒泡 (blue /blɜːr/ 模糊 /不乐/)</td>
</tr>
<tr>
<td><strong>focus</strong>、focusin</td>
<td>元素获取焦点时触发,<strong>focus</strong>不会冒泡</td>
</tr>
<tr>
<td>from.submit</td>
<td>提交表单form时触发,可用于表单校验</td>
</tr>
<tr>
<td>change</td>
<td>值发生变化时触发,文本框是在值变化且失去焦点是才触发</td>
</tr>
<tr>
<td>input</td>
<td>输入值改变时触发,<code>event.preventDefault()</code>无法阻止,因为已经改变了</td>
</tr>
<tr>
<td>⚡<strong>Document 事件</strong>(event)</td>
<td>文档生命周期:DOMContentLoaded ➡️ load ➡️ beforeunload ➡️ unload</td>
</tr>
<tr>
<td>doc.<strong>DOMContentLoaded</strong></td>
<td>已加载 HTML并构建好DOM树,外部资源(image、css)可能尚未加载完成<br>- 如果遇到<code>&lt;script&gt;</code>标签,会执行(包括外部的资源)然后才继续后面的DOM加载,要注意!async、defer标记的除外(只支持外部js资源)<br></td>
</tr>
<tr>
<td>window.<strong>load</strong></td>
<td>文档完全加载完成,包括图片、样式都准备好了。可用于window、element</td>
</tr>
<tr>
<td>window.<strong>beforeunload</strong></td>
<td>当用户正在离开页面时,不可取消,好像也不能干什么。</td>
</tr>
<tr>
<td>window.<strong>unload</strong></td>
<td>用户几乎已经离开了,同上</td>
</tr>
<tr>
<td>doc.<strong>readystatechange</strong></td>
<td>文档状态变化时触发,可跟踪文档加载状态<code>readyState</code></td>
</tr>
<tr>
<td>onerror</td>
<td>加载出现错误,用于元素</td>
</tr>
<tr>
<td>scroll</td>
<td>滑动条滚动事件,具有滚动的视图元素。用于window、element</td>
</tr>
<tr>
<td>⚡<strong>ClipboardEvent</strong><strong>事件</strong></td>
<td>事件参数对象<code>clipboardData</code>由于安全限制,方法无法使用</td>
</tr>
<tr>
<td>cut,copy,paste</td>
<td>剪切、拷贝、粘贴时触发</td>
</tr>
<tr>
<td> e.<strong>clipboardData</strong></td>
<td>保存了一个DataTransfer对象,用于存放数据,该对象也用于拖放</td>
</tr>
<tr>
<td>⚡<strong>CSS事件</strong>(event)</td>
<td><br></td>
</tr>
<tr>
<td>transitionend</td>
<td>一个元素 CSS 动画完成时<code>ele.addEventListener("transitionend", func)</code></td>
</tr>
</tbody>
</table>
<h2 id="12事件的绑定">1.2、事件的绑定</h2>
<p><strong>① HTML事件</strong>:HTML中绑定(调用)事件处理程序,<code>&lt;button onclick="func(event);func2()"&gt;button&lt;/button&gt;</code><strong>,</strong>注意加括号()<strong>。</strong></p>
<p><strong>② JS绑定事件(DOM-0级事件)</strong>:<code>button.onclick = function() {}</code>,和HTML绑定一样,只能绑定一个事件处理程序。不能用setAttribute设置事件,因为设置的是字符串值。</p>
<p><strong>③ 注册事件</strong>(<strong>DOM-2级事件</strong>):</p>
<ul>
<li>ele.addEventListener(event,func[, options]) :注册事件,<strong>👍推荐</strong>的常用方式,可添加多个事件处理程序,但同一个事件类型不可添加同一个handler对象。参数options为配置信息,如是否冒泡。</li>
<li>ele.removeEventListener(event,func[, options]) :必须是与添加时相同(恒等)的参数,不可移除匿名函数事件。</li>
</ul>
<p><strong>④ 事件处理对象handleEvent</strong></p>
<p>除了注册事件方法,还可用将一个包含<code>handleEvent</code>方法的<strong>对象</strong>注册到事件处理程序,触发事件时调用对象的<code>handleEvent</code>方法。so,只要对象中包含<code>handleEvent</code>方法即可,任何对象、类的实例都可以。</p>
<pre><code class="language-html">&lt;div id="ediv"&gt;
    &lt;span id="espan" onclick="console.log('html bind')"&gt;span&lt;/span&gt;
    &lt;button id="btn" onclick="console.log('html bind')"&gt;button&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
    function func1(event) {
      console.log(event.currentTarget, event.target); //divspan
      console.log("event.cancleable:" + event.cancelable) //event.cancleable:true
      console.log(event.clientX, event.clientY); //31 363
      //取消冒泡
      event.cancelBubble = true;
      event.stopPropagation();
      event.stopImmediatePropagation(); //取消冒泡,以及元素同类型的其他事件
      //取消默认事件,如checkbox,a元素的默认行为
      event.preventDefault();//对自定义事件没用,
    }
    ediv.addEventListener('click', func1);
    ediv.addEventListener('click', e=&gt;console.log(e.currentTarget.localName)); //div,前面取消了则不会执行
    ediv.addEventListener('click', ()=&gt;console.log('click me'));

    //事件处理对象,调用对象的handelEvent方法执行事件
    let eventObj = {
      handleEvent(event) {
            console.log("handleEvent", this.objName, event);
      },
      objName: "eventObj",
    }
    btn.addEventListener("click", eventObj);
&lt;/script&gt;
</code></pre>
<h2 id="13事件对象event">1.3、事件对象event</h2>
<p>每一个事件处理程序都有一个<code>event</code>对象,内置了事件的详细信息。最基础的Event如下,还有很多继承事件对象。</p>
<table>
<thead>
<tr>
<th><strong>✅</strong><strong>Event</strong><strong>属性</strong></th>
<th><br></th>
</tr>
</thead>
<tbody>
<tr>
<td>type</td>
<td>事件的类型</td>
</tr>
<tr>
<td><strong>target</strong></td>
<td>指向事件<strong>触发</strong>的目标元素,可能为子元素,冒泡中不会改变。originalTarget为非标准(Mozilla)</td>
</tr>
<tr>
<td><strong>currentTarget</strong> = this</td>
<td>指向事件<strong>绑定</strong>的元素,当前正在处理事假的元素,同 <strong><code>this</code></strong>。</td>
</tr>
<tr>
<td>isTrusted</td>
<td>触发方式,true=用户,false=脚本触发,(Trusted/ˈtrʌstɪd/ 可信的)</td>
</tr>
<tr>
<td>bubbles</td>
<td>判断事件是否冒泡,bool。( Bubble/ˈbʌb(ə)l/ 冒泡)</td>
</tr>
<tr>
<td><strong>cancelBubble</strong>✏️</td>
<td>是否取消冒泡,可设置true阻止冒泡,stopPropagation()的别名</td>
</tr>
<tr>
<td>composed</td>
<td>表示事件是否可以穿过 Shadow DOM 和常规 DOM 之间的隔阂进行冒泡,bool</td>
</tr>
<tr>
<td>event.clientX / clientY</td>
<td>鼠标事件触发的x、y坐标</td>
</tr>
<tr>
<td><strong>✅Event 方法</strong></td>
<td><br></td>
</tr>
<tr>
<td><strong>stopPropagation</strong>()</td>
<td><strong>停止向上冒泡</strong>(propagation /ˌprɒpəˈɡeɪʃn/ 传播),不影响当前元素的其他注册事件</td>
</tr>
<tr>
<td><strong>stopImmediatePropagation</strong>()</td>
<td><strong>取消后面的同类型事件的执行,包括冒泡</strong>,(Immediate/ɪˈmiːdiət/ 立刻)</td>
</tr>
<tr>
<td><strong>preventDefault</strong>()</td>
<td><strong>取消默认事件行为</strong>,如checkbox、<code>&lt;a&gt;</code>,不影响冒泡。<strong><code>defaultPrevented</code></strong> 判断是否取消了</td>
</tr>
</tbody>
</table>
<p>使用<code>event.preventDefault()</code> 可以移除浏览器的默认事件行为,也可以用<code>return false</code>。</p>
<pre><code class="language-html">&lt;p&gt;
    &lt;input type="checkbox" onclick="return false"&gt;
    &lt;!--取消默认事件行为:点击无效了--&gt;
    &lt;a href="http://www.qq.com" id="qq1" onclick="return false"&gt;QQ-1&lt;/a&gt;
    &lt;a href="http://www.qq.com" id="qq2"&gt;QQ-2&lt;/a&gt;
    &lt;a href="http://www.qq.com" id="qq3"&gt;QQ-3&lt;/a&gt;
&lt;/p&gt;
&lt;script&gt;
    //return false 对a标签好像没有作用
    qq1.addEventListener("click", () =&gt; false);
    qq2.addEventListener("click", (event) =&gt; event.preventDefault()); //取消默认事件行为
    qq3.addEventListener("click", (event) =&gt; {
      if (!confirm("你确定已满18周岁,要前往[ " + event.target.getAttribute("href") + " ] 吗?")) {
            event.preventDefault(); //取消默认事件行为prevent /prɪˈvent/ 阻止
      }
    });
&lt;/script&gt;
</code></pre>
<h2 id="14事件流冒泡和捕获">1.4、事件流:冒泡和捕获</h2>
<p><strong>事件的触发</strong>大都是某一个HTML元素,但这一个元素触发事件时,该事件会在该元素与根节点之间进行顺序传播,路过的元素都会接收到该事件,这个过程称为“事件流”,简单来说就是<strong>接收事件的顺序</strong>,如下三个阶段。</p>
<p><strong>① 捕获阶段</strong>(Capturing phase):(phase /feɪz/ 阶段)</p>
<p><strong>事件</strong>(从 Window)逐级向下传播,直到具体的目标元素。捕获阶段实际上很少使用,默认情况下也不会触发,<strong>addEventListener</strong> 注册事件时通过参数对象<code>options.capture = true</code>设置在捕获阶段触发事件。<code>ediv.addEventListener("click", fevent2, true /* { capture: true } */); </code></p>
<p><strong>② 目标阶段</strong>(Target phase):事件到达目标元素。</p>
<blockquote>
<p><strong>❗目标元素</strong> <strong><code>event.target</code></strong>:直接触发事件的、最近的那个元素,也是嵌套最深的那个元素。</p>
</blockquote>
<p><strong>③ 冒泡阶段</strong>(Bubbling phase):一般常用的是冒泡阶段,这更符合逻辑。</p>
<p>事件从目标元素上开始冒泡,逐级向上春波,直到根节点。几乎所有事件都会冒泡,除了个别的,如<code>blur</code>、<code>focus</code>没有冒泡。</p>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114205539404-667150167.png" alt="image" loading="lazy"></p>
<pre><code class="language-html">&lt;div id="ediv"&gt;
    &lt;button id="ebutton"&gt;button&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
    const eles = document.querySelectorAll("#ediv,#ebutton");
    for (let ele of eles) {
      ele.addEventListener("click", e =&gt; console.log("capturing:" + e.currentTarget.localName), true); //捕获
      ele.addEventListener("click", e =&gt; console.log("bubbling:" + e.currentTarget.tagName)); //冒泡
    }
    /*
    capturing:div
    capturing:button
    bubbling:BUTTON
    bubbling:DIV */
&lt;/script&gt;
</code></pre>
<p>事件流的两种传播方式其实是IE和Netscape两个公司的不同处理机制导致的。</p>
<blockquote>
<p><strong>📢 停止冒泡</strong>:<code>stopPropagation()</code>、<code>stopImmediatePropagation()</code></p>
<ul>
<li><strong>注意的区别</strong>,<code>stopPropagation()</code>只是停止向上冒泡;<code>stopImmediatePropagation()</code>会额外取消当前元素同类型的后续事件。</li>
<li><strong>非必要不主动关闭冒泡</strong>,谨慎使用,可能会影响其他功能。</li>
</ul>
</blockquote>
<h2 id="15事件委托">1.5、事件委托</h2>
<p><strong>事件委托</strong>只是事件的一种使用方式而已,基于事件冒泡在,上级节点统一处理从而简化事件的绑定。比如有一堆导航按钮,不需要每个都添加事件,把点击事件委托给其父级元素统一处理。</p>
<ul>
<li><strong>优点</strong>:简化代码逻辑,便于修改维护。</li>
<li><strong>缺点</strong>:事件必须冒泡,如果被阻止了,就嗝屁了;可以忽略的冒泡性能损失。</li>
</ul>
<p>表格排序示例(委托给表格统一处理):codePen地址</p>
<pre><code class="language-javascript">//需求:点击表格标题,对数据进行排序
const table = document.querySelector("#grid");
table.onclick = function (e) {
//点击标题单元格,并且有自定义排序属性
if (e.target.tagName != "TH" || !e.target.hasAttribute("data-sort")) return;
let th = e.target;
sortTable(th.cellIndex, th.dataset.sort);
};
function sortTable(colIndex, type) {
let trs = Array.from(document.querySelectorAll("#grid tbody tr"));
let tbody = table.tBodies;
let sortFunc = function (r1, r2) {
    switch (type) {
      case "number":
      return r1.cells.innerText - r2.cells.innerText;
      break;
      case "number":
      default:
      return r1.cells.innerText &gt; r2.cells.innerText? 1: -1;
      break;
    }
};
trs = trs.sort(sortFunc);
tbody.append(...trs); //追加已存在的元素,自动进行移动
}
</code></pre>
<p>全局提示示例:点击查看【codepen】</p>
<h2 id="16自定义事件">1.6、自定义事件</h2>
<p><strong>① 创建事件对象</strong>:<code>let event = new Event(type[, options])</code> ,使用Event构造函数,或者<code>CustomEvent</code>自定义事件(参数中有一个<code>detail</code>字段可存放自定义数据,在事件处理程序中通过<code>event.detail</code>使用),或其他事件对象MouseEvent、KeyboardEvent。</p>
<ul>
<li><strong>type</strong>:事件类型,可以是像 "click" 这样的字符串或任意。</li>
<li><strong>options</strong>:具有两个可选属性的对象,是否冒泡<code>bubbles</code>(true=冒泡、false),是否取消默认行为<code>ancelable</code>: (true=阻止、false),默认值都是false。</li>
</ul>
<p><strong>②触发事件</strong>:<code>elem.dispatchEvent(event)</code></p>
<p>在你需要的地方调用<code>elem.dispatchEvent(event)</code>触发自定义事件,事件的处理程序和普通事件一样通过<code>addEventListener</code>添加,不支持<code>on***</code>。</p>
<pre><code class="language-html">&lt;p&gt;
&lt;input type="text" id="input"&gt;
&lt;/p&gt;
&lt;script&gt;
//1、定义事件:当按下F4按钮时触发
let keyF4Click = new CustomEvent("keyF4Click", { detail: { key: "F4" } })
input.addEventListener("keyup", (event =&gt; {
    if (event.key == "F4")
      //2、触发事件
      input.dispatchEvent(keyF4Click);
}))
//只能通过addEventListener添加自定义的事件处理程序
input.addEventListener("keyF4Click", (e) =&gt; {
    input.value += e.detail.key;
})
&lt;/script&gt;
</code></pre>
<hr>
<h1 id="02ui事件">02、UI事件⚡</h1>
<h2 id="22鼠标事件mouseevent">2.2、鼠标事件MouseEvent</h2>
<table>
<thead>
<tr>
<th><strong>鼠标事件</strong>(event)</th>
<th><br></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>click</strong>(event)</td>
<td>点击触发,通常是鼠标左键在一个元素上被按下并放开时</td>
</tr>
<tr>
<td>dblclick</td>
<td>双击触发事件</td>
</tr>
<tr>
<td>contextmenu</td>
<td>鼠标右键点击触发</td>
</tr>
<tr>
<td><strong>mousedown</strong>、<strong>mouseup</strong></td>
<td>鼠标按下、弹起时触发</td>
</tr>
<tr>
<td><strong>mousemove</strong></td>
<td>鼠标在元素上移动时触发</td>
</tr>
<tr>
<td><strong>onmouseover</strong>、<strong>mouseout</strong></td>
<td>鼠标移入、移出元素区域时触发</td>
</tr>
<tr>
<td>mouseenter、mouseleave</td>
<td>鼠标移入、移出元素区域时触发,与上面不同的是不会冒泡</td>
</tr>
<tr>
<td>dragstart、dragend</td>
<td>拖放事件(drag/dræɡ/拖)</td>
</tr>
</tbody>
</table>
<p><strong>鼠标事件响应顺序</strong>:<code>mouseenter</code><strong>→</strong> <code>mousemove</code><strong>→</strong><code>mousedown</code><strong>→</strong> <code>mouseup </code>→ <code>click</code> <strong>→</strong> <code>mouseleave</code></p>
<pre><code class="language-html">&lt;button id="btn" &gt;button&lt;/button&gt;
&lt;script&gt;      
    btn.addEventListener("mouseenter", (e)=&gt;console.log(1,e.type)); //1 'mouseenter'
    btn.addEventListener("mousemove", (e)=&gt;console.log(2,e.type));//2 'mousemove'
    btn.addEventListener("mousedown", (e)=&gt;console.log(3,e.type));//3 'mousedown'
    btn.addEventListener("mouseup", (e)=&gt;console.log(4,e.type));    //4 'mouseup'
    btn.addEventListener("click", (e)=&gt;console.log(5,e.type));      //5 'click'
    btn.addEventListener("mouseleave", (e)=&gt;console.log(6,e.type)); //6 'mouseleave'
&lt;/script&gt;
</code></pre>
<table>
<thead>
<tr>
<th><strong>MouseEvent</strong><strong>属性</strong></th>
<th><br></th>
</tr>
</thead>
<tbody>
<tr>
<td>button</td>
<td>鼠标按下的按钮:<strong>0</strong>=主按键/左键,<strong>1</strong>=滚轮中按键,<strong>2</strong>=次按键/右键</td>
</tr>
<tr>
<td>clientX / clientY</td>
<td>鼠标指针在窗口的 X 坐标、Y 坐标</td>
</tr>
<tr>
<td>pageX/pageY</td>
<td>鼠标指针在文档的 X 坐标、Y 坐标</td>
</tr>
<tr>
<td>ctrlKey、altKey、shiftKey</td>
<td>是否按下了<code>Ctrl</code>、<code>Alt</code>、<code>Shift</code>按键,bool值</td>
</tr>
<tr>
<td>metaKey</td>
<td>Mac中的 Cmd,同window的<code>Ctrl</code></td>
</tr>
<tr>
<td>relatedTarget</td>
<td>次要(关联)目标,鼠标移入/出中使用,表示上一个<code>target</code></td>
</tr>
</tbody>
</table>
<p>鼠标点击位置动画示例:codepen</p>
<pre><code class="language-html">&lt;style&gt;
    .mpoint {
      position: absolute;
      padding: 0; margin: 0;
      width: 200px; height: 200px;
      background-color: #dda427;
      border-radius: 50%;
      animation: click 1s;
    }
    @keyframes click {
      0% { transform: scale(0, 0); opacity: 0; }
      30% { transform: scale(1, 1); opacity: 1; }
      100% { transform: scale(0, 0); background-color: #7c20e4; opacity: 0; }
    }
&lt;/style&gt;
&lt;script&gt;
    let cdiv = document.createElement('div');
    //动画执行完后移除自身
    cdiv.addEventListener('animationend', () =&gt; cdiv.remove());
    window.addEventListener('click', (e) =&gt; {
      document.body.append(cdiv);
      cdiv.className = 'mpoint';
      //定位圆圈的位置,为鼠标点坐标
      cdiv.style.left = (e.clientX - cdiv.clientWidth / 2) + 'px';
      cdiv.style.top = (e.clientY - cdiv.clientHeight / 2) + 'px';
    });
&lt;/script&gt;
</code></pre>
<p>点击查看【codepen】</p>
<h2 id="23键盘事件keyboardevent">2.3、键盘事件KeyboardEvent</h2>
<table>
<thead>
<tr>
<th><strong>键盘事件</strong>(event)</th>
<th><br></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>keydown</strong><strong>、keyup</strong></td>
<td>键盘按键按下、松开时触发</td>
</tr>
<tr>
<td>过时的<code>keypress</code></td>
<td></td>
</tr>
</tbody>
</table>
<br>
<table>
<thead>
<tr>
<th><strong>KeyboardEvent</strong><strong>属性</strong></th>
<th><br></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>code</strong></td>
<td><strong>按键编码</strong>(KeyA、KeyA、F1、0、Shift),物理按键的准确编码,比较稳定</td>
</tr>
<tr>
<td><strong>key</strong></td>
<td><strong>按键值</strong>(A、a、F1、Digit0、ShiftLeft),正常看到的值,可能会随系统语言、输入环境变化</td>
</tr>
<tr>
<td>repeat</td>
<td>按键是否被一直按住,bool。按住时会一直触发<code>keydown</code></td>
</tr>
<tr>
<td>ctrlKey、altKey、shiftKey</td>
<td>是否按下了<code>Ctrl</code>、<code>Alt</code>、<code>Shift</code>按键,bool值</td>
</tr>
<tr>
<td>metaKey</td>
<td>Mac中的 Cmd,同window的<code>Ctrl</code></td>
</tr>
</tbody>
</table>
<hr>
<h1 id="03表单事件">03、表单事件⚡</h1>
<h2 id="31表单查找取值">3.1、表单查找/取值</h2>
<p><strong>🔸获取表单</strong><code>&lt;form&gt;</code>,<code>&lt;form name="formName"&gt;</code> 除了元素查找还有如下方式</p>
<ul>
<li><strong>属性访问</strong>:<code>document.formName</code>,</li>
<li><strong>forms属性</strong>:<code>document.forms</code>为文档中所有表单集合。</li>
</ul>
<pre><code class="language-html">&lt;form name="loginForm"&gt;&lt;input type="text"&gt;&lt;/form&gt;
&lt;script&gt;
    document.loginForm;
    document.forms.loginForm;
    document.forms['loginForm'];
    document.forms;
&lt;/script&gt;
</code></pre>
<p><strong>🔸获取表单元素</strong>:</p>
<ul>
<li><code>form.name</code></li>
<li><code>form.elements</code>集合,不用管元素的层级
<ul>
<li>form.<strong>elements</strong>.<strong>name</strong>,单个元素</li>
<li>form.<strong>elements</strong>['<strong>name</strong>'],元素名为<code>name</code>的集合,组合元素使用。</li>
</ul>
</li>
<li><strong>子表单</strong><code>fieldset.elements</code></li>
</ul>
<blockquote>
<p>❗表单和表单元素的双向引用:<br><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114204631513-1659367113.png" alt="image.png" loading="lazy"></p>
</blockquote>
<p><strong>🔸表单元素取值</strong>:<strong>input.value</strong>,<code>&lt;input&gt;</code>表单元素大部分都是<code>value</code>取值/赋值,注意下面的:</p>
<ul>
<li><strong>input.checked</strong>,单选<code>radio</code>、多选<code>checkbox</code>通过<code>checked</code>取值/赋值,多个需要遍历取值。</li>
<li><strong>textarea.value</strong>,⚠️注意多行文本<code>&lt;textarea&gt;</code>是通过<code>value</code>取值,而不是<code>innerHTML</code>。</li>
<li>下拉框<strong>select</strong>:select.options =<code>&lt;option&gt; </code>的子元素的集合
<ul>
<li><strong>单选</strong>:<code>select.value</code>、<code>select.selectedIndex</code></li>
<li><strong>多选</strong>:遍历<code>options</code>取值,<code>Array.from(select.options).filter(op=&gt;op.select).map(op=&gt;op.value);</code></li>
</ul>
</li>
</ul>
<p><strong>🔸提交表单</strong>:</p>
<ul>
<li>document.loginForm.<strong>submit</strong>():表单的<code>submit()</code>方法提交,完全自主控制,推荐食用。</li>
<li><strong>submit按钮+事件onclick=return 校验函数()</strong>:校验函数校验表单数据,返回true提交表单,否则不提交</li>
</ul>
<p><code>&lt;button type="submit" onclick="return canSubmit()"&gt;</code></p>
<ul>
<li><strong>submit按钮+form</strong>的事件<strong>onsubmit=return 校验函数()</strong>:功能和用法基本同上。</li>
</ul>
<pre><code class="language-html">&lt;form name="fuser" id="fuser" action="" method="post"&gt;
    姓名:&lt;input name="userName" type="text" title="请输入用户名" /&gt;&lt;br /&gt;
    密码:&lt;input name="userPwd" type="password" title="请输入密码" /&gt;&lt;br /&gt;
    生日:&lt;input name="userBirthday" type="date" value="2021-10-11" /&gt;&lt;br /&gt;
    性别:&lt;input name="sex" id="usex1" type="radio" value="男" checked=true /&gt;&lt;label for="usex1"&gt;男&lt;/label&gt;
    &lt;input name="sex" id="usex2" type="radio" value="女" /&gt;&lt;label for="usex2"&gt;女&lt;/label&gt;
    &lt;input name="sex" id="usex3" type="radio" value="其他" /&gt;&lt;label for="usex3"&gt;其他&lt;/label&gt;&lt;br /&gt;
    爱好:&lt;input id="uint1" name="interest" type="checkbox" value="运动" /&gt;&lt;label for="uint1"&gt;运动&lt;/label&gt;
    &lt;input id="uint2" name="interest" type="checkbox" value="学习" /&gt;&lt;label for="uint2"&gt;学习&lt;/label&gt;
    &lt;input id="uint3" name="interest" type="checkbox" value="看书" /&gt;&lt;label for="uint3"&gt;看书&lt;/label&gt;
    &lt;input id="uint4" name="interest" type="checkbox" value="躺着" /&gt;&lt;label for="uint4"&gt;躺着&lt;/label&gt;&lt;br /&gt;
    学历:&lt;select id="education" name="education"&gt;
      &lt;option value="大专"&gt;大专&lt;/option&gt;
      &lt;option value="本科"&gt;本科&lt;/option&gt;
      &lt;option value="研究生"&gt;研究生&lt;/option&gt;
    &lt;/select&gt;&lt;br /&gt;
    &lt;button type="button" onclick="getData()"&gt;获取数据&lt;/button&gt;
&lt;/form&gt;
</code></pre>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114204631530-1008807869.png" alt="image.png" loading="lazy"></p>
<pre><code class="language-javascript">&lt;script&gt;
    var form = document.fuser;
function getData() {
    var form = document.fuser;
    var userData = {};
    userData.userName = form.userName.value;
    userData.userPwd = form.userPwd.value;
    userData.userBirthday = form.userBirthday.value;
    //单选、多选,注意设置name、value值,遍历取值
    userData.sex = Array.from(document.getElementsByName('sex'))
      .filter(n =&gt; n.checked)?.value
    userData.interest = Array.from(document.getElementsByName('interest'))
      .filter(n =&gt; n.checked).map(n=&gt;n.value).join();
    //下拉框取值
    userData.education = form.education.value;
    userData.education = form.education.options.value;
    console.log(JSON.stringify(userData));
};
getData();
&lt;/script&gt;
</code></pre>
<h2 id="32表单事件">3.2、表单事件</h2>
<table>
<thead>
<tr>
<th><strong>✅表单事件</strong>(event)</th>
<th><br></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>blur</strong>(event)、focusout()</td>
<td>元素失去焦点,<strong>blur</strong>不会冒泡 (blue /blɜːr/ 模糊 /不乐/)</td>
</tr>
<tr>
<td><strong>focus</strong>、focusin</td>
<td>元素获取焦点时触发,<strong>focus</strong>不会冒泡</td>
</tr>
<tr>
<td>from.<strong>submit</strong></td>
<td>提交表单form时触发,可用于表单校验</td>
</tr>
<tr>
<td><strong>change</strong></td>
<td>值发生变化时触发,文本框是在值变化且失去焦点是才触发</td>
</tr>
<tr>
<td><strong>input</strong></td>
<td>输入值改变时触发。event.preventDefault()无法阻止,因为已经改变了</td>
</tr>
<tr>
<td><strong>✅方法-聚焦</strong></td>
<td><br></td>
</tr>
<tr>
<td>elem.focus()</td>
<td>设置元素获得焦点</td>
</tr>
<tr>
<td>elem.blur()</td>
<td>设置元素失去焦点</td>
</tr>
</tbody>
</table>
<p>可编辑单元格的表格示例:codepen</p>
<hr>
<blockquote>
<p><strong>©️版权申明</strong>:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!<em>原文编辑地址-语雀</em></p>
</blockquote><br><br>
来源:https://www.cnblogs.com/anding/p/16890365.html
頁: [1]
查看完整版本: JavaScript入门⑧-事件总结大全