linche0859
8/29/2019 - 8:19 AM

深入Component

事件名

component 中觸發一個 camelCase 名字的事件

this.$emit('myEvent')

父組件使用不能使用kebab-case

<!-- 没有效果 -->
<my-component @my-event="doSomething"></my-component>

需也使用camelCasePascalCase

<my-component @myEvent="doSomething"></my-component>

將原生事件綁定到 Component

替整個 component 加上事件(click,focus),需使用.native修飾詞

<base-input @focus.native="onFocus"></base-input>

但如果當base-input

<label>
  {{ label }}
  <input
    v-bind="$attrs"
    v-bind:value="value"
    v-on:input="$emit('input', $event.target.value)"
  />
</label>

因為實際上它是一個<label>,父層的.native監聽器會失敗,也不會報錯,onFocus也不會被調用

解決方法

命名規則

如果在Vue Instance中的$data變數為camelCase,則在HTML中需改為kebab-case

<child style="border:1px solid #CCC;" :msg-text.sync="msgText" />
Vue.component('child', {
  template: '#child-template',
    props: {
      msgText: {
        type: String,
        required: true
      }
    },
    computed: {
      newVal: {
        get() {
          return this.msgText
        },
        set(newVal) {
          this.$emit('update:msgText', newVal)
        }
      }
    }
})

new Vue({
  el: '#app',
  data() {
    return {
      msgText: 'test'
    }
  }
})

.sync 修飾詞

欲修改父層的資料,推薦使用update:myPropName,如

this.$emit('update:title', newTitle)

父層的屬性

<text-document
  :title="doc.title"
  @update:title="doc.title = $event"
></text-document>

使用.sync修飾詞

<text-document :title.sync="doc.title"></text-document>

如要傳遞多個 prop 的時候,可以將.syncv-bind配合使用

<text-document v-bind.sync="doc"></text-document>

這樣會把 doc 物件中的每一個屬性 (如 title) 都作為一個獨立的 prop 傳進去

$emit

自定義事件

  1. 子層發出 $emit 夾帶 value
  2. 父層接收事件,而觸發綁定的函式

😎 簡單來說: 子層使用父層的事件

範例

父層.vue

<custom-checkbox :item="item" @changeHandler="toggleTodo" />

<script>
  import customCheckbox from './customCheckbox.vue';
  export default {
    components: {
      customCheckbox
    },
    methods:{
      toggleTodo(){
        ...
      }
    }
  }
</script>

子層.vue

<template>
  <div class="squaredFour">
    <input
      type="checkbox"
      :id="getID"
      :checked="item.done"
      @change="handleChange"
    />
    <label :for="getID" class="checkbox-icon"></label>
    <label :for="getID">{{ item.content }}</label>
  </div>
</template>

<script>
  export default {
    props: {
      item: Object
    },
    computed: {
      getID() {
        // 為了解決 input 與 label 對應的 id
        return `custom_${Math.floor(Math.random() * 9999)}`
      }
    },
    methods: {
      handleChange($event) {
        // $emit 向上傳遞的 value 包成 object
        this.$emit('changeHandler', {
          key: this.item.key,
          // checked(done) 直接使用 chackbox 狀態
          checked: $event.target.checked
        })
      }
    }
  }
</script>