# 自定义事件

# 事件名

<!-- 没有效果 -->
<my-component v-on:my-event="doSomething"></my-component>

<script>
  this.$emit('myEvent'); // 需要修改为 this.$emit('my-event')
</script>

# 自定义组件的v-model, model选项

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

<input type="checkbox" v-model="checked">
等价于
<input 
  type="checked" 
  :checked="checked" 
  @change="checked=$event.target.checked"
>

自定义一个组件使用v-model,一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突:

<div id="app">
  <my-checkbox v-model="mychecked"></my-checkbox>
  <p> mychecked: {{ mychecked }}</p>
</div>
<script>
  Vue.component('my-checkbox', {
    model: {
      prop: 'checked',
      event: 'change'
    },
    props: {
      checked: Boolean
    },
    template: `
      <input 
        type="checkbox" 
        :checked="checked" 
        @change="$emit('change', $event.target.checked)"
      >
    `
  })
  var app = new Vue({
    el: '#app',
    data: {
      mychecked: false
    }
  })
</script>

# .native与$listeners 属性

在一个组件的根元素上直接监听一个原生事件,可以使用v-on的.native修饰符

<div id="app">
  <base-input 
    v-on:focus.native="onFocus" 
    :value="name" 
    @input="name=$event"
  ></base-input>
</div>
<script>
  Vue.component('base-input', {
    props: ['value'],
    template: `
      <input 
        v-bind="$attrs"
        v-bind:value="value"
        v-on:input="$emit('input', $event.target.value)"
      >
    `
  })
  var app = new Vue({
    el: '#app',
    data: {
      name: '',
    },
    methods: {
      onFocus: function(event) {
        console.log('focus')
      }
    }
  })
</script>

# 非根级元素绑定事件

Vue.component('base-input', {
  inheritAttrs: false,
  props: ['label', 'value'],
  computed: {
    inputListeners: function () {
      var vm = this
      // `Object.assign` 将所有的对象合并为一个新对象
      return Object.assign({},
        // 我们从父级添加所有的监听器
        this.$listeners,
        // 然后我们添加自定义监听器,
        // 或覆写一些监听器的行为
        {
          // 这里确保组件配合 `v-model` 的工作
          input: function (event) {
            vm.$emit('input', event.target.value)
          }
        }
      )
    }
  },
  template: `
    <label>
      {{ label }}
      <input
        v-bind="$attrs"
        v-bind:value="value"
        v-on="inputListeners"
      >
    </label>
  `
})

# .sync修饰符

props属性是单向的,子组件改动不会传到父组件,如果需要将子组件的值传回去,可以使用.async, 参考: 深入理解vue 修饰符sync【 vue sync修饰符示例】 (opens new window)

<comp :foo.sync="bar"></comp>
会被扩展为
<comp :foo="bar" @update:foo="val => bar = val"></comp>

<!-- 在子组件里面使用 $emit('update:foo', newValue); // 即可更新bar的值
--?

当用一个对象同时设置多个 prop 的时候,也可以将这个 .sync 修饰符和 v-bind 配合使用: 这样会把 doc 对象中的每一个属性 (如 title) 都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器。

上次更新: 2020/10/29 22:59:19