从零撸一个pc端vue的ui组件库( 计数器组件 )

  • 时间:
  • 浏览:44

听到计数器那个名字良多人是否是1霎时出有甚么印象, 究竟结果那个组件用的比力少,便是那种左侧1个'-'右侧1个'+', 掌握某些数目的时分才会用到, 好比我之前做的商乡小法式只要'下单'页里的规格弹出框内里才有他的身影, 若是是触及四处理商品数目很频仍的营业场景应当会很罕见吧, 可是没有要看那个组件小, 编写它的时分坑借很多, 本次我们便去做1个计数器, 目的便是尽量小, 尽量的省机能.

1:需供阐发

  • 每次+1 ⑴是常态, 可是若是弄举动, 每次起码为+⑵个或3个, 便要兼容1下了,( 举1个现实碰到的坑, 我们之前把用户限定为每次举动, 每一个用户只能购2个, 可是出有做好抗御, 致使用户能够此次只购1个, 而下次他再次购置的时分会提醒每次只能购两个, 但显现他只面击了购1个, 由于他已购过1个, 为了兼容那个成绩, 弄得借要减稀里糊涂的弥补代码 )
  • 中心的显现区应当可输出的, 用户念购1000个不成能让他+1+1+1..., 某些组件采取的是, 日常平凡其为div, 面击以后变成input, 小我觉得完整出需要, 1个元素便够了, 何须弄两个元素, input形态下把他的默许款式来失落就行了.
  • 摆布双方要无限造, 良多时分会无限购1道, 好比我做的商乡, 库存只要10个 或单个用户最多购置3个, 起码购两个等等限定.
  • 小数位数的显现1道... 那个实在我借实碰到过, 有1种需供叫做, 只需触及数字便必需切确到后两位, 这类需供会致使背景同窗对数据库做1定的限定, 从而我们传给背景的数据也便存正在限定了.

2: 根本构造:

先展现1章通俗形态的图, 让我们更曲不雅的来完成它, 外型比力新颖, 是本套组件的1个特性, 哈哈做的取他人1样会致使思惟的监禁, 本身写代码多测验考试新的工具, 可是事情中1定要中规中矩, 以公司条目为原则.

vue-cc-ui/src/components/InputNumber/index.js

import inputNumber from './main/input-number.vue'
inputNumber.install = function(Vue) {
 Vue.component(inputNumber.name, inputNumber);
};
export default inputNumber

vue-cc-ui/src/components/InputNumber/main/input-number.vue

那里我们挑选吧input取button放正在1个div内里, 且同级别这类体例, 取其他的没有太1样, 由于如许更曲不雅, 并且也充足真现我念要的功用.

3: 事务的绑定

// 削减
 
// 删减
// 输出框的监控

那里我们有个成绩, 便是本组件采取的是v-model的情势编写, v-model有1些短处, 正在测试的时分我发明, 好比道用户为多个组件绑定了不异的v-model会致使无穷衬着的bug, 上面会解读处理那类bug的相干代码.

prpos

props: {
 max: { type: Number }, // 数字没有传默许是undefined
 min: { type: Number },
 step: { // 每次计较的单元
  type: Number,
  default: 1
 },
 value: { 
 // 绑定的数值, 那里许可两种type, 为了便利用户誊写,详细判定上面我们本身写
  type: [String, Number],
  required: true
 },
 precision: { // 显现小数面后几位数
  type: Number,
  validator(value) {
  if (value < 1 || value === undefined) {
   return 1;
  } else {
   return parseInt(value);
  }
  }
 }
 },

add 办法的真现

add() {
// 极可能用户便输出了1个string属性, 
// 1: 好比背景前往的便是字符串;
// 2: input框输出的便是字符串范例;
// 3: 用v-model绑定了一样的值的其他组件付与了那个值string范例;
 let num = Number(this.value) + this.step; // 减上牢固的少度
// 那里我们笼统出1个特地卖力数值的变革的函数
 this.emitVal(num);
},

reduce 办法的真现

reduce() {
  let num = Number(this.value) - this.step;
  this.emitVal(num);
 },

监听input框的输出事务

inputChange(e) {
// 那里便有能够呈现string范例的了
  this.emitVal(Number(e.target.value));
 },

枢纽性的赋值函数

emitVal

