亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

從零擼一個pc端vue的ui組件庫( 計數器組件 )

2019-11-19 11:03:37
字體:
來源:轉載
供稿:網友

聽到計數器這個名字很多人是不是一瞬間沒有什么印象, 畢竟這個組件用的比較少,就是那種左邊一個'-'右邊一個'+', 控制某些數量的時候才會用到, 比如我之前做的商城小程序只有'下單'頁面的規格彈出框里面才有他的身影, 如果是涉及到處理商品數量很頻繁的業務場景應該會很常見吧, 但是不要看這個組件小, 編寫它的時候坑還不少, 本次我們就來做一個計數器, 目標就是盡可能小, 盡可能的省性能.

1:需求分析

  • 每次+1 -1是常態, 但是如果搞活動, 每次最少為+-2個或三個, 就要兼容一下了,( 舉一個實際遇到的坑, 我們之前把用戶限制為每次活動, 每個用戶只能買2個, 但是沒有做好防備, 導致用戶可能這次只買一個, 而下次他再次購買的時候會提示每次只能買兩個, 但顯示他只點擊了買一個, 因為他已經買過一個, 為了兼容這個問題, 搞得還要加莫名其妙的補救代碼 )
  • 中間的顯示區應該可輸入的, 用戶想買1000個不可能讓他+1+1+1..., 某些組件采用的是, 平時其為div, 點擊之后變為input, 個人感覺完全沒必要, 一個元素就夠了, 何必搞兩個元素, input狀態下把他的默認樣式去掉就好了.
  • 左右兩邊要有限制, 很多時候會有限購一說, 比如我做的商城, 庫存只有10個 或者單個用戶最多購買3個, 最少買兩個等等限制.
  • 小數位數的顯示一說... 這個其實我還真遇到過, 有一種需求叫做, 只要涉及數字就必須精確到后兩位, 這種需求會導致后臺同學對數據庫做一定的限制, 從而我們傳給后臺的數據也就存在限制了.

2: 基本結構:

先展示一章普通狀態的圖, 讓我們更直觀的去完成它, 造型比較別致, 是本套組件的一個特點, 哈哈做的與別人一樣會導致思想的禁錮, 自己寫代碼多嘗試新的東西, 但是工作中一定要中規中矩, 以公司條款為準則.

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

<template> <div class="cc-input-number"> // 左側的':heavy_minus_sign:'符號 <div class="cc-input-number__reduce">  // 自己封裝的icon組件, 出鏡率還挺高:smirk_cat:.  <cc-icon name='cc-reduce2'/> </div> // 中間的顯示與輸入部分,讓人又愛又恨的number屬性 // 下面的屬性就能干掉凡人的上下按鈕 // input::-webkit-outer-spin-button, // input::-webkit-inner-spin-button { // -webkit-appearance: none; // } <input ref="input"   type="number"   class="cc-input-number__input"> <div class="cc-input-number__add">  <cc-icon name='cc-add2'/> </div> </div></template>

這里我們選擇吧input與button放在一個div里面, 且同級別這種方式, 與其他的不太一樣, 因為這樣更直觀, 而且也足夠實現我想要的功能.

3: 事件的綁定

// 減少 <div class="cc-input-number__reduce"   @click='reduce'> // 增加<div class="cc-input-number__add"   @click="add">// 輸入框的監控<input ref="input"  type="number"  class="cc-input-number__input"  @input="inputChange($event)">

這里我們有個問題, 就是本組件采用的是v-model的形式編寫, v-model有一些弊端, 在測試的時候我發現, 比如說用戶為多個組件綁定了相同的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() {// 很可能用戶就輸入了一個string屬性, // 1: 比如后臺返回的就是字符串;// 2: input框輸入的就是字符串類型;// 3: 用v-model綁定了同樣的值的其他組件賦予了這個值string類型; let num = Number(this.value) + this.step; // 加上固定的長度// 這里我們抽象出一個專門負責數值的變化的函數 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;  // 這里兼容一下位數控制  let value = Number(newVal).toFixed(this.precision);  // 這個oldVal下面會解釋:point_down:  if (value === this.oldVal) return;  this.oldVal = ls;  // 發出兩個事件, 一個負責改變value, 一個負責返回給用戶  // 畢竟用戶不可能監聽input事件然后再把值附上去, 太麻煩  this.$emit("input", value);  this.$emit("change", value);  // 這一步很重要  // 下面會詳細說  this.$refs.input.value = value; }

上面遺留的問題,這里解釋一下.

oldVal: 能防止很多多余的改變, 比如說用戶復制粘貼了一組數進來, 這個數大于max, 但是當時顯示的數值就是max, 所以就不用渲染了, 或者v-model不止綁定了這個組件, 還綁定了其他各種組件, 導致值超出范圍, 這邊也會進行相應的限制, 而這個oldVal 就是上一個合法的值, 所以在做完檢測之后, 檢測通過的數值要賦值給他.

this.$refs.input.value = value; 這一步看似很沒用, 因為輸入框里面的是value, value改變input里面的值自然會改變, 但是實際測試并不是這樣, 問題也是出現在v-model上, 綁定很多的時候會出現值的不改變, 可能是vue的機制問題, 而且他要放在 this.$emit(....);下面操作, 如果放在上面會導致多次執行, 因為他的執行會循環觸發input的監聽事件, 多次試驗之后, 還是放在這里沒有bug.
上面的兩個問題都是涉及到v-model的問題, 下面還有一個同類的問題, 我們來看看.

對value進行的監控

因為value的變化, 不一定全是 通過+-輸入這三種方式, 還有第三方通過v-model的方式, 還有用戶手動亂填的方式.

watch: { value: {  handler() {  // 為了解決, 多組件共同v-model采用的這個方法, 也算是另辟蹊徑了  let { value, time } = this;  clearTimeout(time);  // 畢竟把它放入宏任務Macrotasks可以躲過很多無限循環.  time = setTimeout(() => {   if (value !== undefined) this.emitVal(value);  });  },  // 這個是開啟進頁面的瞬間就出發一次的意思, 很有用, 但是數據稍大會消耗性能, 慎用  // watch還有一個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, 點擊到了最大值的話就會置灰, 我們上面已經阻止了繼續點擊的渲染

<cc-icon size='25px'   name='cc-add2'   :color="valueMax" />

做點有意思的事

slot是個自由度很高的標簽

把左右按鈕都包上, 讓用戶可以自己定義顯示的標簽是什么樣子的

<div class="cc-input-number__reduce"   @click='reduce'>  <slot name='left'>  <cc-icon size='25px'     name='cc-reduce2'     :color='valueMin' />  </slot> </div>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; // 有個放大動畫, 看過我文章的同學都知道, 操作類的組件, 我喜歡有一個懸停放大效果. 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

總的來說是這些組件中比較簡單的一個了, 有些坑能夠讓我更好的學習vue以及前端的思想, 總的來說挺有趣的.

大家繼續一起學習,一起進步, 早日實現自我價值!!

下一集準備聊聊 tab切換組件的相關知識;

github: 鏈接描述

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产成人精品在线视频| 日韩国产高清视频在线| 日韩综合中文字幕| 精品magnet| 色樱桃影院亚洲精品影院| 亚洲精品成人av| 亚洲天堂免费视频| 色综合91久久精品中文字幕| 欧美久久久精品| 欧美日韩免费网站| 精品人伦一区二区三区蜜桃免费| 欧美另类99xxxxx| 久久久久久久久久久久久久久久久久av| 俺去了亚洲欧美日韩| 中文字幕av一区二区三区谷原希美| 51久久精品夜色国产麻豆| 亚洲最大在线视频| 成人午夜小视频| 国产精品白丝av嫩草影院| 亚洲欧美中文日韩在线v日本| 精品视频久久久久久| 欧美日韩国产91| 亚洲精品国产精品久久清纯直播| 日韩美女视频免费看| 亚洲欧美日韩精品久久| 亚洲欧洲午夜一线一品| www.日韩视频| 国产精品香蕉在线观看| 日韩av综合中文字幕| 91美女片黄在线观| 国产精品中文在线| 亚洲白虎美女被爆操| 岛国av一区二区三区| 91精品综合视频| 日韩欧美在线视频观看| 国产日韩欧美视频在线| 欧美一区二区三区免费观看| 日韩成人av网址| 精品免费在线视频| 免费97视频在线精品国自产拍| 亚洲一区国产精品| 日韩av网站在线| 大伊人狠狠躁夜夜躁av一区| 亚洲女同性videos| 欧美成人精品在线观看| 久久精品视频亚洲| 68精品久久久久久欧美| 国产亚洲福利一区| 色视频www在线播放国产成人| 亚洲国产欧美一区二区三区同亚洲| 久色乳综合思思在线视频| 国产精品久久色| 欧美乱大交做爰xxxⅹ性3| 亚洲国产成人精品一区二区| 亚洲自拍小视频免费观看| 亚洲一区国产精品| 久久久www成人免费精品张筱雨| 亚洲精品456在线播放狼人| 高清亚洲成在人网站天堂| 国产午夜精品美女视频明星a级| 日韩国产精品视频| zzijzzij亚洲日本成熟少妇| 91精品国产91久久久久| 伊人成人开心激情综合网| 久久亚洲精品毛片| 日韩在线一区二区三区免费视频| 欧美精品做受xxx性少妇| 欧美精品videos| 国产成一区二区| 色综合伊人色综合网站| 国产热re99久久6国产精品| 欧美一级成年大片在线观看| 国产精品久久99久久| 2025国产精品视频| 久久大大胆人体| 日韩欧美在线中文字幕| 国产综合色香蕉精品| 欧美黑人xxxx| 国产成人精品优优av| 亚洲a∨日韩av高清在线观看| 国产精品激情av在线播放| 久久久久在线观看| 日韩欧美精品网站| 久久久999国产| 久久人人爽人人爽人人片av高清| 欧美成人激情图片网| 中文字幕久久久av一区| 欧美日韩国产精品一区二区不卡中文| 68精品久久久久久欧美| 久久九九免费视频| 欧美日韩另类在线| 国产精品视频成人| 成人h视频在线| 色综合视频一区中文字幕| 国产在线观看精品| 亚洲精品视频在线观看视频| 欧美极品少妇xxxxⅹ免费视频| 精品欧美一区二区三区| 国产精品高潮呻吟久久av野狼| 亚洲午夜精品久久久久久性色| 日韩中文字幕在线精品| 色无极影院亚洲| 日韩一区二区福利| 91av成人在线| 亚洲a中文字幕| 国产在线观看一区二区三区| 欧美伦理91i| 日本在线精品视频| 欧美成人激情在线| 欧美激情中文字幕乱码免费| 日韩免费在线观看视频| 久久99国产精品久久久久久久久| 亚洲国产精品电影在线观看| 亚洲国产精品高清久久久| 欧美综合第一页| 精品人伦一区二区三区蜜桃免费| 美女精品视频一区| 国产成人在线一区| 福利一区福利二区微拍刺激| 日韩小视频在线| 国产99久久久欧美黑人| 亚洲精品短视频| 国产精品欧美激情| 欧亚精品在线观看| 国产精品久久久久免费a∨大胸| 欧美日韩精品国产| 久久福利网址导航| 81精品国产乱码久久久久久| 国产精品老女人视频| 亚洲视频axxx| 久久手机精品视频| 亚洲第一男人天堂| 亚洲欧洲国产伦综合| 欧美黑人xxxx| 国产三级精品网站| 亚洲xxxx3d| 亚洲国产精品嫩草影院久久| 中文字幕免费精品一区高清| 国产日韩中文字幕在线| 久久999免费视频| 欧美孕妇与黑人孕交| 欧美黄色三级网站| 91chinesevideo永久地址| 欧美午夜电影在线| 亚洲伊人久久综合| 91av在线影院| 久久人人爽亚洲精品天堂| 国产精品白丝jk喷水视频一区| 日韩在线视频二区| 欧美日韩激情小视频| 成人午夜在线观看| 69**夜色精品国产69乱| 亚洲一区二区三| 精品久久久精品| 日韩精品中文字幕在线观看| 亚洲欧美中文字幕在线一区| 国产ts一区二区| 亚洲最大av在线| 日本韩国欧美精品大片卡二| 欧美人与性动交| 日韩欧美极品在线观看| 精品免费在线视频| 国产日韩在线一区| 亚洲欧洲视频在线|