IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 用el-input实现金额编辑组件 -> 正文阅读

[JavaScript知识库]用el-input实现金额编辑组件

目录

组件说明

效果图:

?代码示例


组件说明

表单中涉及金额控件时,编辑状态下是数字格式,非编辑状态要显示千分位格式化的形式,提交到后台接口时依然是数字格式,于是用el-input组件,结合sync修饰符,实现自定义组件的v-model效果。支持格式化、自定义前缀、后缀、千分位设置以及百分比显示效果。

为什么要借助sync修饰符实现双向数据绑定,因为在vue中props是单向数据绑定,父组件通过prop给子组件下发数据,子组件通过事件给父组件发送消息。但如果直接绑定props会报警告信息,所以在子组件中实现双向数据绑定时,需要使用data的变更来转换一下。

效果图:

非编辑状态

?编辑状态:

提交后台的数据:

?代码示例

注意:使用组件时,绑定value.sync 而非直接 v-model。

  • 父组件 index.vue
<template>
  <div style="padding:40px 10px;">
    <el-form size="mini" label-width="60px">
      <el-row :gutter="24">
        <el-col :span="6">
          <el-form-item :label="'金额'">
            <money :value.sync="moneyValue" :prefix="'¥'"></money>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-button type="primary" size="mini" @click="handleSub"
          >提交</el-button
        >
      </el-row>
    </el-form>
  </div>
</template>
<script>
export default {
  components: { money: () => import('./money.vue') },
  data() {
    return {
      moneyValue: 12345,
    }
  },
  methods: {
    handleSub() {
      this.$message.info('提交到后台的数据:' + this.moneyValue)
    },
  },
}
</script>
<style lang="scss" scoped></style>
  • 子组件 money.vue
<template>
  <div>
    <el-input
      v-show="isEdit"
      v-model="currentValue"
      ref="validInput"
      @blur="handleValueBlur"
    >
      <template slot="prepend" v-if="prefix">{{ prefix }}</template>
      <template slot="append" v-if="suffix">{{ suffix }}</template>
    </el-input>
    <el-input
      v-show="!isEdit"
      v-model="displayValue"
      @focus="handleDisplayfocus"
    >
      <template slot="prepend" v-if="prefix">{{ prefix }}</template>
      <template slot="append" v-if="suffix">{{ suffix }}</template>
    </el-input>
  </div>
</template>
<script>
/** 金额编辑组件 */
export default {
  /**
   * 属性参数
   * @member props
   * @property {number|string} [value] 原始值
   * @property {number} [precision=0] 精度,保留几位小数
   * @property {string} [separator=,] 分隔值的符号,默认值为‘,’(英文逗号)
   * @property {string} [prefix] 前缀内容,也可以用插槽定义
   * @property {string} [suffix] 后缀内容,也可以用插槽定义
   * @property {boolean} [percentage] 按百分比计算显示, 如value=0.2, 显示为 20%
   */
  props: {
    // 数字
    value: [Number, String],
    // 精度,保留几位小数
    precision: {
      type: Number,
      default: 2,
    },
    // 分隔符
    separator: {
      type: String,
      default: ',',
    },
    // 前缀
    prefix: {
      type: String,
      default: '',
    },
    // 后缀
    suffix: {
      type: String,
      default: '元',
    },
    // 按百分比显示
    percentage: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      isEdit: false, // 默认显示格式化后内容
      currentValue: this.value, // 绑定值
      displayValue: this.value, // 显示的值
    }
  },
  watch: {
    value(val) {
      this.currentValue = val || ''
    },
    currentValue(val) {
      this.$emit('update:value', val)
    },
  },
  methods: {
    // 显示格式化的值
    handleValueBlur() {
      // if (this.currentValue.includes(',')) {
      //   this.currentValue = this.currentValue.replaceAll(',', '');
      // }
      let thousandsFormate = this.numberFormat(
        this.currentValue,
        this.precision,
        this.separator
      )
      if (this.percentage) {
        thousandsFormate = this.currentValue * 100 + '%'
      }
      this.displayValue = thousandsFormate
      this.isEdit = false
    },
    // 开启编辑
    handleDisplayfocus() {
      const me = this
      this.isEdit = true
      setTimeout(() => {
        me.$refs.validInput.focus()
      }, 100)
    },
    /*
     * 金额格式化:
     * number:要格式化的数字
     * decimals:保留几位小数
     * thousandsSep:千分位符号
     * tdecPoint:小数点符号
     * */
    numberFormat(number, decimals = 2, thousandsSep = ',', tdecPoint = '.') {
      number = (number + '').replace(/[^0-9+-Ee.]/g, '')
      if (number.indexOf(',') > -1) {
        return number
      }
      let n = !isFinite(+number) ? 0 : +number,
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = typeof thousandsSep === 'undefined' ? ',' : thousandsSep,
        dec = typeof tdecPoint === 'undefined' ? '.' : tdecPoint,
        s = '',
        toFixedFix = function(n, prec) {
          const k = Math.pow(10, prec)
          return '' + Math.ceil(n * k) / k
        }

      s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.')
      const re = /(-?\d+)(\d{3})/
      while (re.test(s[0])) {
        s[0] = s[0].replace(re, '$1' + sep + '$2')
      }

      if ((s[1] || '').length < prec) {
        s[1] = s[1] || ''
        s[1] += new Array(prec - s[1].length + 1).join('0')
      }
      return s.join(dec)
    },
  },
}
</script>
<style lang="scss" scoped></style>

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:03:16  更:2022-03-03 16:05:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:32:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码