自定義元件中如何用v-model?聊聊.sync修飾符的使用場景

2022-02-01 10:00:25
自定義元件中如何用v-model?什麼場景下會使用 .sync 修飾符?下面本篇文章給大家介紹一下自定義元件中使用v-model的方法、.sync修飾符的使用場景,希望對大家有所幫助!

【相關推薦:】

如何在自定義元件使用 v-model ?

答:

1.png

程式碼實現如下:

<input :value="value" @input="handleInput" placeholder="edit me" />

  // ...
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  methods: {
    handleInput(e) {
      this.$emit('input', e.target.value)
    }
  }
  // ...

參照的地方:

<v-base-model v-model="baseModelValue" />
// ...
data() {
  return {
    baseModelValue: ''
  }
}
// ...

可以看到,一個元件上的 v-model 預設會利用名為 value 的 prop 和名為 input 的事件,但是像單選框、核取方塊等型別的輸入控制元件可能會將 value 屬性用於不同的目的

model 選項可以用來避免這樣的衝突:

自定義 prop 名和事件名,程式碼實現如下:

<input type="checkbox" :checked="checked" @change="handleChange" />

  // ...
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  methods: {
    handleChange(e) {
      this.$emit('change', e.target.checked)
    }
  }
  // ...

參照的地方:

<v-base-checkbox v-model="baseCheckboxValue" />

data() {
  return {
    baseCheckboxValue: false
  }
}

這裡的 baseCheckboxValue 的值將會傳入這個名為 checked 的 prop。同時當 <v-base-checkbox> 觸發一個 change 事件並附帶一個新的值的時候,baseCheckboxValue 的值將會被更新。

⚠️ 注意你仍然需要在元件的 props 選項裡宣告 checked 這個 prop。

說實話,日常開發中,我不是很喜歡直接寫 v-model,不寫 v-model 可以讓程式碼更容易被理解,因為傳參值和事件都一目瞭然嘛,而且也符合單向資料流的特點。

但是用了 v-model 確實會讓程式碼簡潔很多,有利有弊,就看取捨了。

什麼場景下會使用 .sync 修飾符?

答:父子元件互動,父元件傳遞給子元件 prop 值,子元件丟擲事件,通知父元件改變這個繫結的值,可以用 .sync 修飾符簡寫。

第一次接觸 .sync 修飾符,是我在使用 element-ui 的 dialog 元件時,看到visible屬性上有這麼一個鬼東西。

2.png

3.png

我心想,還實現了非同步和同步的情況下展示彈窗嗎,是不是還有個 .async 寫法。

然後去看了 vue 檔案,才發現自己太年輕了,還好遇到不懂的都是自己先去查一查,要是直接去問同事,會很羞恥的,hhh。

那麼這個 .sync 修飾符到底是怎麼用的呢?彆著急,要理解 .sync 修飾符的用法,還是要從 vue 單向資料流說起。

在文章 中,我們聊到了 vue 的單向資料流。

子元件不能改變父元件傳遞給它的 prop 屬性,推薦的做法是它丟擲事件,通知父元件自行改變繫結的值。

我們通過一個計數器功能來感受 vue 的單向資料流

子元件程式碼:

<template>
  <div class="test-sync">
    <button @click="add">count + 1</button>
    <p>我們是ti {{ count }} 冠軍</p>
  </div>
</template>

<script>
export default {
  name: 'test-sync',
  props: {
    count: {
      type: Number,
      default: 0
    }
  },
  methods: {
    add() {
      this.$emit('update:count', this.count + 1)
    }
  }
}
</script>

父元件程式碼:

<test-sync :count="count" @update:count="handleAdd" />
//...
data() {
  return {
    count: 8
  }
}
//...
methods: {
  handleAdd(val) {
    this.count = val
  }
}

4.gif

可以看到,我們通過子元件丟擲事件,通知父元件改變繫結的值,實現了子元件 prop 值的變更。

整個流程如下:

5.png

這樣的單向資料流的寫法,是 vue 一直推薦的,vue 為了方便這種寫法,在 2.3.0 版本新增了 .sync 修飾符這個語法糖。

把上面的計數器功能用 .sync 改寫一下。

父元件程式碼:

<test-sync :count.sync="count" />
//...
data() {
  return {
    count: 8
  }
}
//...

是不是簡潔了許多,有了 .sync 修飾符,就不用再寫事件了

⚠️ 注意,子元件內部 emit 事件的時候,事件名必須寫成 update:count 的形式,不然 .sync 功能無法生效。

看著名字如此高大上的功能,居然和 v-model 一樣,只是一個語法糖,我瞭解到真相後,只能手動[捂臉哭]。

那麼回到 element-ui dialog 彈窗的 visible 屬性,該怎麼去用 .sync 屬性呢?

很顯然,也只是語法糖而已,使用 .sync 修飾符的話,可以少寫一點程式碼。

<el-dialog :visible="dialogVisible" @close="dialogVisible = false">

等價於

<el-dialog :visible.sync="dialogVisible">

⚠️ 注意,不寫 .sync 修飾符的話,一定要手動地去呼叫 close 方法,然後把 dialogVisible 置為 false,不然即使點選關閉按鈕也無法關閉彈窗。

為了驗證我們的想法,直接去檢視 element-ui 的原始碼

6.png

果然在 dialog 元件原始碼的 178 行中發現了我們想要的程式碼:

this.$emit('update:visible', false);

總結

在之前的文章《》 中,我們聊到了 vue 的單向資料流。

這一講,我們繼續聊 v-model 和 .sync 修飾符,結果還是重點講了 vue 的單向資料流

可見,vue 的單向資料流思想有多麼重要,它幾乎影響到了你日常開發中的所有元件的設計。

早年的我啥也不懂,直接上手寫頁面,導致測試的時候,各種 bug 層出不窮,究其根本,就是沒有理解 vue 單向資料流的思想,設計的元件資料流轉出了問題,還越陷越深,為了解 bug 寫出更多 bug。

以後再有人問你 v-model 和 .sync 修飾符相關的問題,咱啥也不管,先把 vue 的單向資料流講一遍。

希望我的 vue 系列文章能幫助到前端路上的你。

更多程式設計相關知識,請存取:!!

以上就是自定義元件中如何用v-model?聊聊.sync修飾符的使用場景的詳細內容,更多請關注TW511.COM其它相關文章!