文章目录
text输入框
<input type="text" name='name'>
DOM操作
- 设置文本框的值
input.value='hello world'
- 获取文本框的值
input.value
<body>
<input type="text" name='name'>
<script>
var elm = document.querySelector('input');
input.value='hello world';
console.log(input.value);
</script>
</body>
相关事件
input
事件
文本框中输入文本时触发change
事件
文本框中输入的文本改变,且失去焦点(或回车)时触发
<body>
<input type="text" name='name' id='name' autocomplete="off">
<script>
var elm = document.getElementById('name');
elm.oninput = function(e){
console.log(e.type,e.target.value);
}
elm.onchange = function(e){
console.log(e.type,e.target.value);
}
</script>
</body>
textInput
事件
文本框内输入文本时触发。
和input
事件什么区别?
textInput
事件处理程序只能用DOM2级方法
写(elm.addEventListener
)。
input
事件处理程序既可以用DOM2级方法
写,也可以用DOM0级方法
写(elm.onInput
)
还有么?
呃,没太懂?那试试 拼音输入法吧。
<body>
<input type="text" name='name' id='name' autocomplete="off">
<script>
var elm = document.getElementById('name');
elm.oninput = function(e){
console.log(e.type,e.target.value);
}
const handleTextInput = function(e){
console.log(e.type,e.target.value);
}
elm.addEventListener('textInput',handleTextInput,false);
</script>
</body>
说到 拼音输入法,忽然想到 复合事件。
compositionstart
事件compositionupdate
事件compositionend
事件
<body>
<!-- <div id="root"></div> -->
<input type="text" name='name' id='name' autocomplete="off">
<script>
var elm = document.getElementById('name');
const handleCompositionStart = function(e){
console.log(e.type,e.target.value);
}
const handleCompositionUpdate = function(e){
console.log(e.type,e.target.value);
}
const handleCompositionEnd = function(e){
console.log(e.type,e.target.value);
}
elm.addEventListener('compositionstart',handleCompositionStart,false);
elm.addEventListener('compositionupdate',handleCompositionUpdate,false);
elm.addEventListener('compositionend',handleCompositionEnd,false);
</script>
</body>
keypress
事件
按下键盘字符键触发keydown
事件
按下键盘任意键都会触发
<body>
<div id="root"></div>
<input type="text" name='name' id='name' autocomplete="off">
<script>
var elm = document.getElementById('name');
elm.onkeypress = function(e){
console.log(e.type,e.key);
}
elm.onkeydown = function(e){
console.log(e.type,e.key);
}
</script>
</body>
focus
事件
获得焦点时触发blur
事件
失去焦点时触发
<body>
<input type="text" name='name' id='name' autocomplete="off">
<script>
var elm = document.getElementById('name');
elm.onfocus = function(e){
console.log(e.currentTarget,'get focus');
}
elm.onblur = function(e){
console.log(e.currentTarget,'lost focus');
}
</script>
</body>
select
事件
选中输入框中的文本时触发
<body>
<input type="text" name='name' id='name' autocomplete="off">
<script>
var elm = document.getElementById('name');
elm.onselect = function(e){
var value = e.currentTarget.value;
var startIndex = e.currentTarget.selectionStart;
var endIndex = e.currentTarget.selectionEnd;
console.log('选中文本:',value.slice(startIndex,endIndex));
}
</script>
</body>
相关方法
focus()
使获得焦点
//页面也加载,就将焦点转移至表单的第一个字段
<body>
<input type="text" name='name' id='name' autocomplete="off">
<script>
window.onload = function(){
var elm = document.getElementById('name');
elm.focus();
}
</script>
</body>
blur()
使失去焦点select()
选中全部文本
//页面一加载,就将焦点转移至第一个表单字段
//表单字段一获得焦点,就将框内的文本全部选中,方便用户删除并重新输入
<body>
<input type="text" name='name' id='name' autocomplete="off" value='Nicholas'>
<script>
var elm = document.getElementById('name');
window.onload = function(){
elm.focus();
}
elm.onfocus = function(){
elm.select();
}
</script>
</body>
相关属性
autofocus
自动聚焦
<input type="text" name='name' id='name' value='Nicholas' autofocus>
autocomplete
自动完成,也就是显示之前输入的值。
有两个值:on
和off
,默认是on
。
<input type="text" name='name' id='name' value='Nicholas' autocomplete="off" >
submit按钮
生成提交按钮,有以下三种方式。
- 第一种:
input[type='submit']
<input type="submit" value='提交'>
- 第二种:
button[type='submit']
<button type='submit'>提交</button>
- 第三种:
input[type='image']
<input type="image" src='./imgs/submit.jpg'>
注意:不论以何种方式生成提交按钮,提交按钮必须嵌在form
标签里,否则点击提交按钮无法提交表单数据。
相关事件
submit
事件
点击提交按钮时触发
submit
事件发生后,会发送http请求,并刷新页面
http请求是get
还是post
,取决于form
标签上的method
属性值;
http请求发给谁,form
标签上action
属性说了算。
想了解更多,请移步表单Demo。
<body>
<form method='post' action='/addUser'>
<label>名字: <input type="text" name='name'></label>
<label>密码: <input type='password' name='pass' /></label>
<input type="submit" value='注册'>
</form>
<script>
var form = document.forms[0];
form.onsubmit = function(e){
console.log(e.type);
}
</script>
</body>
相关方法
submit()
提交表单,但注意哈,不会触发submit
事件。
reset按钮
重置按钮和提交按钮的情况几乎一样,也有三种生成方式,只不过type
由submit
变成了reset
- 第一种,
input[type='reset']
<input type="reset" value="重置">
- 第二种,
button[type='reset']
<button type='reset'>重置</button>
- 第三种,
input[type='image']
<input type="image" src='./imgs/reset.jpg'>
相关事件
reset
事件
点击重置按钮时触发reset
事件,整个表单数据会被清空。
实际开发中,重置按钮用的不多,主要因为不实用。试想一下,你辛辛苦苦填了十几项,可能不小心重置了一下,一江春水付诸东流,不抓狂才怪。当然,你可以采用二次确认来避免用户的这种不小心。
<body>
<div id="root"></div>
<form>
<label>名字:<input type="text" name='name' id='name' autocomplete="off"></label>
<input type="reset" value="重置">
</form>
<script>
var form = document.forms[0];
form.onreset = function(e){
console.log(e.type);
}
</script>
</body>
相关方法
reset()
重置表单,也会触发reset
事件
选择框
相关属性
select
的属性select.type
有两个值:select-one
和select-multiple
。
select-one
是单选;select-multiple
是多选select.multiple
布尔值。多选是true
,单选是false
select.size
选择框可见的行数select.options
可选项select.selectedIndex
选中项所在索引,索引从0
开始
option
的属性option.selected
布尔值。选中是true
,没有选中是false
option.index
选项所在索引,索引从0
开始option.label
<option></option>
之间的文本值option.text
<option></option>
之间的文本值option.value
option
有value
属性,则取value
属性值;没有value
属性,则取<option></option>
之间的文本值。
<body>
<form action="">
<select name="fruits" id="fruits">
<option value="grapefruit">葡萄柚</option>
<option value="lime">酸橙</option>
<option value="coconut" selected >椰子</option>
<option value="mango">芒果</option>
</select>
<select name="citys" id="citys" size=4 multiple>
<option value="shenzhen" selected>深圳</option>
<option value="nanjing" selected>南京</option>
<option value="hanzhou">杭州</option>
<option value="nanchang">南昌</option>
</select>
</form>
<script>
var select = document.forms[0].elements[0];
var selectedOption = select.options[select.selectedIndex];
var multipleSelect = document.forms[0].elements[1];
var selectedOptions = Array.prototype.slice.call(multipleSelect.options).filter(option => option.selected);
console.log(selectedOptions);
</script>
</body>
- 获取选中项
单选时,比较简单,select.options[select.selecteIndex]
即可;
多选时,稍微复杂一点点,遍历option
,option.selected
为true
则返回,
Array.prototype.slice.call(multipleSelect.options).filter(option => option.selected)
相关事件
change
事件
选中项发生改变时触发
DOM操作
添加选项
首先,我们要生成一个新的option
,有两种方式。
//第一种,使用document.createElement
var option = document.createElement('option');
option.appendChild(document.createTextNode('大连'));
option.value = 'dalian';
//第二种,调用构造函数Option
var option = new Option('大连','dalian');
然后,将新的option
插入到选择框,也有两种方式。
//第一种,appendChild或insertBefore
select.appendChild(option);//插入末尾
//select.appendChild(option,select.options[1]);//插入指定位置
//第二种,调用add方法
select.add(option);//插入末尾
//select.add(option1,1);//插入指定位置
//select.add(option,select.options[1]);//插入指定位置
举例:新增选项 大连
<body>
<form action="">
<select name="citys" id="citys" size=4>
<option value="shenzhen">深圳</option>
<option value="nanjing">南京</option>
<option value="hanzhou">杭州</option>
</select>
</form>
<script>
var select = document.forms[0].elements[0];
var option = new Option('大连','dalian');
select.insertBefore(option,select.options[1]);
// select.add(option,1);
// select.add(option,select.options[1]);
</script>
</body>
删除选项
有三种方式
//第一种
select.removeChild(select.options[select.options.length-1]);
//第二种
select.remove(select.options.length-1);
//第三种
select.options[select.options.length-1] = null;
举例:删除选项 大连
<body>
<form action="">
<select name="citys" id="citys" size=4>
<option value="shenzhen">深圳</option>
<option value="nanjing">南京</option>
<option value="hanzhou">杭州</option>
<option value='dalian'>大连</option>
</select>
</form>
<script>
var select = document.forms[0].elements[0];
// select.removeChild(select.options[select.options.length-1]);
// select.remove(select.options.length-1);
select.options[select.options.length-1] = null;
</script>
</body>
移动选项
将已经存在的元素进行插入操作即可实现移动。
//杭州 这个选项 向前移动一个位置
var select = document.forms[0].elements[0];
var optionHZ = select.options[2];
select.insertBefore(optionHZ,select.options[optionHZ.index-1]);
//杭州 这个选项 向后移动一个位置
var select = document.forms[0].elements[0];
var optionHZ = select.options[2];
select.insertBefore(optionHZ,select.options[optionHZ.index+2]);
举例:将 杭州、大连 这两个选项交换位置
<body>
<form action="">
<select name="citys" id="citys" size=4>
<option value="shenzhen">深圳</option>
<option value="nanjing">南京</option>
<option value="hanzhou">杭州</option>
<option value='dalian'>大连</option>
</select>
</form>
<script>
var select = document.forms[0].elements[0];
var optionHZ = select.options[2];
var optionDL = select.options[select.options.length-1];
// select.appendChild(optionHZ);
// select.add(optionHZ);
select.insertBefore(optionDL,optionHZ);
</script>
</body>
自定义选择框的实现
//index.js
import React from "react";
import ReactDOM from "react-dom";
import './index.css';
function ListItem(props){
const {value,label} = props;
return (
<li value={value}>{label}</li>
)
}
class Selector extends React.Component{
constructor(props){
super(props);
// this.handleMouseDown = this.handleMouseDown.bind(this);
this.handleClick = this.handleClick.bind(this);
}
handleMouseDown(e){
this.props.selectItem(e.target.textContent);
}
handleClick(e){
this.props.selectItem(e.target.textContent);
}
render(){
const items = this.props.items;
return (
<ul className='selector'
// onMouseDown={this.handleMouseDown}
onClick={this.handleClick}
>
{
items.map(item => (
<ListItem key={item.value}
value={item.value}
label={item.label}/>
))
}
</ul>
)
}
}
class App extends React.Component{
constructor(props){
super(props);
this.state = {
value:'请选择',
isOpen:false
}
this.container = React.createRef();
this.handleClick = this.handleClick.bind(this);
this.handleOutsideClick = this.handleOutsideClick.bind(this);
// this.handleFocus = this.handleFocus.bind(this);
// this.handleBlur = this.handleBlur.bind(this);
this.selectItem = this.selectItem.bind(this);
}
// handleFocus(){
// clearTimeout(this.timeId);
// }
// handleBlur(){
// this.timeId = setTimeout(() => {
// this.setState({
// isOpen:false
// })
// })
// // },100)
// }
handleClick(){
this.setState(currentState => ({
isOpen:!currentState.isOpen
}))
}
handleOutsideClick(e){
if(this.state.isOpen && !this.container.current.contains(e.target)){
this.setState({
isOpen:false
})
}
}
selectItem(value){
this.setState({
value
})
}
componentDidMount(){
window.addEventListener('click',this.handleOutsideClick,false);
}
componentWillUnmount(){
window.removeEventListener('click',this.handleOutsideClick,false);
}
render(){
const {items} = this.props;
const {value,isOpen} = this.state;
return (
<div className='container' ref={this.container}
// onFocus={this.handleFocus}
// onBlur={this.handleBlur}
>
<input type='button'
value={value}
onClick={this.handleClick}
/>
{
isOpen && <Selector items={items}
selectItem={this.selectItem}/>
}
</div>
)
}
}
const items = [
{value:'sz',label:'深圳'},
{value:'hz',label:'杭州'},
{value:'nj',label:'南京'}
]
ReactDOM.render(
<App items={items}/>,
document.getElementById('root')
)
//index.css
.container{
display:inline-block;
}
.selector{
list-style:none;
margin:0px 15px;
padding:0px;
border:1px solid lightgrey;
width:80px;
text-align:left;
background-color:#fff;
box-shadow:1px 1px 1px grey;
font-size:14px;
border-radius: 2px;
position:absolute;
}
.selector li:hover{
cursor:pointer;
background:lightgrey;
}
.selector li{
padding-left:3px;
}
input{
display:block;
margin:5px;
}
无障碍访问的实现
鼠标操作时,整个功能是OK的,但键盘操作时,功能就有问题了。
- 鼠标操作
- 键盘操作
这是因为,键盘操作tab切换焦点不会触发click
事件,所以不会调用handleOutsideClick
来关闭选项。
于是添加blur
和focus
事件来修复以上问题。
在修复的过程中,遇到一个问题:blur
事件会先于click
触发,导致选项一被点击,选项面板就关闭了。
有两个解决方法。 setTimeout
的延时时间长一些,比如200ms
。
100ms
不够无法解决问题;500ms
长了点,反应迟钝。总之,延时时间不好确定,治标不治本。ul
上的click
事件改用mousedown
事件
效果好很多
主要是针对Selector
组件、App
组件的修改。
class Selector extends React.Component{
constructor(props){
super(props);
this.handleMouseDown = this.handleMouseDown.bind(this);
}
handleMouseDown(e){
this.props.selectItem(e.target.textContent);
}
render(){
const items = this.props.items;
return (
<ul className='selector'
onMouseDown={this.handleMouseDown}
>
{
items.map(item => (
<ListItem key={item.value}
value={item.value}
label={item.label}/>
))
}
</ul>
)
}
}
class App extends React.Component{
constructor(props){
super(props);
this.state = {
value:'请选择',
isOpen:false
}
this.container = React.createRef();
this.handleClick = this.handleClick.bind(this);
this.handleOutsideClick = this.handleOutsideClick.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.selectItem = this.selectItem.bind(this);
}
handleFocus(){
clearTimeout(this.timeId);
}
handleBlur(){
this.timeId = setTimeout(() => {
this.setState({
isOpen:false
})
})
}
handleClick(){
this.setState(currentState => ({
isOpen:!currentState.isOpen
}))
}
handleOutsideClick(e){
if(this.state.isOpen && !this.container.current.contains(e.target)){
this.setState({
isOpen:false
})
}
}
selectItem(value){
this.setState({
value
})
}
componentDidMount(){
window.addEventListener('click',this.handleOutsideClick,false);
}
componentWillUnmount(){
window.removeEventListener('click',this.handleOutsideClick,false);
}
render(){
const {items} = this.props;
const {value,isOpen} = this.state;
return (
<div className='container' ref={this.container}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
>
<input type='button'
value={value}
onClick={this.handleClick}
/>
{
isOpen && <Selector items={items}
selectItem={this.selectItem}/>
}
</div>
)
}
}