Vue数字输入框组件使用方法详解


Posted in Javascript onFebruary 10, 2020

前面的话

关于基础组件介绍,已经更新完了。这篇文章将用组件基础知识开发一个数字输入框组件。将涉及到指令、事件、组件间通信。

Vue数字输入框组件使用方法详解

基础需求

  • 只能输入数字
  • 设置初始值,最大值,最小值
  • 在输入框聚焦时,增加对键盘上下键的支持
  • 增加一个控制步伐prop-step,例如,设置为10 ,点击加号按钮,一次增加10

项目搭建

在了解需求后,进行项目的初始化:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
 <div id="app">
 <input-number></input-number>
 </div>
</body>
</html>
<script>
 Vue.component('input-number',{
 template: `
  <div class="input-number">
  <input type="text" />
  <button>-</button>
  <button>+</button>
  </div>
 `}
 var app = new Vue({
 el:'#app'
 })
</script>

初始化结构搭好后,由于要设置初始值,最大值、最小值,我们在父组件中的 < input-number>< /input-number>上设置这些值,并且通过Props将父组件数据传递给子组件

父组件中添加数据:value是一个关键的绑定值,所以用v-model,实现双向绑定。

<input-number v-model="value" :max="100" :min="0"></input-number>

在子组件中添加props选项:

props: {
  max: {
  type: Number,
  default: Infinity
  },
  min: {
  type: Number,
  default: -Infinity
  },
  value: {
  type: Number,
  default: 0
  }
 },

我们知道,Vue组件时单项数据流,所以无法在子组件上更改父组件传递的数据,在这里子组件只改变value值,所以我们给子组件设置一个data数据,默认引用value值,然后在组件内部维护这个data。

data() {
  return{
  // 保存初次父组件传递的数据
  currentValue : this.value,
  }
 }

并且给子组件的input元素绑定value

<input type="text" :value="currentValue" />

这样只解决了初始化时引用父组件value的问题,但是如果父组件修改了value,子组件无法感知,我们想要currentValue一起更新。那么就要使用wacth监听选项监听value。

  • 当父组件value发生变化时,子组件currentValue也跟着变化。
  • 当子组件currentValue变化时,使用$emit触发v-model,使得父组件value也跟着变化
watch: {
  // 监听属性currentValue与value
  currentValue(val) {
  // currentValue变化时,通知父组件的value也变化
  this.$emit('input', val);
  

  },
  value(val) {
  // 父组件value改变时,子组件currentValue也改变
  this.updataValue(val);
  }
 },
 methods: {
  updataValue(val) {
  if(val > this.max) val = this.max;
  if(val < this.min) val = this.min;
  this.currentValue = val;
  }
  },
  // 第一次初始化时,也对value进行过滤
 mounted: function() {
  this.updataValue(this.value);
 }

上述代码中,生命周期mounted钩子也使用了updateValue()方法,是因为初始化时也要对value进行验证。

父子间的通信解决差不多了,接下来完成按钮的操作:添加handleDown与handleUp方法

template: `
  <div class="input-number">
  <input type="text" :value="currentValue" />
  <button @click="handleDown" :disabled="currentValue <= min">-</button>
  <button @click="handleUp" :disabled="currentValue >= max">+</button>
  </div>
 `,
  methods: {
  updataValue(val) {
  if(val > this.max) val = this.max;
  if(val < this.min) val = this.min;
  this.currentValue = val;
  },
  // 点击减号 减10
  handleDown() {
  if(this.currentValue < this.min) return 
  this.currentValue -= this.prop_step;
  },
  // 点击加号 加10 
  handleUp() {
  if(this.currentValue < this.min) return
  this.currentValue += this.prop_step;
  },

当用户在输入框想输入具体的值时,怎么办?

为input绑定原生change事件,并且判断输入的是否数字:

<input type="text" :value="currentValue" @change="handleChange" />

在methods选项中,添加handleChange方法:

// 输入框输入值
 handleChange(event) {
 var val = event.target.value.trim();
 var max = this.max;
 var min = this.min;
  if(isValueNumber(val)) {
   val = Number(val);
   if(val > max) {
   this.currentValue = max;
   }
   if(val < min) {
   this.currentValue = min;
   }
   this.currentValue = val;
   console.log(this.value);
  }else {
   event.target.value = this.currentValue;
  }

在外层添加判断是否为数字的方法isValueNumber:

function isValueNumber(value) {
 return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value+ '');
 }

到此一个数字输入框组件基本完成,但是前面提出的后两个要求也需要实现,很简单,在input上绑定一个keydown事件,在data选项中添加数据prop_step

<input type="text" :value="currentValue" @change="handleChange" @keydown="handleChange2" />
data() {
  return{
  // 保存初次父组件传递的数据
  currentValue : this.value,
  prop_step: 10
  }
 }
// 当聚焦时,按上下键改变
  handleChange2(event) {
  console.log(event.keyCode)
  if(event.keyCode == '38') {
   this.currentValue ++;
  }
  if(event.keyCode == '40') {
   this.currentValue --;
  }
  }

完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
 <div id="app">
  <input-number v-model="value" :max="100" :min="0"></input-number>
 </div>
</body>
</html>
<script>
 function isValueNumber(value) {
  return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value+ '');
 }
 Vue.component('input-number',{
  props: {
   max: {
    type: Number,
    default: Infinity
   },
   min: {
    type: Number,
    default: -Infinity
   },
   value: {
    type: Number,
    default: 0
   }
  },
  template: `
   <div class="input-number">
    <input type="text" :value="currentValue" @change="handleChange" @keydown="handleChange2" />
    <button @click="handleDown" :disabled="currentValue <= min">-</button>
    <button @click="handleUp" :disabled="currentValue >= max">+</button>
   </div>
  `,
  data() {
   return{
    // 保存初次父组件传递的数据
    currentValue : this.value,
    prop_step: 10
   }
  },
  watch: {
   // 监听属性currentValue与value
   currentValue(val) {
   // currentValue变化时,通知父组件的value也变化
   this.$emit('input', val);
   

   },
   value(val) {
   // 父组件value改变时,子组件currentValue也改变
    this.updataValue(val);
   }
  },
  methods: {
   updataValue(val) {
    if(val > this.max) val = this.max;
    if(val < this.min) val = this.min;
    this.currentValue = val;
   },
   // 点击减号 减10
   handleDown() {
    if(this.currentValue < this.min) return 
    this.currentValue -= this.prop_step;
   },
   // 点击加号 加10 
   handleUp() {
    if(this.currentValue < this.min) return
    this.currentValue += this.prop_step;
   },
   // 输入框输入值
   handleChange(event) {
    var val = event.target.value.trim();
    var max = this.max;
    var min = this.min;
    if(isValueNumber(val)) {
     val = Number(val);
     if(val > max) {
      this.currentValue = max;
     }
     if(val < min) {
      this.currentValue = min;
     }
     this.currentValue = val;
     console.log(this.value);
    }else {
     event.target.value = this.currentValue;
    }
   },
   // 当聚焦时,按上下键改变
   handleChange2(event) {
    console.log(event.keyCode)
    if(event.keyCode == '38') {
     this.currentValue ++;
    }
    if(event.keyCode == '40') {
     this.currentValue --;
    }
   }

  },
  // 第一次初始化时,也对value进行过滤
  mounted: function() {
   
   this.updataValue(this.value);
  }


 })
 var app = new Vue({
  el:'#app',
  data:{
   value: 5
  }
 })
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
tagName的使用,留一笔
Jun 26 Javascript
jquery显示loading图片直到网页加载完成的方法
Jun 25 Javascript
JavaScript利用HTML DOM进行文档操作的方法
Mar 28 Javascript
JavaScript事件学习小结(五)js中事件类型之鼠标事件
Jun 09 Javascript
原生js实现jquery函数animate()动画效果的简单实例
Aug 21 Javascript
jQuery实现的导航下拉菜单效果示例
Sep 05 Javascript
jQuery插件HighCharts实现气泡图效果示例【附demo源码】
Mar 13 Javascript
ES6入门教程之Class和Module详解
May 17 Javascript
vue系列之requireJs中引入vue-router的方法
Jul 18 Javascript
JavaScript函数、闭包、原型、面向对象学习笔记
Sep 06 Javascript
新年快乐! javascript实现超级炫酷的3D烟花特效
Jan 30 Javascript
Vue scoped及deep使用方法解析
Aug 01 Javascript
JavaScript canvas实现跟随鼠标事件
Feb 10 #Javascript
JavaScript实现简易聊天对话框(加滚动条)
Feb 10 #Javascript
node.js使用 http-proxy 创建代理服务器操作示例
Feb 10 #Javascript
node.js中 redis 的安装和基本操作示例
Feb 10 #Javascript
js实现登录拖拽窗口
Feb 10 #Javascript
javascript 原型与原型链的理解及应用实例分析
Feb 10 #Javascript
在 Vue 中使用 JSX 及使用它的原因浅析
Feb 10 #Javascript
You might like
php 文件状态缓存带来的问题
2008/12/14 PHP
paypal即时到账php实现代码
2010/11/28 PHP
PHP中仿制 ecshop验证码实例
2017/01/06 PHP
关于JavaScript的gzip静态压缩方法
2007/01/05 Javascript
FireFox与IE 下js兼容触发click事件的代码
2008/11/20 Javascript
js怎么终止程序return不行换jfslk
2013/05/30 Javascript
如何从jQuery的ajax请求中删除X-Requested-With
2013/12/11 Javascript
JS 实现列表与多选框选择附预览动画
2014/10/29 Javascript
jQuery结合ajax实现动态加载文本内容
2015/05/19 Javascript
使用vue编写一个点击数字计时小游戏
2016/08/31 Javascript
jQuery实现别踩白块儿网页版小游戏
2017/01/18 Javascript
js微信分享实现代码
2020/10/11 Javascript
浅谈Angular 的变化检测的方法
2018/03/01 Javascript
微信小程序时间戳转日期的详解
2019/04/30 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
2019/07/26 Javascript
基于vue实现简易打地鼠游戏
2020/08/21 Javascript
[03:42]2018完美盛典-《加冕》
2018/12/16 DOTA
Python使用gensim计算文档相似性
2016/04/10 Python
浅谈python内置变量-reversed(seq)
2017/06/21 Python
使用Flask集成bootstrap的方法
2018/07/24 Python
python实现贪吃蛇小游戏
2020/03/21 Python
简单了解Python3里的一些新特性
2019/07/13 Python
在Pytorch中使用样本权重(sample_weight)的正确方法
2019/08/17 Python
Python基于Webhook实现github自动化部署
2020/11/28 Python
伦敦的高级牛仔布专家:Trilogy
2018/08/06 全球购物
屈臣氏俄罗斯在线商店:Watsons俄罗斯
2020/08/03 全球购物
NHL官方在线商店:Shop.NHL.com
2020/05/01 全球购物
求职信写作要突出重点
2014/01/01 职场文书
八年级音乐教学反思
2014/01/09 职场文书
高中军训第一天感言
2014/03/06 职场文书
留学经费担保书
2014/05/12 职场文书
小学生植树节活动总结
2014/07/04 职场文书
2014年小学辅导员工作总结
2014/12/23 职场文书
运动员入场前导词
2015/07/20 职场文书
关于感恩的素材句子(38句)
2019/11/11 职场文书
Java数据结构之堆(优先队列)
2022/05/20 Java/Android