深入组件
组件注册
全局注册
js
import { createApp } from 'vue'
import App from './App.vue'
import MyComponent from './Component.vue'
const app = createApp(App)
app.component('ComponentA',MyComponent)
app.component('ComponentB',{...组件对象})
局部注册
js
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
}
//组合式
//setup(){}
}
vue
<script setup>
import ComponentA from './ComponentA.vue'
</script>
传参
js
export default {
props: ['foo'],
created() {
console.log(this.foo)
}
//组合式
//setup(props) { console.log(props.foo) }
// 规定类型
props: {
title: String,
likes: Number
//构造函数
}
}
vue
<script setup>
const props = defineProps(['foo'])
console.log(props.foo)
// 规定类型
defineProps({
title: String,
likes: Number,
propA:[String, Number],
propB:{
type: String, //类型
required: true, // 必要
default: 'ok' // 默认
}
// 详见文档
})
</script>
事件
js
export default {
methods: {
submit() {
this.$emit('someEvent',7)
}
}
}
//<button @click="$emit('someEvent',7)">click me</button>
//<MyComponent @some-event="n=>n+n" />
vue
<script setup>
// 因为不能使用this
const emit = defineEmits(['someEvent'])
function func(){
emit('someEvent',7)
}
// 关于v-model和组件的组合使用详见文档
</script>
透传
当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上,包括class、style 和 id. 可以通过$attrs
或import { useAttrs } from 'vue'+const attrs = useAttrs()
访问到
插槽
html
<slot>默认插槽的默认内容</slot>
<slot name="theName">具名插槽</slot>
<Component>
<template #default>
加到默认的插槽
</template>
<template #theName>
加到具名插槽
</template>
<template v-slot:[dynamicSlotName] #[dynamicSlotName]>
动态插槽名
</template>
</Component>
作用域插槽
vue
<div>
<slot text="hello" :count="1"></slot>
</div>
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
<MyComponent v-slot="{ text, count }">
{{ text }} {{ count }}
</MyComponent>
vue
<slot name="header" message="hello"></slot>
<MyComponent>
<template #header="headerProps">
{{ headerProps }} -> { message: 'hello' }
</template>
</MyComponent>
无渲染组件
在script中进行计算 但在template中就丢一个传参用的插槽 父组件拿到参数 然后写出具体视图 非常有意思的思路
依赖注入
js
export default {
// 选项
provide: {
message: 'hello!'
}
// 函数形式访问this
provide() {
return {
message: this.message
// 提供响应性
reactivity:computed(()=>this.message)
}
}
}
// 全局
app.provide('key','value')
js
export default {
inject: ['message'],
inject: {
newName: { // 别名
from: 'message', // 原名
default: '默认值' // 默认
}
}
}
vue
<script setup>
import { provide,inject } from 'vue'
provide('message','hello!')
const newName = inject('message','default')
// 响应式略
</script>
异步组件
js
import { defineAsyncComponent } from 'vue'
export default {
components: {
NewName: defineAsyncComponent(() =>
import('./components/AdminPageComponent.vue')
)
AsyncComp: defineAsyncComponent({
loader:()=>import('./Comp.vue'), // 加载项
loadingComponent: LoadingComponent, // 加载组件
delay: 200, // 展示加载组件前的延迟时间
errorComponent: ErrorComponent, // 加载失败组件
timeout: 3000 //超时
})
}
}
js
import { defineAsyncComponent } from 'vue'
const AdminPage = defineAsyncComponent(() =>
import('./components/AdminPageComponent.vue')
)
const AsyncComp = defineAsyncComponent({...})
// 全局
app.component('MyComponent', defineAsyncComponent(() =>
import('./components/MyComponent.vue')
))