element ui vue2 数值范围输入框组件
·
效果
使用
注意:使用element el-form el-form-item 包裹组件后,会自动添加范围校验规则。另,由于我不需要其他功能,所以没有处理input的各种事件。
<el-form ref="volatilityFormRef" :disabled="!volatility.checked" label-width="7rem" :model="volatility.data" :rules="volatility.rules" size="medium">
<el-form-item label="波动范围" prop="range">
<input-number-range v-model="volatility.data.range" :disabled="!volatility.checked" unit="%"></input-number-range>
</el-form-item>
</el-form>
组件代码
<template>
<el-row v-auto-range-validate class="input-number-range" :class="{ 'is-disabled': disabled || formDisabled }" justify="space-between" type="flex">
<el-input v-model.trim="value[0]" v-number :disabled="disabled" placeholder="最小值" :size="formSize || size" type="text">
<template v-if="unit" v-slot:append>
<span>{{ unit }}</span>
</template>
</el-input>
<span :class="{ 'is-disabled': disabled || formDisabled }">{{ separator }}</span>
<el-input v-model.trim="value[1]" v-number="numberType" :disabled="disabled || formDisabled" placeholder="最大值" :size="formSize || size" type="text">
<template v-if="unit" v-slot:append>
<span>{{ unit }}</span>
</template>
</el-input>
</el-row>
</template>
<script>
export default {
name: "InputNumberRange",
directives: {
"auto-range-validate": {
inserted(el, binding, vnode) {
const _this = vnode.context
let formItem = _this
while (formItem && formItem.$options.name !== "ElFormItem") {
formItem = formItem.$parent
if (!formItem) break
}
if (!formItem) return
let form = formItem.$parent
while (form && form.$options.name !== "ElForm") {
form = form.$parent
if (!form) break
}
if (!form) return
// 大小和禁用状态
_this.formSize = form.size
_this.formDisabled = form.disabled
const prop = formItem.prop
if (!prop) return
let rules = form.rules
if (!rules) form.rules = rules = { [prop]: [] }
if (!rules[prop]) rules[prop] = []
if (!Array.isArray(rules[prop])) rules[prop] = [rules[prop]]
rules[prop].push({
validator: (rule, value, callback) => {
const msg = _this.validate()
callback(msg ? new Error(msg) : "")
},
trigger: "blur",
})
},
},
},
model: {
prop: "value",
event: "onChange",
},
emits: ["onChange"],
props: {
value: {
type: [Array],
default: () => [null, null],
},
disabled: {
// 禁用
type: Boolean,
default: false,
},
size: {
// 大小
type: String,
default: "",
validator: (val) => ["mini", "small", "medium"].includes(val),
},
separator: {
// 分隔符
type: String,
default: "至",
},
unit: {
// 单位
type: String,
default: "",
},
precision: {
// 精度
type: Number,
default: null,
},
numberType: {
// 数字类型
type: String,
default: "decimal",
validator: (val) => ["integer", "decimal", "positive-integer", "positive-decimal"].includes(val),
},
},
data() {
return {
formSize: "",
formDisabled: false,
}
},
watch: {
value: {
handler(val) {
this.$nextTick(() => {
if (!Array.isArray(val) || val.length !== 2) {
// 第一次 修正value值
this.$emit("onChange", [null, null])
}
})
},
immediate: true,
},
},
methods: {
validate() {
const min = this.value[0]
const max = this.value[1]
if (!min && !max) return ""
if (!min) return "请输入最小值"
if (!max) return "请输入最大值"
if (parseFloat(min) > parseFloat(max)) return "最小值不能大于最大值"
if (this.precision !== 0 && !this.precision) return
this.$emit("onChange", [parseFloat(min).toFixed(this.precision), parseFloat(max).toFixed(this.precision)])
},
},
}
</script>
<style lang="stylus" scoped>
.input-number-range
background-color #fff
border 1px solid #dcdfe6
border-radius 4px
.is-disabled
background-color #eef0f6
border-color #e4e7ed
color #c0c4cc
cursor not-allowed
/deep/.el-input-group__append
background-color inherit
color inherit
// 取消element原有的input框样式
/deep/.el-input
.el-input__inner
border 0
margin 0
padding 0 15px
background-color transparent
text-align center
/deep/.el-input-group__append
background-color #fff
border unset
</style>
另一个自定义指令
// 注意自行注册
/**
* @name v-number
* @description 数值输入框指令,用于限制输入框只能输入特定类型的数值,具体类型由指令参数指定。
* @param {string} binding.value - 可选值:'integer'(整数), 'decimal'(小数), 'positive-integer'(正整数), 'positive-decimal'(正小数)。
* - 'integer': 应用整数验证规则,输入框能输入正整数、负整数和0,非法字符会被自动过滤,仅允许输入数字和负号。
* - 'decimal': 应用小数验证规则,输入框可输入包含小数点的有理数(正负皆可),非法字符会被过滤,允许输入数字、负号和小数点。
* - 'positive-integer': 应用正整数验证规则,输入框只能输入正整数,非数字字符会被自动过滤,只允许输入数字。
* - 'positive-decimal': 应用正小数验证规则,输入框只能输入大于等于0的有理数,非法字符会被过滤,允许输入数字和小数点。
* @type {{inserted: number.inserted, unbind: number.unbind}}
*/
export const number = {
inserted: function (el, binding) {
const inputEl = el.querySelector("input")
if (inputEl) {
// 用于存储当前使用的正则表达式
let currentReg
// 用于存储当前输入内容的替换(过滤)正则表达式
let replaceReg
// 根据初始参数设置正则表达式和替换规则
switch (binding.value) {
case "integer":
currentReg = /^-?(0|[1-9]\d*)$/
replaceReg = /[^\d-]/g
break
case "positive-integer":
currentReg = /^(0|[1-9]\d*)$/
replaceReg = /[^\d]/g
break
case "positive-decimal":
currentReg = /^(0|[1-9]\d*)(\.\d*)?$/
replaceReg = /[^\d.]/g
break
default: // decimal
currentReg = /^-?(0|[1-9]\d*)(\.\d*)?$/
replaceReg = /[^\d.-]/g
}
const inputHandler = function () {
let value = inputEl.value
value = value.replace(replaceReg, "")
if (!currentReg.test(value) && value !== "") {
inputEl.value = ""
} else {
inputEl.value = value
}
}
inputEl.addEventListener("input", inputHandler)
// 存储解绑函数,以便在元素销毁时调用
el.__unbindVNumber = function () {
inputEl.removeEventListener("input", inputHandler)
}
}
},
unbind: function (el) {
if (el.__unbindVNumber) {
el.__unbindVNumber()
delete el.__unbindVNumber
}
},
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)