前端項目框架搭建隨筆---input組件的編寫

接上篇文章,費心勞神好幾天的項目框架終於能夠用了。如今能夠開始寫頁面了吧?javascript

既然上司說,UI框架咱們本身來寫,那咱們就本身寫吧。css


雖然答應的時候挺痛快。真到寫的時候,首先就不知道從哪裏開始下手了html

那咱們就一點點來。先從組件框架開始一點點作。html5


首先先排布一下UI框架目錄。在於上司聊了許久後,最後決定用這種目錄架構:java


紅色箭頭表明業務組件(business components) 存放項目中業務類組件的地方。如頭部導航,我的信息卡等正則表達式

綠色箭頭表明業務組件(framework components) 存放項目中基礎框架組件的地方。如按鈕,輸入框,開關等
bash

藍色箭頭是導出文件。統一導出全部組件方便調用(文章後面會講到)架構


好的,那咱們先從input開始app


input組件的編寫

咱們先看看效果圖:框架


大體就是這個樣子。很是簡潔的UI,功能也算是夠用了。(這裏給UI大哥的做品點個贊)

我把它拆分紅了這個樣子(如圖) 每一個顏色框內都是不一樣的slot(具名插槽)


大體代碼就是這個樣子的存在:

<template>
  <div class="input-wrapper">
    <div class="input-content">
      <div class="input__left">
        <slot name="left"></slot> //紅色框插槽
      </div>
      <div class="input__center">
        <input type="text" title="">
        <div class="input__center__tools">
          <i class="iconfont icon-qingchu" v-show="inputValue" @click="clearInputValue"></i> 
         //清除value的地方
        </div>
      </div>
      <div class="input__right">
        <slot name="right"></slot> //input右側的自定義區。能夠放置「獲取驗證碼」之類的操做
      </div>
    </div>
    <div class="input-tip">
      <slot name="tip"></slot> //下方提示區域插槽
    </div>
  </div>
</template>複製代碼

css方面選用flex佈局。字體/圖標大小,元素間距使用rem佈局 class命名使用bem方式

CSS:

<style scoped>
  .input__left .iconfont {
    font-size: 2rem;
  }

  .input-content {
    display: flex;
    flex-direction: row;
  }

  .input__left {
    padding-bottom: 0.4rem;
  }

  .input__left > span {
    font-size: 1.5rem;
  }

  .input__center {
    margin-left: .5rem;
    flex: 1;
    display: flex;
    flex-direction: row;
    padding-bottom: .3rem;
    border-bottom: 1px solid #E9E9E9;
  }

  .input__center > .input__center__tools > .iconfont {
    color: #141414;
    cursor: pointer;
    font-size: 2rem;
  }

  .input__center > input {
    text-indent: .3rem;
    flex: 1;
    border: 0;
    width: 100%;
    height: 100%;
    font-size: 1.3rem;
    color: #3b3b3b;
    outline: none;
  }

  .input__right {
    padding-left: .5rem;
    padding-bottom: .3rem;
    border-bottom: 1px solid #E9E9E9;
  }

  .icon-qingchu {
    color: #E9E9E9 !important;
  }

  .input-tip {
    margin-top: .3rem;
    margin-left: 2.45rem;
    font-size: 1rem;
  }

  .input-tip i {
    font-size: 1rem;
  }

  .input-tip--info {
    color: #BFBFBF;
  }

  .input-tip--success {
    color: #5CD18B;
  }

  .input-tip--warning {
    color: #FFC53D;
  }

  .input-tip--error {
    color: #FF7875;
  }
</style>
複製代碼


OK,這時候咱們的UI畫完了。還能輸入文字...不錯哦

這時候遇到了一個問題:以前咱們直接v-model就能夠雙向數據綁定input的value。如今input在組件內包着。那咱們如何在父組件綁定子組件內的input呢??

找了半天教程,找到了這樣一個操做:

給組件添加 v-model 屬性時,默認會把 value 做爲組件的屬性,而後把 'input' 值做爲給組件綁定事件時的事件名

啊哈,這樣就好說了。那咱們能夠這樣去寫:

<input :type="textType" title="" v-model="inputValue"
       @input="$emit('input', inputValue)">

export default{
  data() {
    return { 
     inputValue: "" //子組件內綁定一遍。等會要用
     }
   },
  }

複製代碼

外部調用:

<zb-input v-model="phoneLogin.phone.value">複製代碼

這樣就大功告成了。這樣父組件調用方就能夠綁定到輸入框的值了




OK,接下來咱們開始作「一鍵清空」功能

因爲咱們傳出去的值,是走的子組件內的雙向綁定的data。因此理論上咱們只須要把綁定在data內的變量清空就好了

this.inputValue = '';複製代碼

可是這樣會有問題,子組件內已經清空,父組件仍然保留着值。

那咱們就模仿上面的作法,再$emit一次~~~

