<template>
  <div>
    <!-- 能保证 v-model 可以在最底层组件使用。通过将底层的事件往上传，而不是在中间层修改 -->
    <input v-bind="$attrs" v-bind:value="value" v-on="inputListeners" />

    <!-- 这个会报错: mutate props -->
    <!-- <input v-model="value"> -->
  </div>
</template>

<script>
export default {
  name: "myinput",
  props: {
    value: {
      type: Number,
      default: 2333,
    },
  },
  computed: {
    inputListeners: function() {
      var vm = this;
      console.log(this.$listeners.input); // 从调用 <myinput @input /> 而来
      // `Object.assign` merges objects together to form a new object
      return Object.assign(
        {},
        // We add all the listeners from the parent
        // 不会覆盖父组件的listener。是怎么通知父组件的呢？this是谁?
        // 比如 <myinput @focus />, <input @focus='focus' />, 被调用时，会触发？？？
        this.$listeners,
        // Then we can add custom listeners or override the
        // behavior of some listeners.
        {
          // This ensures that the component works with v-model
          input: function(event) {
            vm.$emit("input", +event.target.value);
          },
        }
      );
    },
  },
};
</script>
