attrs的使用与v-model

253 阅读1分钟

$attrs的使用

当我们传递给一个组件某个属性,但是该属性并没有定义对应的props或者emits时,就称之为 非Prop的

Attribute。 例如class,style,id。

当组件有单个根节点时,非Prop的Attribute将自动添加到根节点的Attribute中。如果不希望组件的根元素继承attribute,可以在组件中设置 inheritAttrs: false。并且通过$attrs来访问非Props的Attribute属性。

定义一个子组件ShowMessage.vue。可见我们想要为h2提供非props的属性。

<template>
  <div>
    <!-- 将父组件传递的非props的attribute属性给h2 -->
    <h2 v-bind="$attrs">{{ title }}</h2>
    <p>{{ content }}</p>
  </div>
</template>

<script>
  export default {
    // props: ['title', 'content']
    // 不希望组件的根元素继承attribute,可以在组件中设置 inheritAttrs: false:
    inheritAttrs: false,
    props: {
      title: String,
      content: {
        type: String,
        required: true,
        default: "123",
      },
      counter: {
        type: Number,
      },
      info: {
        // 对象类型的prop,默认值必须写成函数形式
        type: Object,
        default() {
          return { name: "why" };
        },
      },
      messageInfo: {
        type: String,
      },
    },
  };
</script>

<style scoped>
</style>

接着在App.vue中调用该子组件,并传入id,class等属性。其余注册过程略过。

<show-message
      id="abc"
      class="why"
      title="哈哈哈"
      content="我是哈哈哈哈"
      message-info=""
    ></show-message>

可见,我们传递了id和class属性,并且在子组件中通过$attrs的方式进行了使用。

自定义组件使用v-model

v-model 可以在自定义组件上使用以实现双向绑定。例如对于在自定义的组件中,下面两种方式是等价的。

<hy-input v-model="message"></hy-input>
<hy-input :modelValue="message" @update:model-value="message = $event"></hy-input>

对于子组件HyInput.vue,可以通过多种方式实现双向绑定。但如果要在组件内也使用v-model的话,需要借助计算属性的get与set方法。get 方法需返回 modelValue prop,而 set 方法需触发相应的事件。

<template>
  <div>
    <!-- 1.默认绑定和事件处理 -->
    <!-- <button @click="btnClick">hyinput按钮</button>
    <h2>HyInput的message: {{modelValue}}</h2> -->

    <!-- 2.通过input -->
    <!-- <input :value="modelValue" @input="btnClick"> -->

    <!-- 4. 利用计算属性来实现,-->
    <input v-model="value">

  </div>
</template>

<script>
  export default {
    props: {
      modelValue: String
    },
    emits: ["update:modelValue"],
    computed: {
      value: {
        set(value) {
          this.$emit("update:modelValue", value);
        },
        get() {
          return this.modelValue;
        }
      }
    },
    methods: {
      btnClick(event) {
        this.$emit("update:modelValue", event.target.value);
      }
    }
  }
</script>

此外在组件上使用v-model时,v-model 在组件上都是默认使用 modelValue 作为 prop,并以 update:modelValue 作为对应的事件。我们可以通过给 v-model 指定一个参数来更改这些名字。

<hy-input v-model="message" v-model:title="title"></hy-input>

可以看到为v-model指定名字后,prop默认名称不再是modelValue,而是指定的名字。

<template>
  <div>
    <!-- v-model里面的名称,是和计算属性里的属性名对应的 -->
    <input v-model="value">
    <input v-model="why">
  </div>
</template>

<script>
  export default {
    props: {
      modelValue: String,
      title: String 
    },
    emits: ["update:modelValue", "update:title"],
    computed: {
      value: {
        set(value) {
          this.$emit("update:modelValue", value);
        },
        get() {
          return this.modelValue;
        }
      },
      why: {
        set(why) {
          this.$emit("update:title", why);
        },
        get() {
          return this.title;
        }
      }
    }
  }
</script>

<style scoped>

</style>