@Form

. 通过种类多样的表单元素,以值对 name-value 的形式收集/采集数据,提交给后端服务器backend server处理
. 表单本身并不可见;表单元素可见
<form action="" method="" name=""></form>
类别 说明
action 表单提交后端处理;通常由服务器端脚本负责处理,如PHP或Node.js
method 表单提交的方式,常见有GET | POST;默认GET
GET:获取数据,数据地址栏可见;数据少,不安全;便于分享[绩效],通常使用各种ID来标记资源
POST:提交数据;数据不可见;数据多,安全;适合上传数据,如用户注册
name 区分页面中不同的表单
常见表单元素
. 表单元素类型很多,每个必须指定name,否则提交时无法获取数据;常见的表单元素如下表
. 由于表单元素默认的样式极其丑陋且不一致,需要自定义样式
类别 说明
<input> 供用户输入/选择,类型最为丰富,应用最多
<select> 下拉列表
<textarea> 多行输入
<button> 提交按钮;通过type可以指定为提交submit或清除reset;默认是submit;也可以通过<input>指定其type为button
<fieldset> 分组表单元素
<legend> 分组的标题;分组的好处是操作整个分组,如使用disabled属性禁止整个分组
<datalist> 以下拉列表的形式,为input等文本输入元素提供一个输入可选项;使用list属性和对应文本元素的id绑定在一起
表单事件类型
类别 说明
提交 submit 按照name-value的形式将各表单元素的数据提交给后端backend处理;默认页面会跳转,通常会阻止该事件
清除 reset 清除各表单元素数据
<form action="">
  <input type="text" name="uname" id="">
  <input type="text" name="upass" id="">
  <input type="submit" value="submit">
  <input type="reset" value="reset">
</form>
. 应用最广泛的表单元素;有很多种类type,默认是text,单行文本输入
<input type = "text">
常用属性
类别 说明
type input类型,如:单选radio、多选checkbox等
name 提交时,由后端区别不同类型元素的值;还可以对元素分类,如一组单选按钮
value
maxlength 最大字符数
id 多用于js控制;或配合<label>使用,增强用户体验
placeholder 内容占位符,显示提示信息
checked 是否选中;selected表示select的默认选中
disabled 是否可用
autocomplete 提示历史输入,方便自动完成,一般配合datalist
autofocus 自动获取焦点
required 必填字段;否则会把空的当成有效字符
pattern 利用正则表达式提供验证功能,如:pattern="^[a-zA-Z]\w{4,9}$"
常用类型
. 更多input类型,请访问 input一节
类别 说明
text 单行文本输入;默认类型
password 密码输入
radio 单选按钮;多个选一个
checkbox 多选按钮
file 文件选择按钮,请参考 file
number 数值,如输入电话号码
range 指定数值范围选择,如音量选择
color 颜色选择
submit 数据提交按钮
reset 数据复位按钮
基本使用
. 为了扩展交互热区,增强用户体验,input通常使用id属性,配合<label>的for属性一起使用
. <label>不能嵌套<div>
1. 默认下,由于元素比较小,用户点击没有那么方便,尤其是单选或多选
<input type = "text">
2. 改进使用1-通过id将<label>和<input>绑定起来,点击了<label>就相当于选择了<input>
方便使用相邻选择器操作元素
<input type='text' id=''>
<label for=''>text here</label>
3. 改进使用2-使用<label>包裹<input>,请移除for属性
<label>
    <input type='text'>text here
</label>
. 也可以使用<span>包裹文本信息,结构更加清晰
<label>
    <input type='text'>
    <span>text here</span>
</label>
[ ] input-range
.To add tick marks to a range control, include the list attribute, giving it the id of a <datalist> element which defines a series of tick marks on the control. Each point is represented using an <option> element with its value set to the range's value at which a mark should be drawn.
.You can label tick marks by giving the <option> elements label attributes. However, the label content will not be displayed by default. You can use CSS to show the labels and to position them correctly.
.min、max、step、list
.datalist:value、label
水平
垂直
说明
. 表单元素在不同浏览器上的默认样式不尽相同,为了统一,通常需要覆盖默认样式,再重新自定义新的样式
. 部分样式需要使用浏览器前缀
. 方便起见,设置各表单元素为border-box
. 部分元素可以设置appearance为none,从头开始设计UI
. form布局可以使用表格;也可以使用其它布局方式
. 以下各例,如无特殊说明,均进行初始化设计
. 请多参考底部的 can i use,避免样式使用异常
相关伪元素
类别 说明
::placeholder 占位符样式
::selection 元素选中部分样式
相关伪类
以下伪类都可以配合:not()使用
类别 说明
:focus 获取焦点时
:checked 元素选择中
:valid 有效时
:invalid 无效时
:in-range 在指定范围
:out-of-range 超出指定范围
:placeholder-shown 占位符显式[必须有占位符]
新CSS样式
类别 说明
accent-color 指定部分控件的颜色,如<input>的radio、checkbox、range和<progress>;抛弃原来丑到爆的样式
可以统一指定
:root {
  accent-color: #f40;
}
[ ] input初始化设置
. 字体大小、类型、边框、轮廓
. 默认的占位符样式和文本选择样式
. 通常根据type修改特定的表单元素
input[type=text] {
    width: 100%;
    border: none;
    outline: none;
    font: inherit;
    box-sizing: border-box;
    background-color: transparent;
}
    
