图例:
输入除了数字以外的字符会自动过滤
组件代码:
<template>
<div>
<div :class="['el-input' ,'el-input--mini',{'is-disabled': inputDisabled}]">
<input
ref="input"
class="el-input__inner"
:disabled="inputDisabled"
:value="formatValue"
maxlength="15"
@change="handleChange"
@input="updatevalue($event.target.value)"
@blur="onBlur"
@focus="selectAll">
</div>
</div>
</template>
class 属性使用了数组语法和对象语法的结合,其中包含了三个类名:el-input、el-input--mini 和 is-disabled。el-input 和 el-input--mini 是组件自身的样式类名,is-disabled 是根据组件状态动态添加的类名,表示输入框是否被禁用。
ref 属性为 input,表示该元素在组件实例中的引用名称。
class 属性为 el-input__inner,表示输入框内部的样式。
:disabled 属性绑定了组件实例的 inputDisabled 属性,用于动态设置输入框是否禁用。
:value 属性绑定了组件实例的 formatValue 属性,用于动态设置输入框中的值。
maxlength 属性为 15,表示输入框中最多可以输入 15 个字符。
@change 属性绑定了组件实例的 handleChange 方法,表示输入框的值发生改变时需要执行的回调函数。
@input 属性绑定了组件实例的 updateValue 方法,表示输入框的值发生改变时需要更新组件实例的 value 属性。
@blur 属性绑定了组件实例的 onBlur 方法,表示输入框失去焦点时需要执行的回调函数。
@focus 属性绑定了组件实例的 selectAll 方法,表示输入框获得焦点时需要执行的回调函数,用于选中输入框中的所有文本。
<script>
import accounting from '..................'
export default {
name: 'CurrencyInput',
inject: {
elForm: {
default: ''
},
elFormItem: {
default: ''
}
},
props: {
value: {
type: [String, Number],
default: 0,
desc: '数值'
},
symbol: {
type: String,
default: '',
desc: '货币标识符'
},
decimal: {
type: Number,
default: 0,
desc: '小数位'
},
/* eslint-disable */
disabled: [Boolean, undefined],
elvalue: [String, Number]
},
data() {
return {
focused: false
}
},
computed: {
inputDisabled() {
return this.disabled || (this.elForm || {}).disabled;
},
formatValue() {
if (this.focused) {
return this.value ? accounting.unformat(this.value) : ''
} else {
if (this.value === 0) {
return accounting.formatMoney(this.value, this.symbol, this.decimal)
} else if (
this.value === '' ||
this.value === null ||
this.value === undefined
) {
return ''
} else {
return accounting.formatMoney(this.value, this.symbol, this.decimal)
}
}
}
},
methods: {
handleChange(){
this.$emit('change', this.formatValue)
this.dispatch('ElFormItem', 'el.form.change', [this.value]);
},
updatevalue(value) {
if(this.decimal && value.indexOf('.')>-1 &&
value.substring(value.lastIndexOf('.')+1).length>this.decimal ) return
var formatvalue = value ? accounting.unformat(value) : ''
this.$emit('input', formatvalue)
},
onBlur() {
this.focused = false
this.$emit('blur', event)
this.dispatch('ElFormItem', 'el.form.blur', [this.value])
},
selectAll(event) {
this.focused = true
setTimeout(() => {
event.target.select()
}, 0)
},
dispatch(componentName, eventName, params) {
var parent = this.$parent || this.$root
var name = parent.$options.componentName
while (parent && (!name || name !== componentName)) {
parent = parent.$parent
if (parent) {
name = parent.$options.componentName
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params))
}
}
}
}
</script>
使用方法:
引入组件:
import CurrencyInput from '................'
<details>
<summary>【CurrencyInput货币数字输入框组件】</summary>
- 示例程序:
```
<el-form-item label="" prop="">
<CurrencyInput
v-model=""
field-type="currency"
name="currency"
symbol="¥"
:decimal="2"
label="测试金额"
placeholder="请输入"
clearable
/>
```
- 属性说明:
`field-type`固定为`currency`;`symbol`表示要显示的货币符号,可空;`decimal`表示要显示的小数位数。
</details>
引入的文件 accounting.min.js 它是一个第三方库,用于进行数字和货币格式化。
/* eslint-disable */
/*!
* accounting.js v0.4.2, copyright 2014 Open Exchange Rates, MIT license, http://openexchangerates.github.io/accounting.js
*/
(function(p, z) { function q(a) { return !!(a === '' || a && a.charCodeAt && a.substr) } function m(a) { return u ? u(a) : v.call(a) === '[object Array]' } function r(a) { return v.call(a) === '[object Object]' } function s(a, b) { var d; var a = a || {}; var b = b || {}; for (d in b)b.hasOwnProperty(d) && a[d] == null && (a[d] = b[d]); return a } function j(a, b, d) { var c = []; var e; var h; if (!a) return c; if (w && a.map === w) return a.map(b, d); for (e = 0, h = a.length; e < h; e++)c[e] = b.call(d, a[e], e, a); return c } function n(a, b) { a = Math.round(Math.abs(a)); return isNaN(a) ? b : a } function x(a) { var b = c.settings.currency.format; typeof a === 'function' && (a = a()); return q(a) && a.match('%v') ? { pos: a, neg: a.replace('-', '').replace('%v', '-%v'), zero: a } : !a || !a.pos || !a.pos.match('%v') ? !q(b) ? b : c.settings.currency.format = { pos: b, neg: b.replace('%v', '-%v'), zero: b } : a } var c = { version: '0.4.1', settings: { currency: { symbol: '$', format: '%s%v', decimal: '.', thousand: ',', precision: 2, grouping: 3 }, number: { precision: 0, grouping: 3, thousand: ',', decimal: '.' }}}; var w = Array.prototype.map; var u = Array.isArray; var v = Object.prototype.toString; var o = c.unformat = c.parse = function(a, b) { if (m(a)) return j(a, function(a) { return o(a, b) }); a = a || 0; if (typeof a === 'number') return a; var b = b || '.'; var c = RegExp('[^0-9-' + b + ']', ['g']); var c = parseFloat(('' + a).replace(/\((.*)\)/, '-$1').replace(c, '').replace(b, '.')); return !isNaN(c) ? c : 0 }; var y = c.toFixed = function(a, b) { var b = n(b, c.settings.number.precision); var d = Math.pow(10, b); return (Math.round(c.unformat(a) * d) / d).toFixed(b) }; var t = c.formatNumber = c.format = function(a, b, d, i) { if (m(a)) return j(a, function(a) { return t(a, b, d, i) }); var a = o(a); var e = s(r(b) ? b : { precision: b, thousand: d, decimal: i }, c.settings.number); var h = n(e.precision); var f = a < 0 ? '-' : ''; var g = parseInt(y(Math.abs(a || 0), h), 10) + ''; var l = g.length > 3 ? g.length % 3 : 0; return f + (l ? g.substr(0, l) + e.thousand : '') + g.substr(l).replace(/(\d{3})(?=\d)/g, '$1' + e.thousand) + (h ? e.decimal + y(Math.abs(a), h).split('.')[1] : '') }; var A = c.formatMoney = function(a, b, d, i, e, h) { if (m(a)) return j(a, function(a) { return A(a, b, d, i, e, h) }); var a = o(a); var f = s(r(b) ? b : { symbol: b, precision: d, thousand: i, decimal: e, format: h }, c.settings.currency); var g = x(f.format); return (a > 0 ? g.pos : a < 0 ? g.neg : g.zero).replace('%s', f.symbol).replace('%v', t(Math.abs(a), n(f.precision), f.thousand, f.decimal)) }; c.formatColumn = function(a, b, d, i, e, h) { if (!a) return []; var f = s(r(b) ? b : { symbol: b, precision: d, thousand: i, decimal: e, format: h }, c.settings.currency); var g = x(f.format); var l = g.pos.indexOf('%s') < g.pos.indexOf('%v') ? !0 : !1; var k = 0; var a = j(a, function(a) { if (m(a)) return c.formatColumn(a, f); a = o(a); a = (a > 0 ? g.pos : a < 0 ? g.neg : g.zero).replace('%s', f.symbol).replace('%v', t(Math.abs(a), n(f.precision), f.thousand, f.decimal)); if (a.length > k)k = a.length; return a }); return j(a, function(a) { return q(a) && a.length < k ? l ? a.replace(f.symbol, f.symbol + Array(k - a.length + 1).join(' ')) : Array(k - a.length + 1).join(' ') + a : a }) }; if (typeof exports !== 'undefined') { if (typeof module !== 'undefined' && module.exports)exports = module.exports = c; exports.accounting = c } else typeof define === 'function' && define.amd ? define([], function() { return c }) : (c.noConflict = (function(a) { return function() { p.accounting = a; c.noConflict = z; return c } }(p.accounting)), p.accounting = c) })(this)
------------------------------------------------------------------------------------------------------------------------------
js中的方法解释:
computed:{} 中,
名为 inputDisabled
的
对象方法,它返回一个布尔值。该方法的作用是判断当前输入框是否被禁用,或者其所属的表单是否被禁用。
具体来说,方法通过检查两个属性来判断输入框是否被禁用:
this.disabled
:表示输入框本身是否被禁用。如果该属性为true
,则表示输入框被禁用。(this.elForm || {}).disabled
:表示输入框所属的表单是否被禁用。该属性使用了 JavaScript 中的短路操作符||
和空对象{}
。如果输入框没有所属的表单,则this.elForm
为undefined
,短路操作符会返回空对象{}
,从而避免了访问undefined
对象的错误。如果表单被禁用,则该属性为true
。
因此,当输入框被禁用或其所属的表单被禁用时,该方法返回 true
,否则返回 false
。
名为 formatValue
的
对象方法,它返回一个格式化后的字符串。
该方法用于将输入框的值进行格式化。具体来说,当输入框处于焦点状态时,该方法会将输入框的值进行反格式化,即将货币符号、千位分隔符和小数位进行去除。当输入框失去焦点时,该方法会将输入框的值进行格式化,即添加货币符号、千位分隔符和小数位。
具体实现逻辑如下:
- 当输入框处于焦点状态时,
if (this.focused)
为真,方法会判断输入框的值是否为空。如果不为空,则使用accounting.unformat
方法进行反格式化,将输入框的值转换为数字类型。否则,返回空字符串(即''
)。 - 当输入框失去焦点时,
if (this.focused)
为假,方法会判断输入框的值是否为数字 0。如果是,则使用accounting.formatMoney
方法进行格式化,添加货币符号、千位分隔符和小数位。如果输入框的值为空字符串、null 或 undefined,则返回空字符串。否则,也使用accounting.formatMoney
方法进行格式化。
在这段代码中,accounting
在上方已注明.
methods: {} 中,
名为 handleChange
的
一个对象方法,它没有返回值。
该方法主要用于处理输入框的变化事件,并触发相关的事件和钩子函数。具体来说,该方法会执行以下两个操作:
- 使用
$emit
方法触发change
事件,并将格式化后的值作为参数传递给事件的回调函数。这里的formatValue
是上面的一个计算属性,用于根据输入框的状态和数值进行格式化处理,返回格式化后的货币字符串或空字符串。 - 使用
dispatch
(此方法在文章最下方) 方法触发el.form.change
钩子函数,并将输入框的值作为参数传递给该函数。
需要注意的是,该方法依赖一些对象属性来进行处理,包括:
$emit
方法:用于触发 Vue 实例上的自定义事件。this.formatValue
属性:表示输入框的格式化后的值。this.value
属性:表示输入框的原始值。dispatch
方法:用于在组件树中向上派发事件。
因此,在使用该方法前,需要确保对象的这些属性和方法已经被正确设置。
名为 updatevalue 的
对象方法,没有返回值。
该方法主要用于更新输入框的值,并触发相关的事件。具体来说,该方法会执行以下两个操作:
- 如果输入框的小数位数(即
this.decimal
属性)大于 0,且输入的值包含小数点,并且小数部分的位数大于小数位数,则直接返回,不进行任何操作。 - 使用
accounting.unformat
方法将输入框的值进行反格式化,即将货币符号、千位分隔符和小数位进行去除,并将结果赋值给变量formatvalue
。如果输入框的值为空,则将formatvalue
设置为空字符串。 - 使用
$emit
方法触发input
事件,并将formatvalue
作为参数传递给事件的回调函数。这里的input
事件是一个 Vue 内置的事件,用于响应用户输入操作。
需要注意的是,该方法依赖一些对象属性和方法来进行处理,包括:
this.decimal
属性:表示货币小数位数。value
参数:表示输入框的原始值。accounting.unformat
方法:用于将货币字符串进行反格式化,将其转换为数值类型。$emit
方法:用于触发 Vue 实例上的自定义事件。
因此,在使用该方法前,需要确保对象的这些属性和方法已经被正确设置。
名为 onBlur 的
对象方法,它没有返回值。
该方法主要用于处理输入框失去焦点事件,并触发相关的事件和钩子函数。具体来说,该方法会执行以下三个操作:
- 将输入框的
focused
属性设置为false
,表示输入框失去了焦点。 - 使用
$emit
方法触发blur
事件,并将event
对象作为参数传递给事件的回调函数。这里的event
对象是一个 JavaScript 事件对象,表示输入框失去焦点事件的相关信息。 - 使用
dispatch
方法(此方法在文章最下方)触发el.form.blur
钩子函数,并将输入框的值作为参数传递给该函数。
需要注意的是,该方法依赖一些对象属性和方法来进行处理,包括:
this.focused
属性:表示输入框是否处于焦点状态。$emit
方法:用于触发 Vue 实例上的自定义事件。event
参数:表示输入框失去焦点事件的相关信息。dispatch
方法:用于在组件树中向上派发事件。
因此,在使用该方法前,需要确保对象的这些属性和方法已经被正确设置
名为 selectAll 的
对象方法,它没有返回值。
该方法主要用于选中输入框中的所有文本,并将输入框设置为焦点状态。具体来说,该方法会执行以下两个操作:
- 将输入框的
focused
属性设置为true
,表示输入框处于焦点状态。 - 使用
setTimeout
方法来延时执行一个回调函数,该回调函数会在下一个事件循环中被执行。在回调函数中,使用select
方法选中输入框中的所有文本。这里的event.target
表示触发事件的元素,即输入框元素。
需要注意的是,由于 select
方法必须在输入框处于焦点状态下才能生效,因此在执行该方法前,需要确保输入框已经处于焦点状态,即通过设置 this.focused
属性为 true
来实现。此外,为了确保 select
方法能够正常工作,需要在下一个事件循环中执行该方法,即使用 setTimeout
方法来进行延时处理。
名为 dispatch 的
对象方法,用于在组件树中向上派发事件,并触发指定的钩子函数。它没有返回值。
该方法接受三个参数:componentName
表示需要触发钩子函数的组件名称;eventName
表示需要触发的钩子函数名称;params
表示需要传递给钩子函数的参数列表。
该方法会从当前组件开始向上遍历组件树,直到找到指定名称的组件或遍历到根组件为止。在遍历过程中,使用 parent
变量来表示当前遍历到的组件,使用 name
变量来表示当前组件的名称。如果当前组件的名称与指定名称不一致,则继续向上遍历其父组件,直到找到指定名称的组件或遍历到根组件为止。
如果找到了指定名称的组件,即 parent
不为 null
,则通过 parent.$emit
方法触发该组件上的指定钩子函数,并将参数列表传递给该函数。这里的 apply
方法用于将参数列表展开成一个个参数,以便传递给 $emit
方法。
需要注意的是,该方法依赖于 $parent
和 $root
属性,这两个属性分别表示当前组件的父组件和根组件。由于 $parent
和 $root
属性可能为 null
,因此在使用该方法前需要进行判断,以确保这两个属性存在。此外,该方法还依赖于 $options.componentName
属性,该属性为组件的名称,需要在组件定义时进行设置。