banner
banner
banner
NEWS LETTER

VUE3-组件知识

Scroll down
  • 组件名格式:PascalCase

组件注册

  • 全局注册
  • 局部注册

全局注册 — 只有多个页面都要用到才使用全局

1
2
3
import { createApp } from 'vue'
const app = create({})
app.component('注册的名字', 写好的组件) --可以被链式调用

局部注册

  • 使用该组件的父组件引入且在components:{}中注册

Props声明 — 组件间通信父传子

  • Prop名字的格式:camelCase

用法

  • 子组件:在props定义好属性,然后使用
  • 父组件:在组件中调用这个属性,传值

组件的props标注类型 — ts

  • defineComponent() — 启用类型推导
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import { defineComponent } from 'vue'

    export default defineComponent({
    props: {
    name: String,
    age: Number
    },
    mounted() {
    this.name // 类型: string | undefined
    }
    })
  • PropType — 多层级时启用工具类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import { defineComponent } from 'vue'
    import type { PropType } from 'vue'

    interface Book {
    title: string
    author: string
    year: number
    }

    export default defineComponent({
    props: {
    book: {
    type: Object as PropType<Book>,
    required: true
    },
    callback: Function as PropType<(id: number) => void >
    // validater 和 default ts版本低于4.7要使用箭头函数
    },
    mounted() {
    this.book.title // string
    this.callback?.('123')
    }
    })

静态prop:prop=”只能传字符串”

动态prop::prop=”可传多种类型”

使用一个对象绑定多个prop:v-bind=”对象数据”

单向数据流

单向数据流

  • 所有props都遵循着单向绑定原则
  • props因父组件的更新而变化
  • ❌ 子组件更改prop

prop校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
props:{
propA: {
type: 该属性的类型
default: 该属性的默认值
required: true 该属性必传
},
propB: [类型A, 类型B] // 多类型
propC: {
type: Object | Function
default(){}
},
propC: {
validator(value){} // 自定义类型校验函数
}
}

组件事件

触发与监听事件

  • 子组件事件

    • 子组件上的要监听事件要调用$emit方法,通过传入事件名称来抛出一个事件
    • 示例:<button @click="$emit('enlarge-text')">文本</button>
  • 父组件事件

    • 通过v-on 或 @来选择性监听子组件上的事件
    • 示例:<子组件名 @enlarge-text="表达式" />

事件参数

  • 子组件:$emit(事件名,事件参数)
  • 父组件: @事件名=”(事件参数) => 表达式” 或者 @事件名=”事件处理函数” 然后在methods写方法

显式声明触发事件+标注类型 emits + ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
emits:[] // 字符串数组语法
emits:{} //对象语法,支持校验
示例:
// addBook为事件名,
// bookName为事件内的一个属性且类型为字符串
emits:{
addBook(payload:{bookName: string}) {
return payload.bookNAme.length > 0
}
},
methods: {
onSubmit: {
this.$emit('addBook',{
bookName: '5655'
})
}
}

组件 v-model

  • 默认情况下,v-model 在组件上都是使用 modelValue 作为 prop,并以update:modelValue作为对应的事件

组件上使用v-model实现双向绑定

  • 方法一

    • 组件内的表单元素要有以下两行
    • :value=”modelValue”
    • @input=”$emit(‘update:modelValue’),$event.target.value”
  • 方法二

    • 使用具有 getter 和 setter 的 computed 属性
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      <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的参数 — 适用于组件有多个 v-model 绑定

  • 通过给 v-model 指定一个参数来更改modelValue这个名
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 名字从modelValue改为title
    父组件: <子组件名 v-model:title="" />
    子组件:
    <script>
    export default {
    props: ['title'],
    emits: ['update:title']
    }
    </script>

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

处理 v-model 修饰符

  • 自定义的修饰符 capitalize
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    父组件: <MyComponent v-model.capitalize="myText" />
    子组件:
    <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>

透传 Attributes:传递给一个组件,却没有被组件声明的属性或v-on

  • 例:<组件名 class=”btn”></组件名>,这个组件的根元素就多了一个btn的类

单根节点: 有自动 attribute 透传行为

  • 禁用Attributes继承:inheritAttrs: false
  • 使用v-bind=”$attrs” 可以让透传的attribute指定到目标元素

多根节点(一个组件多个子组件): 没有自动 attribute 透传行为

  • 必须使用v-bind=”$attrs” 让透传的attribute指定到目标元素

插槽slot —在组件中添加<slot />

  • 插槽的内容无法访问到子组件的状态
  • v-slot 简写 #
  • 具名插槽 — 适用一个组件多个插槽<slot name="" />(无名=默认插槽)
  • 父组件
    1
    2
    3
    4
    5
    6
    <BaseLayout>
    // 当一个组件同时接收默认插槽和具名插槽时,所有位于顶级的非 `<template> `节点都被隐式地视为默认插槽的内容
    // 指定插入那个插槽
    <template v-slot:插槽名></template>
    <template #插槽名></template>
    </BaseLayout>
  • 动态插槽名: <template #[插槽名]></template></span?
  • 作用域插槽 — 插槽内容想要同时使用父组件域内和子组件域内的数据
    • 传递prop: <slot name="可不写为默认插槽" message="hello" />
    • 接受插槽:
      • 默认插槽:<组件名 v-slot="slotProps">{{slotProps.xxx}}</组件名>
      • 具名插槽:<组件名 #插槽名="插槽名Props">{{}}</组件名>

