VUE實現自定義雙向綁定組件

前言:要實現vue的雙向綁定組件,我們實際上需要清楚v-model指令的實際底層交互實現。v-model實際上包含了默認屬性value和默認事件input的父子組件通信過程。

下方舉例說明了我的一個自定義mySelect的實現過程:

<template>
  <div class="select">
    <div class="input" @click="collapse=!collapse">
      <span v-if="currentValue">{{currentLabel||currentValue}}</span>
      <span v-else class="placeholder">{{placeholder}}</span>

      <span :class="collapse?'arrow-down':'arrow-up'"></span>
    </div>

    <div class="option-list" v-show="!collapse">
      <div class="option-item" v-for="item in data" :key="item.id" @click="chooseItem(item)">{{item[itemLabel?itemLabel:'name']}}</div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "mySelect",
    props: [
      'value',
      'placeholder',
      'data',
      'itemLabel',
      'itemValue'
    ],
    data() {
      return {
        collapse: true,
        currentValue: '',
        currentLabel: '',
      }
    },
    watch: {
      value: {
        immediate: true,
        handler(value) {
          this.currentValue = value;
          this.$emit('input', value);
          this.data.forEach(item => {
            if (item[this.itemValue ? this.itemValue : 'id'] == value) {
              return this.currentLabel = item[this.itemLabel ? this.itemLabel : 'name'];
            }
          });
        }
      },
      data:{
        immediate: true,
        handler(arr) {
          if(this.value||!this.currentLabel){
            arr.forEach(item=>{
              if(item[this.itemValue ? this.itemValue : 'id'] == this.value){
                this.currentLabel = item[this.itemLabel ? this.itemLabel : 'name'];
                return;
              }
            })
          }
        }
      }
    },
    methods: {
      chooseItem(item) {
        if (this.currentValue !== item[this.itemValue ? this.itemValue : 'id']) {
          this.$emit('change',item[this.itemValue ? this.itemValue : 'id']);
        }
        this.currentValue = item[this.itemValue ? this.itemValue : 'id'];
        this.currentLabel = item[this.itemLabel ? this.itemLabel : 'name'];
        this.$emit('input', this.currentValue);
        this.collapse = true;
      }
    }
  }
</script>

<style lang="scss" scoped>
  .select {
    position: relative;

    .input {
      width: 100%;
      height: 30px;
      line-height: 30px;
      background-color: #fff;
      border: 1px solid #02b4fe;
      border-radius: 0 3px 3px 0;
      padding-left: 10px;
      color: #666;
      position: relative;
      .placeholder {
        color: #aaa;
      }
    }

    .arrow-down {
      width: 0;
      height: 0;
      border-left: 5px solid transparent;
      border-right: 5px solid transparent;
      border-top: 8px solid #02b4fe;
      position: absolute;
      right: 5px;
      top: 10px;
    }

    .arrow-up {
      width: 0;
      height: 0;
      border-left: 5px solid transparent;
      border-right: 5px solid transparent;
      border-bottom: 8px solid #02b4fe;
      position: absolute;
      right: 5px;
      top: 10px;
    }

    .option-list {
      max-height: 200px;
      overflow-y: scroll;
      position: absolute;
      top: 2rem;
      left: 0;
      z-index: 5;
      width: 100%;
      padding: 0 5px;
      font-size: 10px;
      color: #aaa;
      background-color: #fff;
      text-align: left;
      box-shadow: 0 0 5px rgba(0, 0, 0, .1);
      border: 1px solid rgb(79, 192, 232);

      .option-item {
        text-align: center;
        line-height: 1.5rem;
      }
    }
  }
</style>

如上所示,當聲明了mySelect組件之后,在項目中實際使用時,就可以如下所示直接使用:

<template>
  <mySelect v-model="testValue" placeholder="請選擇" :data="testArr" item-label="id"
                      item-value="name"></mySelect>
</template>
<script>
    import mySelect from './mySelect'
    
    export default{
        components:{
          mySelect
        },
         data(){
            return {
                  testValue:'',
                  testArr:[]
             }
          },
          mounted(){
            //預置select的下拉選擇基礎數據,數據為對象數組,包含id和name屬性
          }
}
</script> 

以上就是一個簡單的自定義雙向綁定組件的實現,包括簡單的使用過程。在vue中的自定義組件,關于props的聲明時,還是盡量使用官方建議的對象方式,可以聲明屬性的默認值和數據類型。我這邊偷懶了用的是props的字符串數組簡寫方式,但是這樣的話對使用組件時的錯誤調試不利。所以,盡量不要學我偷懶噢,親~~~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。