{"action":"opened","issue":{"url":"https://api.github.com/repos/tcatche/tcatche.github.io/issues/82","repository_url":"https://api.github.com/repos/tcatche/tcatche.github.io","labels_url":"https://api.github.com/repos/tcatche/tcatche.github.io/issues/82/labels{/name}","comments_url":"https://api.github.com/repos/tcatche/tcatche.github.io/issues/82/comments","events_url":"https://api.github.com/repos/tcatche/tcatche.github.io/issues/82/events","html_url":"https://github.com/tcatche/tcatche.github.io/issues/82","id":294619708,"number":82,"title":"JavaScript 常用事件之表单事件","user":{"login":"tcatche","id":7147399,"avatar_url":"https://avatars3.githubusercontent.com/u/7147399?v=4","gravatar_id":"","url":"https://api.github.com/users/tcatche","html_url":"https://github.com/tcatche","followers_url":"https://api.github.com/users/tcatche/followers","following_url":"https://api.github.com/users/tcatche/following{/other_user}","gists_url":"https://api.github.com/users/tcatche/gists{/gist_id}","starred_url":"https://api.github.com/users/tcatche/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tcatche/subscriptions","organizations_url":"https://api.github.com/users/tcatche/orgs","repos_url":"https://api.github.com/users/tcatche/repos","events_url":"https://api.github.com/users/tcatche/events{/privacy}","received_events_url":"https://api.github.com/users/tcatche/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-02-06T03:23:40Z","updated_at":"2018-02-06T03:23:40Z","closed_at":null,"author_association":"OWNER","body":"**本文博客地址：[JavaScript 常用事件之表单事件](http://tcatche.site/2018/01/broswer_common_form_event/).**\n\n\n和表单元素相关的事件有：`change`、`input`、`compositionstart/compositionupdate/compositionend`、`focusin/focus`、`focusout/blur`、`submit`。\n\n## change\n\n`change` 事件可以被 `<input>`、`<textarea>`、`<select>`、`checkbox/radio` 元素触发,.\n\n**注意**，对于文本输入内容的改变，也就是说在文本域（input、textarea）输入内容时候，该事件不会触发，直到当文本元素**失去焦点** 时，触发该事件。\n\n对于 `<select>`、`checkbox/radio` 则只要发生变化就能正常触发该事件。\n\n## input\n\n这个事件和上一个事件相似也是处理表单元素的变化：当 `<input>`、`<textarea>`、`<select>` 元素的值更改时，`input` 事件会同步的触发。\n\n如果想要处理 `<input>`、`<textarea>` 的每个修改，那么这个事件是最好的：\n\n```html\n<!-- 每次修改，并不会弹出对话框，直到该元素失去焦点才弹出 -->\n<input type=\"text\" onchange=\"alert(this.value)\" />\n\n<!-- 每次修改，即弹出对话框，并且弹出动作发生在元素改变之前 -->\n<input type=\"text\" oninput=\"alert(this.value)\" />\n```\n\n而对于 `checkbox/radio` 元素，当用户单击控件时，`input` 事件不会触发，因为 `value` 属性没有更改。\n\n```html\n<!-- 每次修改，并不会弹出对话框，直到该元素失去焦点才弹出 -->\n<input type=\"checkbox\" onchange=\"alert('Everytime click, This will alert current value：' + this.value)\" />\n\n<!-- 每次修改，即弹出对话框，并且弹出动作发生在元素改变之前 -->\n<input type=\"checkbox\" oninput=\"alert('This will never alert!!!')\" />\n```\n\n一些键盘事件如 `keyup`、`keypress` 也可以用来监控文本的改变，但是键盘事件对于控制键，比如 `Ctrl`、 `Shift` 等也会触发。\n\n**注意**：这个事件的 `Cancelable` 值为 `false`。因此无法取消，`event.preventDefault()` 不起作用。\n\n## compositionstart、compositionupdate、compositionend\n\n当我们在使用 `input` 或者 `keyup` 事件监控用户的输入的时候，当用户的输入语言是中文的时候，会出现一些问题，比如用户输入“事件”，如果我们监控了 `input` 事件，则实际上会导致了多次触发事件，比如下面这个例子：\n\n用户使用中文输入法输入 “shijian” 并选中 “事件” 词语，控制台会打印以下结果：\n\n```js\nele.addEventListener('input', function (e) {\n  console.log(value);\n});\n\n// s\n// sh\n// shi\n// shij\n// shiji\n// shijia\n// shijian\n// 事件\n```\n\n如果我们根据用户的输入实时向服务端查询数据，则发出了多个无效查询，这堆拼音并不是我们想要查询的内容，我们想要处理的输入文本是“事件”，这个时候，这几个事件就派上了用场。\n\n首先看一下这三个事件在 MDN 的描述：\n\n- `compositionstart`：事件触发于一段内容的输入之前（类似于 keydown 事件，但是该事件仅在若干可见字符的输入之前，而这些可见字符的输入可能需要一连串的键盘操作、语音识别或者点击输入法的备选词。\n- `compositionupdate`：事件触发于内容被输入到一段文字的时候（此时类似于 input 事件，这些可见字符的输入可能需要一连串的键盘操作、语音识别或者点击输入法的备选词）。\n- `compositionend`：事件触发于一段文字的输入之后。\n\n再来看一下事件触发顺序：\n\n```js\nele.addEventListener('keydown', function (e) {\n  console.log('keydown');\n});\nele.addEventListener('keyup', function (e) {\n  console.log('keyup');\n});\nele.addEventListener('compositionstart', function (e) {\n  console.log('compositionstart');\n});\nele.addEventListener('compositionupdate', function (e) {\n  console.log('compositionupdate');\n});\nele.addEventListener('compositionend', function (e) {\n  console.log('compositionend');\n});\nele.addEventListener('input', function (e) {\n  console.log('input');\n});\n\n// 当开始输入中文的时候，触发一次 compositionstart：\n// keydown\n// compositionstart\n// compositionupdate\n// input\n// keyup\n// 输入中间字符，循环开始\n// keydown\n// compositionupdate\n// input\n// keyup\n// 输入最后一个字符，循环结束，注意 compositionend 事件是在 input 之后 keyup 之前触发。\n// keydown\n// compositionupdate\n// input\n// compositionend\n// keyup\n```\n\n知道了这些内容，这样我们就可以这样解决上面的问题：\n\n```js\nfunction inputListener(ele, callback) {\n  let inputing = false;\n  elem.addEventListener('compositionstart', function (e) {\n    inputing = true;\n  });\n  elem.addEventListener('compositionend', function (e) {\n    inputing = false;\n\n    // compositionend 事件在 input 事件之后触发，所以需要在此调用事件处理用户输入\n    // 如果是处理 keyup 事件，由于 keyup 事件在 compositionend 之后触发，则不要调用 callback\n    callback(e);\n  });\n  elem.addEventListener('input', function (e) {\n    if (inputing) return;\n    callback(e);\n  });\n}\n\ninputListener(ele, function (e) {\n  console.log(value);\n});\n\n// 使用中文输入法输入 “shijian” 并选中 “事件” 词语，控制台会打印以下结果\n// 事件\n```\n\n## focusin、focus 与 focusout、blur\n\n当元素获得焦点的时候可以触发 `focusin`、`focus`，两者不同之处在于 `focusin` 事件冒泡 `focus` 事件不冒泡，而同理，元素失去焦点的时候可以触发 `focusout`、`blur`，两者不同之处在于 `focusout` 事件冒泡 `blur` 事件不冒泡。\n\n注意，并不是所有元素都支持这几个事件的。\n\n## submit\n\n执行提交表单的行为触发的事件。\n\n触发表单事件有三种方式：\n\n- 点击 `<input type=\"submit\">`、 `<input type=\"image\">` (`type=\"image\"` 是图形的提交按钮)\n- 在表单域按(input,textarea 等) `Enter` 键\n- 调用 `form.submit()`\n\n使用 `event.preventDefault()` 可以阻止数据被提交。\n\n**注意**，在表单元素使用 `Enter` 提交表单的时候，会触发提交按钮的上的一个点击事件，尽管并没有发生点击：\n\n```html\n<form>\n <input type=\"text\" value=\"Focus here and press enter.\">\n <input type=\"submit\" value=\"Submit\" onclick=\"alert('click event triggered')\">\n</form>\n```\n"}}
{"actor":{"display_login":"tcatche"}}