Vue组件分享|Vue中双向绑定实现的表单选择组件(按钮样式)
写在前面 表单中经常会用到选择框的组件,HTML自带的样式太丑了,第三方的组件也不满足项目的使用需求,而且样式也不好看,于是自己就撸了一个,代码很简单,可以实现单选和多选,且选择后不需要再对选择的数据进行处理。
我写的这个组件是按钮的样式,如果需要图标+文字的哪种,自行更改样式即可。
效果图
文章图片
选择子组件代码
{{title}}
-
/>
{{tips}}
>
// 超出选择限制弹窗提示,请自行引入自己的弹窗
import { toast } from '../../../mixins/popup'
export default {
props: {
// 必传,第一项是name,第二项是value
propName: Array,
// 非必传,限选项数
limit: {
type: Number,
default: 999
},
// 非必传,只读属性
readonly: Boolean,
// 非必传,图中的红色提示文字
tips: String,
// 非必传,默认单选,多选传checkbox
type: {
type: String,
default () {
return 'radio'
}
},
// 非必传,标题
title: String,
// 必传,选项数据仅支持数组形式,如[{name: '选项一', value: 1}],
// name和value即为propName中的第一个和第二项
options: {
type: Array,
default: []
},
// 必传,选中的值,支持三种类型,单选可传String、Number类型,
// 多选只能传Array类型
value: [String, Array, Number]
},
data () {
return {}
},
computed: {
// 处理父组件传过来的数组,与双向绑定的vlaue值比较,
// 选中项的要加上selected为true的属性
checkArr () {
let checkArr = JSON.parse(JSON.stringify(this.options))
checkArr.forEach(item => {
// 默认添加上selected为false的属性
this.$set(item, 'selected', false)
// 单选
if (this.type === 'radio') {
if (item[this.itemVal] === this.value) {
item.selected = true
}
} else if (this.type === 'checkbox') {
// 多选
this.value.forEach(val => {
if (item[this.itemVal] === val[this.itemVal]) {
item.selected = true
}
})
}
})
return checkArr
},
// 选项名,使用computed转换一下,方便处理
itemName () {
return this.propName[0]
},
// 选项值,使用computed转换一下,方便处理
itemVal () {
return this.propName[1]
}
},
methods: {
change (item) {
// 只读属性则不可点击
if (this.readonly) return
// 选中的值
let value = https://www.it610.com/article/item[this.itemVal]
// 单选
if (this.type ==='radio') {
this.$emit('input', value)
console.log('单选选中的值', value)
return
}
// 多选
if (this.type === 'checkbox') {
let newValue = https://www.it610.com/article/JSON.parse(JSON.stringify(this.value))
if (item.selected) {
let index = 0
newValue.forEach((newVal, i) => {
if (value =https://www.it610.com/article/== newVal[this.itemVal]) {
index = i
}
})
newValue.splice(index, 1)
} else {
// 超出选择
if (this.value.length === this.limit) {
console.log(`最多选择${this.limit}个`)
return toast('warn', `最多选择${this.limit}个`)
}
newValue.push(item)
}
console.log('多选选中的值', newValue)
this.$emit('input', newValue)
}
}
}
}
='less' scoped>
.selectBtn{
padding: 0 24/75rem;
// 标题
h1{
font-size:28/75rem;
color:#222222;
line-height:28/75rem;
background: #fff;
padding-top: 30/75rem;
display: flex;
align-items: cneter;
background:#fff;
margin-bottom: 6/75rem;
&:before {
display: inline-block;
content: '*';
width: 6/75rem;
color: #ff6633;
// background: #ff6633;
height: 25/75rem;
border-radius: 2/75rem;
margin-right: 12/75rem;
margin-top: 4/75rem;
}
}
ul{
&.readonly{
opacity: 0.65;
}
min-height: 84/75rem;
display: flex;
align-items: center;
padding-left:6/75rem;
flex-wrap: wrap;
li{
margin-right: 20/75rem;
margin-top: 18/75rem;
button{
padding: 0 20/75rem;
height: 54/75rem;
border-radius: 4/75rem;
color: fff;
font-size: 26/75rem;
background: #fff;
border: 1px solid #ccc;
color: #666;
&.selected{
color: #fff;
border: 1px solid #079ff7;
background: #079ff7;
}
}
}
}
.tips{
color: #ff6633;
font-size: 26/75rem;
line-height: 36/75rem;
margin-top: 12/75rem;
padding-left:6/75rem;
}
}
父组件调用代码
>
// 引入选择框组件
import MeSelect from './MeSelect'export default {
data () {
return {
// 单选
// selectData: 1,
// 多选
selectData: [{name: '选项一', value: 1}],
options: [
{name: '选项一', value: 1},
{name: '选项二', value: 2},
{name: '选项三', value: 3},
{name: '选项四', value: 4},
{name: '选项五', value: 5}
]
}
},
components: {
MeSelect
}
}
="less" scoped>
【Vue组件分享|Vue中双向绑定实现的表单选择组件(按钮样式)】有问题就评论问我吧,(●ˇ?ˇ●)
个人联系方式(添加请备注):
QQ:332983810
微信:hu_jiliang
推荐阅读
- 第326天
- vue-cli|vue-cli 3.x vue.config.js 配置
- 2020-04-07vue中Axios的封装和API接口的管理
- 姚老师互动问答会|姚老师互动问答会 # 问题001(如何更有智慧的和身边人分享金刚智慧())
- 焦点学习田源分享第267天《来访》
- 《偶得》
- 2018.03.18
- 坚持分享第104天
- 句子分享
- 记录iOS生成分享图片的一些问题,根据UIView生成固定尺寸的分享图片