FrankKai / FrankKai.github.io

FE blog
https://frankkai.github.io/
363 stars 39 forks source link

一些低调的HTML事件 #96

Open FrankKai opened 5 years ago

FrankKai commented 5 years ago

起源于对input的change事件的困惑,因此特地开一个issue记录遇到的浏览器事件。

FrankKai commented 5 years ago

input事件

<input type="text">有两个事件,一个是input,一个是change。 这两个事件是非常非常重要的两个事件,可以说与click是旗鼓相当的重要程度。 所以特地开此issue系统性学习input事件。

input事件会由哪些标签触发?

<input> <select> <textarea>。当它们的value发生改变时,会触发这个事件。

input事件在开启contenteditable后也可以使用吗?打开designMode的可以吗?

都可以。

contenteditable和designMode下,event target是什么?如何表现?

editing host。 如果这些属性被设置到多个元素,editing host是父元素不可编辑的,最近的祖先元素。

type=checkbox或type=radio的元素,input事件怎么表现?

input理应会在toggle时触发。 但是由于浏览器兼容性问题,有时可能替换成change事件。

input事件和change事件的区别是什么?

input事件在元素的值每次发生变化时都会触发。 而change事件只有在commit时才会提交,比如通过enter提交,选中某一项等等。

其它

是否可冒泡?Yes。 是否可取消?No。 接口:InputEvent。 事件处理属性:GlobalEventHandlers.oninput。

一个简单的使用<input>的例子

<input placeholder="Enter some text" name="name"/>
<p id="values"></p>
const input = document.querySelector('input');
const log = document.getElementById('values');

input.addEventListener('input', updateValue);

function updateValue(e) {
  log.textContent = e.target.value; // e.target.value是input标签的value值
}
FrankKai commented 5 years ago

change事件

<input type="text">有两个事件,一个是input,一个是change。 这两个事件是非常非常重要的两个事件,可以说与click是旗鼓相当的重要程度。 所以特地开此issue系统性学习change事件。

什么时候会触发change事件?

<input> <select> <textarea>。 在用户修改了元素的值并且提交了修改,change事件会触发。 与每次修改都去触发事件的input事件不同。

几个触发change事件的示例

浏览器兼容性怎样?

在Gecko内核下,通过键盘改变<select>的navigation,不会直接fire一个change事件,只有在用户按下Enter或者从当前选中的select失去焦点才会fire。

哪些<input>的type类型可以fire change事件?

可以参阅规范https://html.spec.whatwg.org/multipage/input.html#concept-input-apply,明确告诉我们哪些type可以发射change事件。

Hidden Text,Search URL,Telephone E-mail Password Date,Month,Week,Time LocalDate and Time Number Range Color Checkbox,Radio,Button FileUpload SubmitButton ImageButton Reset Button,Button
· Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes · · ·

image https://html.spec.whatwg.org/multipage/input.html#concept-input-apply

select例子

<label>Choose an ice cream flavor:
  <select class="ice-cream" name="ice-cream">
    <option value="">Select One …</option>
    <option value="chocolate">Chocolate</option>
    <option value="sardine">Sardine</option>
    <option value="vanilla">Vanilla</option>
  </select>
</label>

<div class="result"></div>
const selectElement = document.querySelector('.ice-cream');

selectElement.addEventListener('change', (event) => {
  const result = document.querySelector('.result');
  result.textContent = `You like ${event.target.value}`;
});

input例子

<input placeholder="Enter some text" name="name"/>
<p id="log"></p>
const input = document.querySelector('input');
const log = document.getElementById('log');

input.addEventListener('change', updateValue) // change事件可以在回车,失焦的时候触发

function updateValue(e) {
  log.textContent = e.target.value;
}

vue中测试<input>的change事件只要输入值变化就会触发吗?

<template>
  <input
    @input="handleInput"
    @change="handleChange"/>
</template>

<script>
export default {
  name: 'change',
  methods: {
    handleInput(e) {
      console.log('触发了input事件', e.target.value);
    },
    handleChange(e) {
      console.log('触发了change事件', e.target.value);
    },
  },
};
</script>

不是。 只有当鼠标失去焦点的时候才会触发change事件,而input事件是只要输入值变化就会触发。

其它

是否可冒泡?Yes。 是否可取消?No。 接口:Event。 事件处理属性:onchange。

FrankKai commented 4 years ago

hashchange事件

hashchange事件会在URL的fragment identifier发生变化时发射,fragment identifier是指URL的#的部分,包括#符号。

// 触发haschange的changeHash函数,它改变了localtion.hash的值
function changeHash() {
    location.hash = (Math.random() > 0.5) ? "666" : "777";
}
// hashchange事件触发后的事件处理函数
function HashHandler() {
    console.log("The Hash has changed!");
}
// window对象监听hashchange事件,其实也就是location.hash的值的变化
window.addEventListener("hashchange", HashHandler, false);

运行:changeHash();
结果:https://foo.com#/666->https://foo.com/#/777

用途:

FrankKai commented 2 years ago

DOMContentLoaded事件 vs load事件

DOMContentLoaded

HTML文档完成加载和解析,无需等待样式表,图片,iframe加载完成。

window.addEventListener('DOMContentLoaded', (event) => {
    console.log('DOM fully loaded and parsed');
});

load

HTML页面及所有依赖完全加载,包含样式表,图片,iframe加载完成。

window.addEventListener('load', (event) => {
  console.log('page is fully loaded');
});