emitVal(newVal) {
  let { max, min } = this;
  // 没有传参数的时分默许值便是undefined
  // 对那个值的限定便是, max以内, min以上
  if (max !== undefined && newVal > max) newVal = max;
  if (min !== undefined && newVal < min) newVal = min;
  // 那里兼容1下位数掌握
  let value = Number(newVal).toFixed(this.precision);
  // 那个oldVal上面会注释:point_down:
  if (value === this.oldVal) return;
  this.oldVal = ls;
  // 收回两个事务, 1个卖力改动value, 1个卖力前往给用户
  // 究竟结果用户不成能监听input事务然后再把值附上来, 太费事
  this.$emit("input", value);
  this.$emit("change", value);
  // 那1步很主要
  // 上面会具体道
  this.$refs.input.value = value;
 }

下面遗留的成绩,那里注释1下.

oldVal: 能避免良多过剩的改动, 好比道用户复造粘揭了1组数出去, 那个数年夜于max, 可是其时显现的数值便是max, 以是便不消衬着了, 或v-model没有行绑定了那个组件, 借绑定了其他各类组件, 致使值超越范畴, 那边也会停止响应的限定, 而那个oldVal 便是上1个开法的值, 以是正在做完检测以后, 检测经由过程的数值要赋值给他.

this.$refs.input.value = value; 那1步看似很出用, 由于输出框内里的是value, value改动input内里的值天然会改动, 可是现实测试其实不是如许, 成绩也是呈现正在v-model上, 绑定良多的时分会呈现值的没有改动, 多是vue的机造成绩, 并且他要放正在 this.$emit(....);上面操纵, 若是放正在下面会致使屡次履行, 由于他的履行会轮回触收input的监听事务, 屡次实验以后, 仍是放正在那里出有bug.
下面的两个成绩皆是触及到v-model的成绩, 上面借有1个同类的成绩, 我们去看看.

对value停止的监控

由于value的变革, 纷歧定满是 经由过程+-输出那3种体例, 借有第3圆经由过程v-model的体例, 借有效户脚骚乱挖的体例.

watch: {
 value: {
  handler() {
  // 为领会决, 多组件配合v-model采取的那个办法, 也算是另辟门路了
  let { value, time } = this;
  clearTimeout(time);
  // 究竟结果把它放进宏使命Macrotasks能够躲过良多无穷轮回.
  time = setTimeout(() => {
   if (value !== undefined) this.emitVal(value);
  });
  },
  // 那个是开启进页里的霎时便动身1次的意义, 很有效, 可是数据稍年夜会耗损机能, 慎用
  // watch借有1个deep属性, 更是吃机能吃的利害, 能够深度监控内里的数据
  immediate: true
 }
 }

下面的成绩皆是基于v-model的, 以是很早便有人剔除单背绑定的害处, 启拆越多的组件觉得便越较着.

4: 闭于款式的断定

正在计较属性内里我们队以后值停止了监控, 前往的是置灰的色彩, 那个让用户自定的意义没有年夜, 以是间接写了.

computed: {
 valueMin() {
  if (this.value === this.min) return "#bbbbbb";
  return "";
 },
 valueMax() {
  if (this.value === this.max) return "#bbbbbb";
  return "";
 }
 },

dom, 面击到了最年夜值的话便会置灰, 我们下面已禁止了持续面击的衬着

做面成心思的事

slot是个自在度很下的标签

把摆布按钮皆包上, 让用户能够本身界说显现的标签是甚么模样的

vue-cc-ui/src/style/inputNumber.scss @import './common/var.scss'; @import './common/extend.scss'; @import './common/mixin.scss'; @import './config/index.scss'; @include b(input-number) { // 友爱的小脚 cursor: pointer; // 有个缩小动绘, 看过我文章的同窗皆晓得, 操纵类的组件, 我喜好有1个悬停缩小结果. transition:all .1s; align-items: center; display: inline-flex; background-color: white; &:hover { // 缩小被其他组件盖住便划没有去了 z-index: 6; transform: scale(1.2); } // 招牌暗影 @include commonShadow($--color-black); @include e(add) { @include flexCenter(); padding: 4px 6px; } @include e(reduce) { @include flexCenter(); padding: 4px 6px; } @include e(input) { // 来失落输出框的默许款式 border: none; outline:none; display: block; text-align: center; width:60px; height: 20px; } }

结果展现

end

总的来讲是那些组件中比力简朴的1个了, 有些坑可以让我更好的进修vue和前真个思惟, 总的来讲挺风趣的.

各人持续1起进修,1起前进, 早日真现自我代价!!

下1散筹办聊聊 tab切换组件的相干常识;

github: 链接描写