input[type=text]::placeholder {
    color: #089;
}

input[type=text]::selection {
    color: #F40;
}
[ ] 自定义radio-利用:checked
方案1. 额外增加元素,替换/隐藏<input>
. 伪元素 ::after
. 相邻兄弟选择器 +
Gender
[ HTML ]
<label class="label-custom">
    <input type="radio" name="cgender" checked>
    <span class="radio"></span>
    <span>Male</span>
</label>
[ CSS ]
.label-custom {
    cursor: pointer;
}

.label-custom input {
    display: none;
    //appearance: none;
}

.label-custom span {
    vertical-align: middle;
}

.label-custom .radio {
    display: inline-block;
    position: relative;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid #666;
}

.label-custom input:checked+.radio {
    border-color: #f40;
}

.label-custom input:checked+.radio::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background-color: #f40;
}
方案2. 直接使用<label>替换<input>:可以是文字、图片、字体图标;详情请参考 个人网站
[ ] 自定义checkbox-利用伪<label>的伪元素实现;点击时跳转其位置从左边到右边
. <label>是inline,要转换为block才可以设置宽高
. 没有使用传统的父相子绝方式,而是让伪元素相对位置发生变化[作为子元素,它本来就在父元素的开始位置]
. 也可以使用accent-color修改默认的背景颜色,简单快捷,但是只适用于部分表单元素
[ HTML ]
<input type="checkbox" id="cb-custom" hidden>
<label for="cb-custom" class="cb-custom"></label>
[ CSS ]
.cb-custom {
  display: block;
  margin: 2rem auto;
  width: 80px;
  height: 40px;
  border: 2px solid var(--main-color-gray);
  padding: 2px;
  border-radius: 20px;
  cursor: pointer;
}

.cb-custom::before {
  content: '';
  position: relative;
  display: block;
  left: 0px;
  width: 50%;
  height: 100%;
  background-color: var(--main-color-gray);
  border-radius: 50%;
  transition: 0.4s;
}

#cb-custom:checked+.cb-custom::before {
  left: 50%;
  background-color: var(--main-color-blue);
}
[ ] 自定义range-利用appearance
. 默认高度是16px
. 直接修改滑块背景的样式
. 滑块的样式需要使用浏览器前缀
.range-bar {
    appearance: none;
    background-image: linear-gradient(74deg, #16a085, #1abc9c);
    border-radius: 16px;
    border: 2px solid #fff;
    box-shadow: 0 0 10px rgba(0, 0, 0, .2);
}

.range-bar::-webkit-slider-thumb {
    appearance: none;
    width: 20px;
    height: 20px;
    background-color: #f1c40f;
    border-radius: 50%;
    transition: 0.5s;
}

.range-bar:active::-webkit-slider-thumb {
    box-shadow: 0 0 10px 4px #f39c12;
}
[ ] 自定义fieldset
. 可以单独设置每一条边;还可以使用定位任意放置legend
information
teamwork
certificates
.fieldset fieldset {
  position: relative;
  border: 1px solid var(--main-color-dark);
  border-top: 10px solid var(--main-color-blue);
  margin-bottom: 2rem;
}
.fieldset legend {
  font-size: 1.2rem;
  margin: 0 auto;
  padding: 0 1rem;
  text-transform: capitalize;
}
.fieldset fieldset:nth-child(2) legend {
  position: absolute;
  right: 40px;
  top: -20px;
  background-color: #fff;
}
.fieldset fieldset:nth-child(3) legend {
  position: absolute;
  left: 40px;
  bottom: -20px;
  background-color: #fff;
}
[ ] :focus - 获取焦点
. 初始设计:边框border、占位符placeholder颜色,填充padding-left、背景background透明
. :hover:边框换色
. :focus:边框换色、字体颜色;后期可用使用动画设计呼吸灯效果
. :valid内容有效时,通常配合:focus一起使用
.custom-ipt::placeholder {
    color: #999;
}

.custom-ipt::selection {
    color: #089;
}

.custom-ipt:hover {
    border-color: #999;
}

.custom-ipt:focus,
.custom-ipt:valid {
    border-color: #089;
    color: #f40;
}
事件类型
. 事件处理的业务逻辑在<script>中;建议使用外部.js文件
. 没有失去焦点的伪类选择器;只能通过事件onblur检测
类别 说明
input 数据输入时;使用时要采用 防抖 措施
change 数据改变且失去焦点
keypress 按键按下并保持
keydown 按键按下
keyup 按键释放
blur 失去焦点
事件处理一般步骤
1. 获取input元素 querySelector;更多信息,请参考 DOM
2. 添加事件侦听器 addEventListener;更多信息,请参考 Event
[ ] 播放器进度条
[H5] audio | button | input[range]
[C3] appearance
[JS] click | input | loadmetadata | timeupdate | querySelector
[CSS]
#player button {
  width: 120px;
}

