Vue3中不同于Vue2的一些注意事项

253 阅读1分钟

透传Attributes功能

在vue2中不记得有这一点。换句话说,就是单个根节点的子组件,会自动使用父组件中给子组件定义的class、style等属性,也可以使用自定义的属性,在子组件中可以通过$attrsthis.$attrs来取值。

并且根据这一节的描述,Vue3是支持多个根节点的组件的。

增加了emits属性

通过该属性,显式地来表明组件触发的事件:

export default {
  emits: ['inFocus', 'submit']
}

并支持对触发事件的参数进行验证:

export default {
  emits: {
    submit(payload) {
      // 通过返回值为 `true` 还是为 `false` 来判断
      // 验证是否通过
    },
    // 校验 submit 事件 
    // 返回一个布尔值来表明事件是否合法。
    submitEmail: ({ email, password }) => { 
	    if (email && password) {
		    return true 
		} else { 
			console.warn('Invalid submit event payload!');
			return false 
		} 
	}
  }
}

v-model的书写方式变更

在Vue3中,需要按照如下方式来实现默认的v-model

<!-- CustomInput.vue -->
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue']
}
</script>

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

使用时:

<CustomInput v-model="searchText" />

也支持定义多个v-model的值,看示例代码:

<!-- UserName.vue -->
<script>
export default {
  props: {
    firstName: String,
    lastName: String
  },
  emits: ['update:firstName', 'update:lastName']
}
</script>

<template>
  <input
    type="text"
    :value="firstName"
    @input="$emit('update:firstName', $event.target.value)"
  />
  <input
    type="text"
    :value="lastName"
    @input="$emit('update:lastName', $event.target.value)"
  />
</template>

使用方式:

<UserName
  v-model:first-name="first"
  v-model:last-name="last"
/>

其中的抛出事件也可以改为通过计算属性来抛出,我个人喜欢这种方式,更灵活。

<!-- CustomInput.vue -->
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  computed: {
    value: {
      get() {
        return this.modelValue
      },
      set(value) {
        this.$emit('update:modelValue', value)
      }
    }
  }
}
</script>

<template>
  <input v-model="value" />
</template>

并且支持v-model的自定义修饰符。例如其中的capitalize修饰符:

<MyComponent v-model.capitalize="myText" />

具体实现方式如下,注意,若带有修饰符,则子组件中的this.modelModifiers.capitalizetrue

<script>
export default {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:modelValue'],
  methods: {
    emitValue(e) {
      let value = e.target.value
      if (this.modelModifiers.capitalize) {
        // 
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      this.$emit('update:modelValue', value)
    }
  }
}
</script>

<template>
  <input type="text" :value="modelValue" @input="emitValue" />
</template>

依赖注入

根据文档描述,父/祖父等组件使用provide来提供数据,子组件使用inject来使用,并且注入会在组件自身状态之前被解析。 并且在vue3.3之前,需设置app.config.unwrapInjectedRef = true以及computed函数来使注入具有响应式。

关于组合式API

这里想说一句,Vue3也支持选项式API,换句话说,Vue2的代码一般情况下是可以在Vue3中正常运行的。