依赖注入

Provide — 为组件后代提供数据

1
2
3
4
5
exeport default {
provide: {
message: 'test'
}
}

应用层 Provide — 为整个应用层提供依赖app页面

  • app.provide(‘注入名’,值)

Inject — 注入上层组件提供的数据

1
2
3
4
5
6
7
8
9
10
11
export default {
inject: ['message'],
created() {
console.log(this.message) // test
}
data() {
return {
fullMessage: this.meaaage // data的时候拿得到this.message
}
}
}

注入别名/默认值(不要求必须有提供者)

1
2
3
4
5
6
inject: {
别名: {
from: '原注入名', // 别名
default: 'default value' // 默认值,无提供者时
},
}

和响应式数据配合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { computed } from 'vue'

export default {
data() {
return {
message: 'hello!'
}
},
provide() {
return {
// 显式提供一个计算属性
message: computed(() => this.message)
}
}
}

异步组件

  • 仅在需要时再从服务器加载相关组件defineAsyncComponent
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    import { defineAsyncComponent } from 'vue'

    方法一:
    const AsyncComp1 = defineAsyncComponent(() => {
    return new Promise((resolve, reject) => {
    // ...从服务器获取组件
    resolve(/* 获取到的组件 */)
    })
    })

    方法二:
    const AsyncComp2 = defineAsyncComponent({
    loader: () => import('组件路径'), // 加载组件
    loadingComponent: LoadingComponent, // 加载异步组件时使用的组件
    delay: 200, // 展示加载组件前的延迟时间,默认为 200ms
    errorComponent: ErrorComponent, // 加载失败后展示的组件
    timeout: 3000
    })

    // ... 像使用其他一般组件一样使用 `AsyncComp`

    全局注册:
    app.component('MyComponent', defineAsyncComponent(() =>
    import('./components/MyComponent.vue')
    ))

    局部注册:
    components: {
    异步组件名: defineAsyncComponent(() =>
    import('./components/MyComponent.vue')
    )
    }

动态组件 — 适用于Tab界面

  • 当使用 来在多个组件间作切换时,被切换掉的组件会被卸载。

DOM 模板 — 在 DOM 中直接书写 Vue 模板

  • 区分大小写,以kebab-case (短横线连字符) 形式
  • 显示关闭标签<></>
  • 元素位置限制,<ul><ol><tr>等要放在特定元素中才会显示
  • 解决办法:
    • <table><tr is="vue:要放的组件名" /></table>
其他文章
cover
Git找不到null文件
  • 24/11/01
  • 16:45
  • 前端工程化工具
目录导航 置顶
  1. 1. 组件注册
    1. 1.1. 全局注册 — 只有多个页面都要用到才使用全局
    2. 1.2. 局部注册
  2. 2. Props声明 — 组件间通信父传子
    1. 2.1. 用法
    2. 2.2. 组件的props标注类型 — ts
    3. 2.3. 静态prop:prop=”只能传字符串”
    4. 2.4. 动态prop::prop=”可传多种类型”
    5. 2.5. 使用一个对象绑定多个prop:v-bind=”对象数据”
    6. 2.6. 单向数据流
    7. 2.7. prop校验
  3. 3. 组件事件
    1. 3.1. 触发与监听事件
    2. 3.2. 子组件事件
    3. 3.3. 父组件事件
    4. 3.4. 事件参数
    5. 3.5. 显式声明触发事件+标注类型 emits + ts
  4. 4. 组件 v-model
    1. 4.1. 组件上使用v-model实现双向绑定
    2. 4.2. 方法一
    3. 4.3. 方法二
    4. 4.4. v-model的参数 — 适用于组件有多个 v-model 绑定
    5. 4.5. 处理 v-model 修饰符
  5. 5. 透传 Attributes:传递给一个组件,却没有被组件声明的属性或v-on
    1. 5.1. 单根节点: 有自动 attribute 透传行为
    2. 5.2. 多根节点(一个组件多个子组件): 没有自动 attribute 透传行为
  6. 6. 插槽slot —在组件中添加<slot />
  7. 7. 依赖注入
    1. 7.1. Provide — 为组件后代提供数据
    2. 7.2. 应用层 Provide — 为整个应用层提供依赖app页面
    3. 7.3. Inject — 注入上层组件提供的数据
    4. 7.4. 注入别名/默认值(不要求必须有提供者)
    5. 7.5. 和响应式数据配合使用
  8. 8. 异步组件
  9. 9. 动态组件 — 适用于Tab界面
  10. 10. DOM 模板 — 在 DOM 中直接书写 Vue 模板
请输入关键词进行搜索