#player input {
  width: 100%;
}

.custom-range {
  appearance: none;
  height: 10px;
  background-color: #01b4ff;
  border: 2px solid #fff;
  border-radius: 10px;
  box-shadow: 1px 1px 4px rgba(0, 0, 0, .2);
}

.custom-range::-webkit-slider-thumb {
  appearance: none;
  width: 15px;
  height: 15px;
  background-color: #fff;
  border: 1px solid #01b4ff;
  border-radius: 50%;
  cursor: pointer;
}

.custom-range::-webkit-slider-thumb:hover {
  background-color: #ff0;
}
[Javascript]
let bool = false;
let player = document.querySelector('#player');
let audioIpt = player.querySelector('audio');
let btnIpt = player.querySelector('button');
let sliderIpt = player.querySelector('input');
audioIpt.src = '/music/Alizee-La Isla Bonita.mp3';
audioIpt.addEventListener('loadedmetadata', () => {
  sliderIpt.max = audioIpt.duration;
})
audioIpt.addEventListener('timeupdate', () => {
  sliderIpt.value = Math.floor(audioIpt.currentTime);
})
audioIpt.addEventListener('ended', () => {
  sliderIpt.value = 0;
  // audioIpt.pause();
  btnIpt.innerHTML = 'play';
  bool = false;
})
btnIpt.addEventListener('click', () => {
  if (bool) {
    audioIpt.pause();
    btnIpt.innerHTML = 'play';
    bool = false;
  } else {
    audioIpt.play();
    btnIpt.innerHTML = 'pause';
    bool = true;
  }
})
sliderIpt.addEventListener('input', () => {
  audioIpt.currentTime = sliderIpt.value;
  audioIpt.play();
  btnIpt.innerHTML = 'pause';
  bool = true;
})
[ ] 输入长度提示-检测input值
. 获取input元素:querySelector
. 获取input元素的maxlength属性/最大长度:el.getAttribute()
. 获取当前输入的值的长度:el.value.length
还可以输入8
[HTML]
<input type="text" name="len" id="len-ipt" required maxlength="8" placeholder="text here">
[JavaScript] 将input事件分别修改为change事件、keyup事件、blur事件,体会他们之间的不同
let lenIpt = document.querySelector('#len-ipt');
let lenVal = document.querySelector('#len-val');
lenIpt.addEventListener('input', function () {
    lenVal.innerHTML = '还可以输入' + (this.getAttribute('maxlength') - this.value.length)
})
[ ] 显示密码-修改input类型
. 部分系统自带有显式密码功能
. 部分系统要求密码框必须位于表单form中,且应该指定自动完成autocomplete
let spBtn = document.querySelector('#sp-btn');
let spIpt = document.querySelector('#sp-ipt');
spBtn.addEventListener('click', () => {
    if (spIpt.type == 'text') {
        spIpt.type = 'password'
        spBtn.value = '显示密码'
    } else {
        spIpt.type = 'text'
        spBtn.value = '隐藏密码'
    }
})
[ ] 全选-修改input属性
. 利用元素的checked属性判断当前选择状态;如果全选为真/选中,则所有选项都置为真/选中;否则取消全选/置为假
. 统计选中的个数,如果等于选项个数,则全选;如果为0,则全不选
. 更多案例,请参考 DOM
WEB前端
let cbs = document.querySelectorAll('input[name="web"]');
let all = document.querySelector('#all');
let allNo = document.querySelector('#all-no');
all.addEventListener('change', function (e) {
  console.log(this.checked);
  if (this.checked) {
    for (let i = 0; i ≤ cbs.length; i++) {
      cbs[i].checked = true
    }
  }
})

allNo.addEventListener('change', function (e) {
  console.log(this.checked);
  if (this.checked) {
    for (let i = 0; i ≤ cbs.length; i++) {
      cbs[i].checked = false
    }
  }
})

