Vue 3 二 组件

作者: 吴摩西 | 来源:发表于2023-05-15 13:42 被阅读0次

    注册

    全局注册

    import { createApp } from 'vue'
    
    const app = createApp({})
    
    app.component(
      // 注册的名字
      'MyComponent',
      // 组件的实现
      {
        /* ... */
      }
    )
    

    局部注册

    import ComponentA from './ComponentA.js'
    
    export default {
      components: {
        ComponentA
      },
      setup() {
        // ...
      }
    }
    

    组件名格式

    • 主要是为了与原生 HTML 元素区分

    插槽

    声明具名插槽

    <div class="container">
      <header>
        <slot name="header"></slot>
      </header>
      <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>
    

    使用具名插槽

    <BaseLayout>
      <template v-slot:header>
        <!-- header 插槽的内容放这里 -->
      </template>
    </BaseLayout>
    

    v-slot 有对应的简写 #,因此 <template v-slot:header> 可以简写为 <template #header>

    image.png

    例如

    <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>
    

    或者

    <BaseLayout>
      <template #header>
        <h1>Here might be a page title</h1>
      </template>
    
      <!-- 隐式的默认插槽 -->
      <p>A paragraph for the main content.</p>
      <p>And another one.</p>
    
      <template #footer>
        <p>Here's some contact info</p>
      </template>
    </BaseLayout>
    

    作用域插槽

    <!-- <MyComponent> 的模板 -->
    <div>
      <slot :text="greetingMessage" :count="1"></slot>
    </div>
    
    <MyComponent v-slot="slotProps">
      {{ slotProps.text }} {{ slotProps.count }}
    </MyComponent>
    
    image.png

    为作用域插槽传递属性

    <MyComponent>
      <template #header="headerProps">
        {{ headerProps }}
      </template>
    
      <template #default="defaultProps">
        {{ defaultProps }}
      </template>
    
      <template #footer="footerProps">
        {{ footerProps }}
      </template>
    </MyComponent>
    

    依赖注入

    类似于 React 的 context

    <script setup>
    import { ref, provide } from 'vue'
    
    provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
    const count = ref(0)
    provide('key', count)
    </script>
    

    还可以有应用级 provide

    import { createApp } from 'vue'
    
    const app = createApp({})
    
    app.provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
    

    如果要使用组件提供的数据,需使用 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>
    

    可以用 readonly 包装状态

    <script setup>
    import { ref, provide, readonly } from 'vue'
    
    const count = ref(0)
    provide('read-only-count', readonly(count))
    </script>
    

    使用 Symbol

    为防止注入名冲突,可以使用 Symbol 做为注入名。

    // keys.js
    export const myInjectionKey = Symbol()
    
    // 在供给方组件中
    import { provide } from 'vue'
    import { myInjectionKey } from './keys.js'
    
    provide(myInjectionKey, { /*
      要提供的数据
    */ });
    
    // 注入方组件
    import { inject } from 'vue'
    import { myInjectionKey } from './keys.js'
    
    const injected = inject(myInjectionKey)
    

    相关文章

      网友评论

        本文标题:Vue 3 二 组件

        本文链接:https://www.haomeiwen.com/subject/qummsdtx.html