vue 自定義組件 v-model


官方的介紹講得比較全,這里就省去復制粘貼的步驟了。此處模擬一種非表單元素的 v-model 組件:

類似復選框,在組件里點選不同的選項,然后能跟父組件雙向綁定。

1. 首先做好基礎的排版及樣式

<template>
  <div style="padding:10px">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
  </div>
</template>

<style scoped>
  span{
    display: inline-block;
    width: 80px;
    height: 30px;
    line-height: 30px;
    border-radius: 4px;
    border: 1px solid #333;
    color: #333;
    text-align: center;
  }
  span.active{
    border-color: #f45619;
    color: #f45619;
  }
</style>

2. 添加 model 屬性

根據文檔內容,v-model 需要兩個屬性:value、event,一個用來傳值(父傳子),一個用來接收並賦值(子傳父)。

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

我們定為 val、change 以示區分

<script>

export default {
  model:{
    prop:'val',
    event:'change'
  },
  // val 這個值本身是不存在的,所以需要通過 props 定義
  props:{
    val: Array,
  },
  
};
</script>

3. 接下來,我們把數據進一步處理,通過 computed 計算屬性操作父組件傳過來的值。val 為 0,1,2,3 中的值組成的數組,如:[ 1,3 ]。通過 computed 轉換為 list : [ 0,1,0,1]

<template>
  <div style="padding:10px">
    <span :class="{'active':list[0]}" >1</span>
    <span :class="{'active':list[1]}" >2</span>
    <span :class="{'active':list[2]}" >3</span>
    <span :class="{'active':list[3]}" >4</span>
  </div>
</template>

<script>

export default {
  model:{
    prop:'val',
    event:'change'
  },
  // val 這個值本身是不存在的,所以需要通過 props 定義
  props:{
    val: Array,
  },
  computed:{
    list(){
      let arr = []
      this.val.forEach(i=>{
        let n = parseInt(i)
        arr[n] = 1
      })
      return arr
    }
  },
};
</script>

<style scoped>
  span{
    display: inline-block;
    width: 80px;
    height: 30px;
    line-height: 30px;
    border-radius: 4px;
    border: 1px solid #333;
    color: #333;
    text-align: center;
  }
  span.active{
    border-color: #f45619;
    color: #f45619;
  }
</style>

4. 到這里實現了單向的綁定,然后根據子組件的事件操作給父組件傳值。通過子組件的點擊事件觸發父組件的事件提交,並把新值帶給父組件

<template>
  <div style="padding:10px">
    <span :class="{'active':list[0]}" @click="onTap(0)">1</span>
    <span :class="{'active':list[1]}" @click="onTap(1)">2</span>
    <span :class="{'active':list[2]}" @click="onTap(2)">3</span>
    <span :class="{'active':list[3]}" @click="onTap(3)">4</span>
  </div>
</template>

<script>

export default {
  model:{
    prop:'val',
    event:'change'
  },
  // val 這個值本身是不存在的,所以需要通過 props 定義
  props:{
    val: Array,
  },
  computed:{
    list(){
      let arr = []
      this.val.forEach(i=>{
        let n = parseInt(i)
        arr[n] = 1
      })
      return arr
    }
  },
  methods:{
    onTap(n){
      console.log(n)
      let list = this.list
      list[n] = !list[n]
      let res = []
      list.map((i, idx)=>{
        if(i) res.push(idx)
      })
      // 注意
      // 此處的 change ,來自一開始定義在 model 屬性里的event
    // 父組件在接收到傳過來的新值后,會用這個新值更新 val 屬性,這樣就會更新了自組件的值,完成雙向綁定的過程
this.$emit('change',res)
}
}
};
</script>

<style scoped> span{ display: inline-block; width: 80px; height: 30px; line-height: 30px; border-radius: 4px; border: 1px solid #333; color: #333; text-align: center; } span.active{ border-color: #f45619; color: #f45619; } </style>

5. 父組件引用:

// 父組件
<template>
  <div class="hello">
    <hello v-model="value"></hello>
  </div>
</template>

<script>
import hello from '@/components/model'
export default {
  components:{ hello },
  data () {
    return {
      value:[1,3],
    }
  },
}
</script>

 

 

 

參考官方文檔 :

在組件上使用 v-model 、 自定義組件的 v-model


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM