Vue3 深入组件

 Vue 的组件系统允许我们使用小型、独立和可复用的组件构件大型应用。Vue3 引入了<script setup>语法糖,使得组件的options(如data,methods等)会自动从setup函数的返回中导出,无须通过return暴露它们,提高了开发效率。

1 组件进阶

1.1 Props

1)使用defineProps()宏来声明Props。

2)可以声明对props 的校验(required或自定义校验器)。

3)type选项用于指定类型,可以是原生构造函数,例如String、Number、Boolean等,也可以是自定义的类或构造函数。

<script setup lang="ts">
import {defineProps} from "vue";

const { name } = defineProps({
  name: {
    type: String,
    required: true,
    validator(value:String): boolean {
      return 'hello' === value
    }
  }
})
</script>

1.2 事件

1)使用defineEmits()宏来声明要触发的事件。

2)事件可以使用对象形式来描述,可以为事件添加一个校验函数,接受的参数是抛出事件时传入的内容,返回一个布尔值来表名事件是否合法。

<script setup lang="ts">
  import {defineEmits} from "vue";

  const emits = defineEmits({
    customTrigger(name: string,num: number) {
      return name.length > 0 && num > 1
    },
    customTrigger2(args: {name: string, num: number}) {
      return args.name.length > 0 && args.num > 1
    }
  })
</script>

<template>
<button @click="emits('customTrigger','hmf',2)">触发事件1</button>
  <button @click="emits('customTrigger2',{name: '2', num: 2})">触发事件2</button>
</template>

1.3 组件v-model

v-model可以在组件上使用以实现双向绑定。从Vue3.4开始,推荐实现方式是使用defineModel()宏。传入选项用于指定默认值、是否必须等。其底层机制为:

1)在子组件,声明一个名为modelValue的prop。

2)当需要在组件修改该值时,触发名为update:modelValue的事件。

3)父组件中处理update:modelValue的事件,来更新ref的值。

<script setup lang="ts">
import {defineEmits, defineModel, defineProps} from "vue";

const name = defineModel({default: 'hello'})
const emits = defineEmits(['customModelValue:update'])
const props = defineProps(["customModelValue"])
</script>

<template>
  <div><input v-model="name"/></div>
  <div><input :value="props.customModelValue" @input="emits('customModelValue:update',$event.target.value)"/></div>
</template>

4) 可以声明多个v-model绑定。

5) 可以使用修饰符,在子组件定义v-model时,传入选项用于设置set函数,来设置model的最终值。

<script setup lang="ts">
import {defineModel} from "vue";

const [name, nameModifiers] = defineModel('name',{
  set(val:string) {
     if(nameModifiers.trim) {
       val = val.trim()
     }
     return val
  }
})
</script>

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

1.4 透传Attributes

“透传attributes”指传递给一个组件,却没有被该组件声明为props 或 emits的attribute或者v-on事件监听器。

1)当一个组件以单个元素为根作渲染时,透传的attribute会自动添加到根元素上。

2)当以多个元素为根元素时,可以使用$attrs 为元素指定要继承的属性。否则将会警告。

3)如果不想要一个组件自动继承attribute,可以在组件选项中设置 inheritAttrs: false。

4)在<script setup>中使用useAttrs()来访问一个组件所有透传的attributes.

<a-attributes-view @click="clickHandle" style="color: red;font-weight: bold"/>

<script setup lang="ts">
import {defineOptions, useAttrs} from "vue";

 defineOptions({
   inheritAttrs: false
 })
 const attrs = useAttrs();
 function clickHandle() {
   console.log("children click",attrs)
 }
</script>

<template>
<div @click="clickHandle">h1</div>
<div v-bind="$attrs">h2</div>
</template>

1.5 插槽Slots

1)<slot>元素的name属性用于给各个插槽分配唯一的ID,以确定每一处要渲染的内容。

2)在子组件中,使用$slots来访问插槽的内容。

3)向对组件传递props那样,向<slot>元素传递attributes来向插槽内容传递数据。

<template>
<div style="border: solid 1px red">
  <slot :info="'hello js'">默认</slot>
</div>
<div style="margin-top: 20px; border: solid 1px blue" v-if="$slots.default">
  <slot name="footer" :count="1234"/>
</div>
</template>

<template>
  <a-slot-view>
    <template #default="{ info }">
      <div>hello default</div>
      <div>还是 default1 {{info}}</div>
    </template>
    <template #footer="{count}">
      <div>footer {{ count }}</div>
    </template>
  </a-slot-view>
</template>

1.6 依赖注入

1) 要为组件后代提供数据,需要使用到provide()函数。可提供响应式值,这样在后代组件修改值,父组件的值也会发送改变。

2)要注入上层组件提供的数据,需要使用inject()函数。可以指定默认值。

3)如果要在后代中修改注入的值,不建议在后代中直接修改,父组件可以在注入数据时,提供一个修改数据的方法给后代。

<script setup lang="ts">
import {provide, ref} from "vue";
import AInjectView from "@/article/components/AInjectView.vue";

const count = ref(0)
const num = ref(0)

function addNum() {
  num.value++
}

provide("count",count)
provide("num",{ num,addNum })
</script>

<template>
<div>count: {{ count }}</div>
<div>num: {{ num }}</div>
<a-inject-view />
</template>

<script setup lang="ts">
import {inject} from "vue";

const count = inject("count",-1)
const { num, addNum} = inject("num")
</script>

<template>
<button @click="count++">修改count{{ count }}</button>
<div @click="addNum">修改num {{ num }}</div>
</template>

1.7 异步组件

在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。defineAsyncComponent可以实现此功能。

1)改函数支持传入一个选项,用于指定加载函数、加载异步组件时使用的组件、失败后展示的组件、超时时间等。

const SubjectView = defineAsyncComponent({
    loader: () => new Promise((resolve, reject) => {
       setTimeout(() => {
          resolve(import('./components/ASubjectView.vue'))
       },3000)
    }),
    loadingComponent: ALoadingView,
    errorComponent: AErrorView,
    timeout: 2000
  })

相关推荐

  1. Vue3 深入组件

    2024-07-22 21:44:01       17 阅读
  2. vue3-深入组件-事件

    2024-07-22 21:44:01       54 阅读
  3. vue3深入组件:props

    2024-07-22 21:44:01       31 阅读
  4. 深入理解 Vue 3 组件通信

    2024-07-22 21:44:01       22 阅读
  5. vue3组件注册

    2024-07-22 21:44:01       51 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 21:44:01       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 21:44:01       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 21:44:01       45 阅读
  4. Python语言-面向对象

    2024-07-22 21:44:01       55 阅读

热门阅读

  1. Leetcode热题100 Day4

    2024-07-22 21:44:01       16 阅读
  2. Python每日学习

    2024-07-22 21:44:01       15 阅读
  3. web前端 React 框架面试200题(七)

    2024-07-22 21:44:01       15 阅读
  4. 鸡兔同笼求解器

    2024-07-22 21:44:01       17 阅读
  5. 深度学习中的损失函数和网络优化方法

    2024-07-22 21:44:01       13 阅读
  6. VUE复习

    VUE复习

    2024-07-22 21:44:01      10 阅读
  7. Unity扩展 UI线段绘制组件——UI上的LineRenderer

    2024-07-22 21:44:01       14 阅读
  8. IDM破解

    IDM破解

    2024-07-22 21:44:01      11 阅读
  9. 通过Python面向对象编程探索克苏鲁神话

    2024-07-22 21:44:01       12 阅读