在用户使用过程当中提出一键导入的功能,需求以下:点击导入按钮显示提示框,而后是单选框以及上传按钮。pc端常使用element-ui组件,可是这个项目是vue1的老项目,而且没有element-ui组件。因此须要本身动手实现单选功能和上传功能。 css
// html
<div v-for="day in weekSelectList"
:key="day.id"
class="select__day">
<input type="radio"
name="week"
:id="day.label"
:value="day.value"
v-model="selectedDay">
<label :for="day.label">{{day.label}}({{day.value}})</label>
</div>
复制代码
// 暂定的数据
data(){
return {
weekSelectList: [
{ label: '周一', value: '2018-12', id: 1 },
{ label: '周二', value: '2018-13', id: 2 },
{ label: '周三', value: '2018-14', id: 3 },
{ label: '周四', value: '2018-15', id: 4 },
{ label: '周五', value: '2018-16', id: 5 }
]
},
selectedDay: '2018-12',
}
复制代码
经过 v-model 绑定 selectedDay,匹配到相同的值会将该 radio 选中,当改变 radio 的选择,selectedDay 也会动态的变动成选中的 radio 的 valuehtml
<div class="upload__button"
:class="{'upload__button--uploaded':isUploaded}"
@click="onUploadClick">点击上传</div>
<input type="file"
class="upload__file"
v-el:upload
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
@change="onFileChange" />
复制代码
methods:{
onUploadClick() {
if (!this.isUploaded) {
this.$els.upload.click()
}
},
onFileChange(e) {
const file = e.target.files[0]
if (file === undefined) {
return
}
this.fileName = file.name
const result = /[xls|xlsx]$/.test(this.fileName)
if (result) {
this.isUploaded = true
this.showAlert('上传成功')
this.$els.upload.value = null
} else {
this.showAlert('文件格式错误,请确认后重试。')
}
},
}
复制代码
当点击上传按钮触发 onUploadClick 事件后,获取到 upload 绑定的 DOM (因为是老的项目使用的是$els,vue2 使用 ref
)手动触发 click 事件
而且能够在change事件中默认接收一个文件信息对象其中target.files[0]
包含文件的更多信息,以下图:vue
能够看到 change 事件的返回值包含着文件属性,这里咱们须要判断是文件名是否为 excel,使用正则的 test 方法。element-ui
在最后 this.$refs.uploadFile.value = null; 移除文件,能够保证上传一样的文件时,也会触发 change 事件bash
至此关于表单方面的功能都已经实现了,因为原始的radio样式比较丑,并且不能更改。下面咱们就想办法将它作的漂亮些。app
// template
<label v-for="(item,index) in radioList"
:key="item.value"
:for="item.linkLabel"
:accesskey="index">
<span class="content__input">
<span class="radio__replace"
:class="{'radio__replace--checked':selectedRadio===item.value,'radio__replace--disable':item.isDisabled}">
</span>
<input v-model="selectedRadio"
type="radio"
class="radio__button"
name="radio"
:id="item.linkLabel"
:tabindex="index"
:value="item.value"
:disabled="item.isDisabled"
@focus="item.isFocus = true"
@blur="item.isFocus = false" />
</span>
<span class="content__text">{{item.label}}</span>
</label>
复制代码
// data
data() {
return {
radioList: [
{
linkLabel: 'label1',
value: '1',
isDisabled: false,
isFocus: false,
label: '标签1'
},
{
linkLabel: 'label2',
value: '2',
isDisabled: false,
isFocus: false,
label: '标签2'
},
{
linkLabel: 'label3',
value: '3',
isDisabled: true,
isFocus: false,
label: '标签3'
}
],
selectedRadio: '1'
}
复制代码
关联起来
。(这里我将input放在label内,这样点击整个label都会选中,没有label和radio元素之间的间隙
)。name
相同的radio会实现单选效果
,tabindex
表明使用"Tab"键的遍历顺序
,value是选中时v-model绑定的selectedRadio也就会跟着变动关键在于结构
就是用一个类名content__input
标签将类名radio__replace
和radio包起来。设置定位层级(至关于radio被覆盖了,然而只要点击到labelradio就会被选中)selectedRadio
选中的值和当前radio值作对比,以及isDisabled这些Boolean值
来动态绑定class
实现咱们自定义的radio样式切换效果以下:优化
其实radio__replace
类名对应的标签就是咱们自定义的radio,其中的白色原点是经过伪类生成的css代码放在最后,感兴趣能够看下ui
若是想经过类名来改变白色原点的样式,能够经过权重来改变。以下经过isShow来给外层添加test类名
而起始的时候设置的权重为两层,以后添加一层能够起到修改样式的效果。(ps:伪类不能经过预先设定好的类名来修改样式)例子代码以下:this
<div :class="{test:isShow}"
@click="onRedClick">
<div class="text__item"></div>
</div>
复制代码
.text__item {
&:after {
content: '';
width: 30px;
height: 30px;
background-color: #f00;
position: absolute;
bottom: 20px;
}
}
.test {
.text__item {
&:after {
background-color: #ff0;
}
}
}
复制代码
// css
.radio {
&__replace {
border: 1px solid #dcdfe6;
border-radius: 100%;
width: 14px;
height: 14px;
background-color: #fff;
position: relative;
cursor: pointer;
display: inline-block;
box-sizing: border-box;
z-index: 999;
transition: 0.15s ease-in;
&--checked {
border-color: #409eff;
background-color: #409eff;
}
&--disable {
cursor: not-allowed;
}
&:after {
width: 4px;
height: 4px;
border-radius: 100%;
background-color: #fff;
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
&__button {
opacity: 0;
outline: none;
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: 0;
}
}
复制代码
基本属性
,使用案例并优化了radio的样式
缺点
以及改善方法