vue3组件-组合式语法笔记

93 阅读2分钟

注册

一个 Vue 组件在使用前需要先被“注册”。

  • 全局注册(支持链式调用)
import MyComponent from './App.vue' 

app.component('MyComponent', MyComponent)
  • 局部注册
<script setup> 
    import ComponentA from './ComponentA.vue' 
</script> 

<template> 
    <ComponentA /> 
</template>

  • 组件名格式
  1. 注册格式推荐使用PascalCase
  2. 模板中可以通过<MyComponent><my-component> 引用。

props

子组件需要显式声明它所接受的 props

//子组件
<script setup> 
    const props = defineProps(['foo']) 
</script>

<template>
    <div> {{foo}}</div>
</template>

props的声明方式除了字符串数组,还有对象的形式

defineProps({
    title:String,
    count:Number
})

props数据流遵循单向绑定原则,然而当对象或数组作为props被传入时,数据值修改会生效,但是会有很大的性能损耗。

事件

组件模板中直接使用$emit方法

<!--子组件-->
 <button @click="$emit('someEvent')">click me</button>
 
 
 <!--父组件-->
 <MyComponent @some-event="callback" />

声明触发组件

<!--子组件-->
<script setup> 
    const emit = defineEmits(['inFocus', 'submit']) 
    function buttonClick() { 
        emit('submit') 
    } 
</script>

<button @click="$emit('someEvent')">click me</button>
 
 
 <!--父组件-->
 <MyComponent @some-event="callback" />

透传Attributes

“透传 attribute”指的是传递给一个组件,却没有被该组件声明为propsemits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 classstyle 和 id

当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上。多根节点需要显示绑定。

<!--父组件-->
<ComponentA id="aaaa" />


<!--子组件-->
<header>...</header> 
<main v-bind="$attrs">...</main> 
<footer>...</footer>

插槽

<!--父组件-->
<FancyButton> 
    Click me! <!-- 插槽内容 --> 
</FancyButton>


<!--子组件-->
<button class="fancy-btn"> 
    <slot></slot> <!-- 插槽出口 --> 
</button>


<!--渲染结果-->
<button class="fancy-btn">
    Click me!
</button>

插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的。

  • 插槽可以制定默认内容
<button>
    <slot>
        default message
    </slot>
</butto>
  • 具名插槽,适用于一个组件内包含多个插槽出口
<!--子组件-BaseLayout->
<div class="container"> 
    <header> 
        <slot name="header"></slot> 
    </header> 
    <main> 
        <slot></slot> 
    </main> 
    <footer> 
        <slot name="footer"></slot> 
    </footer> 
</div>


<!--父组件-->
<BaseLayout> 
    <template #header> 
        <h1>Here might be a page title</h1> 
    </template> 
    <template #default> 
        <p>A paragraph for the main content.</p> 
        <p>And another one.</p> 
    </template> 
    <template #footer> 
        <p>Here's some contact info</p> 
    </template> 
</BaseLayout>
  • 插槽之间的传参
<!--子组件传参-->
<div> 
    <slot :text="greetingMessage"></slot> 
</div>

当需要接收插槽 props 时,默认插槽和具名插槽的使用方式有一些小区别

<!--默认插槽-->
<MyComponent v-slot="slotProps"> 
    {{ slotProps.text }} 
</MyComponent>

<!--v-slot可以使用解构-->
<MyComponent v-slot="{ text }">
    {{ text }} 
</MyComponent>
<!--具名插槽-->
<MyComponent> 
    <template #header="headerProps"> 
        {{ headerProps }} 
    </template> 
</MyComponent>

依赖注入

provideinject的出现就是为了解决prop 逐级透传的问题。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

  • Provide (提供):为后代提供数据
<script setup> 
    import { provide } from 'vue' 
    provide('message',  'hello!') 
</script>

第一个参数被称为注入名,第二个参数是提供的,必须提供,否则会报错。

一个组件可以多次调用 provide(),使用不同的注入名,注入不同的依赖值。

  • inject (注入) : 注入上层组件提供的数据
<script setup> 
    import { inject } from 'vue' 
    const message = inject('message') 
</script>

当提供 / 注入响应式的数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中。

  • 修改响应式状态
<!--供给方-->
<script setup> 
    import { provide, ref } from 'vue' 
    
    const location = ref('North Pole') 
    
    function updateLocation() { 
        location.value = 'South Pole' 
   } 
   provide('location', { 
       location, 
       updateLocation 
   }) 
</script>
<!--注入方-->
<script setup> 
    import { inject } from 'vue' 
    const { location, updateLocation } = inject('location') </script> 
    
<template> 
    <button @click="updateLocation">
        {{ location }}
    </button> 
</template>