1. 程式人生 > 程式設計 >Vue 如何使用props、emit實現自定義雙向繫結的實現

Vue 如何使用props、emit實現自定義雙向繫結的實現

下面我將使用Vue自帶的屬性實現簡單的雙向繫結。

下面的例子就是利用了父元件傳給子元件(在子元件定義props屬性,在父元件的子元件上繫結屬性),子元件傳給父元件(在子元件使用$emit()屬性定義一個觸發方法,在父元件上的子元件監聽這個事件)。

import Vue from 'vueEsm' 

var Com = {
  name:'Com',props:['val'],template:`<input type='text' @input='handleInput'/>`,methods: {
    handleInput(e){
      this.$emit("input",e.target.value);
    }
  },}

new Vue({
   el:'#app',data() {
     return {
       value:''
     }
   },components:{
    Com
   },template:`
   <div>
   <Com @input='post' :val='value'></Com>
   </div>
   `,methods:{
    post(data){
      this.value=data;
    }
   }
 })

上面這個例子,在input標籤上每次輸入時觸發原生事件input,在這個事件上綁定了一個handleInput方法,事件每次觸發都會執行方法裡的$emit屬性。該屬性裡面第一個引數可以定義一個事件名,第二個引數可以傳一個引數。這裡我們把每次輸入的值e.target.value傳進去。在父元件的子元件上監聽這個事件,定義一個post方法,方法的引數就是傳入的資料。然後我們在父元件的data屬性裡定義一個儲存值的變數value。將剛才傳入的引數賦給這個變數value。最後在父元件的子元件上繫結一個自定義屬性,比如val。將value傳給val。在子元件定義一個props屬性接受這個val。

這個例子對於理解父元件與子元件傳值特別重要。

下方舉例說明了我的一個自定義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,.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的字串陣列簡寫方式,但是這樣的話對使用元件時的錯誤除錯不利。所以,儘量不要學我偷懶噢,親~~~

到此這篇關於Vue 如何使用props、emit實現自定義雙向繫結的實現的文章就介紹到這了,更多相關Vue props、emit實現自定義雙向繫結內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!