clearInputValue() {
  this.inputValue = ''; //清空輸入框的值
  this.$nextTick(function () { //在修改數據以後使用 $nextTick,則能夠在回調中獲取更新後的 DOM
    this.$emit('input', this.inputValue); //執行傳出操做
  });
},複製代碼

這樣功能就實現了。以下圖( 清除按鈕的顏色太淺。動圖錄制軟件看不見~~~ 抱歉)



好的,那接下來實現一下密碼「顯示」「隱藏「的功能




這個功能也比較有意思。不僅是把輸入框的type換成password那麼簡單。還能還原以前傳入的input type

首先咱們先定義一個props:

inputType: { //輸入框類型
  default: 'text'
}
canHide: {  //是否支持隱藏值
  required: false,
  default: false
},

複製代碼

這個props從父組件接收想要的input類型。若是沒有就默認text

而後copy一份同義的變量到data裏。保持以prop作參考,data負責內部更改~~~

textType: this.inputType //從props裏接收初始值
isHideValue: false //如今是否隱藏輸入框值複製代碼

而後清除事件:

hideInputValue() {
  if (this.textType === this.inputType) { //若是props內和data內相等。說明是沒隱藏狀態
    this.textType = "password"; //讓他變爲password類型
    this.isHideValue = true; //控制隱藏按鈕的類名。更換icon
  } else {
    this.textType = this.inputType; //替換爲初始化的type
    this.isHideValue = false;
  }
}複製代碼

按鈕方面:

<i class="iconfont"
   :class="[{'icon-yanjing_yincang_o':!isHideValue},{'icon-yanjing_xianshi_o':isHideValue}]"
   @click="hideInputValue" v-show="canHide && inputValue"></i>複製代碼


這樣就大功告成啦!!


既然咱們作input了,那就作到底唄~~

讓他支持一下自定義規則驗證


經過和上司商定,暫選了這幾個規則支持:


1. lengthRange: Object 支持max,min最大最小值

2. regular: 標準正則表達式

3. required: Boolean 是否必填


數據格式大概是這樣的:

regex: {
  required:false,
  lengthRange: {
    max: 11,
    min: 1
  },
  regular: /^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$/
}複製代碼

而後經過props傳進去:

regexObject: { //校驗對象
  required: false
}

:regexObject="regex"複製代碼


而後準備工做作好了,開始準備校驗工做了

校驗順序按照隊列校驗。分別各自返回校驗結果。沒有指定的放行

是否必填校驗:

reg_required(value) {
  if (this.regexObject.required) { //若是有required這個字段
     return !!value //返回value是否有值
  } else {
    return null; //表明沒填required這個字段
  }
},複製代碼

Tips:" !! " 經常用來作類型判斷,在第一步!(變量)以後再作邏輯取反運算。簡單理解就是判斷這個變量是否存在值。

等價 " value!=null&&typeof(value)!=undefined&&value!='' "

正則表達式校驗:

reg_regular(value) {
  if (this.regexObject.regular) { //若是有regular這個字段
    return this.regexObject.regular.test(value); //返回校驗的結果
  } else {
    return null; //表明沒填regular這個字段
  }
},複製代碼

長度校驗:

reg_lengthRange(value) {
  if (this.regexObject.lengthRange) { //若是有lengthRange這個字段
    return value.length >= this.regexObject.lengthRange.min //若是value的長度大於等於預約最小值
      && value.length <= this.regexObject.lengthRange.max //若是value的長度小於等於預約最大值
  } else {
    return null; //表明沒填lengthRange這個字段
  }
},複製代碼


主入口方法

regex(value) {
  let val = value.toString(); //統一轉成字符串。防止沒有length屬性
  let info = {}; //空對象
  info.value = val; //一塊把輸入框的值傳出去
  if (this.regexObject) { //若是props傳了校驗對象
    info.required = this.reg_required(val);
    info.regular = this.reg_regular(val);
    info.lengthRange = this.reg_lengthRange(val);
  }
  return info;
},複製代碼


最後在輸入框失焦事件(blur)內調用了一下:

inputReg() {
  console.log(this.regex(this.inputValue));
},複製代碼


控制檯:



本身體會~~~

而後發現了個bug,雖然定義了最大輸入範圍,但超出只是提示不由止輸入


因而watch監聽一下inputValue

inputValue(){
  if (this.regexObject && this.regexObject.lengthRange) {
    if (this.inputValue.length > this.regexObject.lengthRange.max) { //若是輸入框長度大於了既定最大長度
      this.inputValue = this.inputValue.slice(0, this.regexObject.lengthRange.max);//從0開始截取。截到最大長度
      return false;
    }
  } else {
    return false;
  }
}複製代碼

由於html5把maxlength屬性去掉了.....因此只能字符串截取


這樣一個入門級別的Input就作好了!!功能還算是比較實用


下一篇寫Tab組件的實現方式。各位週末愉快~~~週日晚繼續寫

相關文章
相關標籤/搜索