cbs.forEach(item => {
  item.addEventListener('change', function () {
    let num = 0
    for (let j = 0; j ≤ cbs.length; j++) {
      if (cbs[j].checked) {
        num++;
      }
    }
    console.log((num));
    if (num == 3)
      all.checked = true;
    else if (num == 0)
      allNo.checked = true;
    else {
      all.checked = false;
      allNo.checked = false;
    }
  })
})
. 配合<option>使用,其子元素只能是<option>
. 使用<optgroup>分组;分组标题不能选择,仅仅作为提示
. <select>的宽度决定了<option>的宽度
. 可以单独设置<select>和<option>的字体颜色、大小,其它可以设置的属性比较少
. <option>很难动态增加或减少
. 默认样式极其丑陋
. appearance: none;可以去掉默认的小箭头以便重新设计样式
. 如果需要动态增加或减少选项,需要从头定制。如利用无序列表实现选项;更多设计技巧,请访问 making a better one
属性
类别 说明
size 显示几个option;通常不指定,以免影响页面布局
selected 默认选中当前<option>
multiple 多选;使用较少
事件
类别 说明
change 选择改变时
[ ] 单选并获取数据
城市
[ HTML ]
<select name="school" id="school-single">
    <option value="guilin">guilin</option>
    <option value="xiamen">xiamen</option>
    <option value="foshan">foshan</option>
    <option value="haikou" selected>haikou</option>
</select>
[ JavaScript ]
let single = document.querySelector("#school-single")
single.addEventListener('change', function () {
    console.log(this.value);
})
[ ] 定制样式-元素覆盖法
. 只显示长的备选信息中的关键信息
城市
123
[ HTML ]
<div class="custom-wrap">
    <select name="schoolC" id="school-custom">
        <option value="桂林">广西壮族自治区桂林市</option>
        <option value="厦门">福建省厦门市</option>
        <option value="佛山">广东省佛山市</option>
        <option value="海口" selected>海南省海口市</option>
    </select>
    <div class="mask">123</div>
    <span class="iconfont icon-unfoldmore"></span>
</div>
1. 增加一个父级容器包裹表单元素<select>;相对定位
2. 增加一个遮罩元素,显示选中的值/城市名;绝对定位到容器前部;取消事件响应
3. 增加一个修饰元素,显示上下箭头,提示用户可以操作;绝对定位到容器后部;取消事件响应
4. 设置<select>颜色透明/不显示
5. 设置<option>颜色为黑色
6. 增加JS;一开始获取<select>的值给遮罩元素
7. 为<select>增加change事件,每次改变时修改遮罩的文本
8. 增加其它设计,如:hover
9. 更多设计细节,请参考天猫登录页面
[ ] 分组-<optgroup>
城市
[ HTML ]
<select name="school" id="school-mul">
    <optgroup label="college">
        <option value="guilin">guilin</option>
        <option value="xiamen">xiamen</option>
        <option value="foshan">foshan</option>
        <option value="haikou" selected>haikou</option>
    </optgroup>
    <optgroup label="unit">
        <option value="gl">gl</option>
        <option value="sh">sh</option>
    </optgroup>
</select>
[ JavaScript ]
let mul = document.querySelector("#school-mul")
mul.addEventListener('change', function () {
    console.log(this.value);
})
. 文本域;多行文本输入框
. 建议使用CSS指定cols、rows
<textarea name="msg" id="" cols="30" rows="10"></textarea>
. 默认情况下,可以自由缩放;为避免影响布局,通常指定其样式为不缩放
textarea {
    resize: none;
}
属性
类别 说明
cols 列数。建议使用CSS宽高指定
rows 行数。建议使用CSS宽高指定
wrap 是否换行;默认on|换行。off|不换行。谁会不换行呢
事件
类别 说明
change 选择改变时
focus 获取焦点时
blur 失去焦点时
[ ] 动态改变背景
. 注意封装函数时,需要额外使用匿名函数或箭头函数,详情请查看 事件 event一节
let ta = document.querySelector('#ta-bg');
function setBg(color) {
  console.log('hi');
  console.log(ta);
  ta.style.background = color;
}
ta.addEventListener('focus', (e) => {
  setBg('#f3f4f5')
});
ta.addEventListener('blur', (e) => {
  setBg('#fff')
});
. 将表单收集的数据提交给后端服务器处理
. 也可以使用<input>并指定类型为button
属性
类别 说明
submit 提交按钮;默认
reset 还原/清除按钮;清除表单元素所有数据
[ ] 数据采集完毕后,点击提交,查看浏览器地址栏信息
基本信息
学历经历
总结与作业 Summary & Homework
总结
. 数据的录入和获取
. <label>配合表单元素可以实现很多非常棒的设计,如定制表单元素、不使用js却能实现js的效果
. 部分系统要求表单元素不能单独使用,必须用在<form>中;还有某些元素如密码,必须指定 autocomplete属性,请注意查看控制台提示信息,如:
xxx field is not contained in a form
Input elements should have autocomplete attributes
作业
. 使用表单元素完善个人网站