这是我参与「第五届青训营 」笔记创作活动的第5天
目录概览
该文章仅限于在项目开始之前对Vue3知识体系的重点概览(帮助回忆)
- 组件命名
- 属性定义
- 事件定义
- 透传特性
- 插槽
- 提供provide/注入inject
- Composables
- 组件通信
- 相关API变化
介绍
一、组件命名
官方建议使用大驼峰命名法来注册组件,原因如下:
- 驼峰命名是合法的js标识符,导入、注册组件会更简单,IEDE会自动完成
- 在setup语法糖中不用注册组件,直接导入使用即可,Vue组件比原生HTML元素更醒目
举个栗子🌰
<template>
<Menu />
</template>
<script setup lang='ts'>
import Menu from "@/components/layout/menu/index.vue";
</script>
二、属性定义
最好采用具体的定义方式:
<script setup lang='ts'>
const props = defineProps({
name:{
type:string,
require:true
}
})
console.log(props.name)
</script>
三、事件定义
自定义事件的名称会被自动做转换,通常使用驼峰做事件名,监听时需要转换为肉串方式a-b
<!-- MyComponet组件-->
<button @click="$emit('someEvent')">点击我触发事件</button>
<!-- 引入MyComponet组件-->
<MyComponet @some-event="callback">
script setup中定义
<script setup lang='ts'>
const emit = defimeEmits(['someEvent'])
emit('someEvent')
</script>
四、透传特性
在vue3中,那些没有在组件props和emits中声明的特性或事件监听器称为透传特性,以前叫非属性特性,比如class,style和id特性。当组件只有单根时,透传特性自动被添加到根元素上作为其特性
例如:
<button class="large">点击</button>
若不想自动继承属性,可以使用inheritAttrs:false禁止
访问透传特性:
<script setup lang='ts'>
import {useAttrs} from 'vue'
const attrs = useAttrs()
</script>
五、插槽
如果要传递模板内容给子组件,我们使用插槽。
特别注意的是,Vue3中插槽的变化是移除
scopeSlots,只需要访问slots对象,且包括default插槽都是函数形式
<script setup lang='ts'>
import {useSlots} from 'vue'
const slots = useSlots()
const defaultContent = slots.default()
</script>
六、提供/注入
隔代传参时,使用provide/inject
<script setup lang='ts'>
import {provide} from 'vue'
//祖代提供数据
provide('message','hello') //key,value
</script>
<script setup lang='ts'>
import {inject} from 'vue'
//后代注入数据
inject('message','hello') //key,value
</script>
七、Composables
利用Composition API封装的可重用状态逻辑称为composables
约定composables函数命名时可加上use前缀
例如:
八、组件通信
- props:父子通信,传入一个属性
{
props:{msg:string}
}
在Vue3.2中,还出了script setup新写法
const props = defineProps({
model:{
type:Object,
required:true
}
})
- $emit
this.$emit('add',good)
vue3.2中出了script setup新语法:
//不推荐使用
const emit = defineEmits(['event'])
//推荐使用
const emit = defineEmits<{
(e:"updateValue",value:string):void;
(e:"validate"):void;
}>()
emit("updateValue",inp.value)
on,once,$off被移除了!这三个方法被认为不应该由vue提供,因此被移除了,可以使用其他库实现等效功能
import mitt from 'mitt'
const emitter = mitt()
//发送事件
emitter.emit('foo','fooooo')
//监听事件
emitter.on('foo',msg=>console.log(msg))
- event bus
在vue2中我们常常用一个Vue实例来做事件总线,现在不行了,所以可以使用上面的mitt方案来代替
- vuex/pinia
在vue3中状态管理一般都用pinia,因为它对ts的支持更好
具体可参照官网简介 | Pinia (vuejs.org)
- parent/root:兄弟组件之间通信可以通过共同祖辈搭桥
//brother1
this.$parent.$on('foo',handle)
//brother2
this.$parents.$emit('foo')
$children
vue3中移除了该选项,官方建议我们访问子组件时使用$refs
- $refs:获取指定元素或者组件
//parent
<HelloWorld ref="hm">
mounted() {
this.$refs.ha.xx = 'xxx'
}
- provide/inject:祖孙辈之间进行通信 *\
import {provid,inject} from vue
//提供数据
provide(key,value)
//注入数据
inject(key)
- attrs:
//child:并未在props中声明foo
<p>{{$attrs.foo}}</p>
//parent
<Hello foo='foo' />
通过v-bind="$attrs"透传到内部组件--在创建高级别组件时非常有用
//给Grandson隔代传值,parent.vue
<Child2 msg="lalal" @some-event="onSomeEvent" />
//给child做展开
<Grandson v-bind="$attrs">
//Grandson使用
<div @click="$emit("some-event",'msg from grandson')>
{{msg}}
</div>
- 插槽:插槽语法是Vue实现的内容分发API,用于复合组件开发,该技术在通用组件库开发中有大量应用
- 匿名插槽
slot称为匿名插槽,作为占位符存在,将来被替换为传入内容
//comp1
<div>
<slot></slot>
</div>
//parent
<comp1>hello</comp1>
- 具名插槽
slot加上name就称为具名插槽,可以将内容分发到子组件指定位置
//comp2
<div>
<slot></slot>
<slot name="content"></slot>
</div>
//parent
<comp2>
<!-- 默认插槽用default作为参数-->
<template v-slot:default>具名插槽</template>
<!-- 具名插槽用插槽名作为参数-->
<template v-slot:content>内容...</template>
</comp2>
- 作用域插槽
分发内容要用到子组件中的数据
//comp3
<div>
<slot :foo="foo"></slot>
</div>
//parent
<comp3>
<!-- 把v-slot的值指定为作用域上下文对象-->
<template v-slot:default="slotProps">
来自子组件的数据{{slotProps.foo}}
</template>
</comp3>
Vue3中组件相关API变化总结
- global-api改为实例方法
//vue2中
Vue.component()
//vue3中
const app = creatApp({})
.componet('comp',{template:'<div>i am comp</div>'})
.mount('#app')
- 移除
.sync,统一为v-model
<div id="app">
<comp v-model="data"></comp>
<!--v-model展开后-->
<comp :data="data" @update:data="onxxx"></comp>
</div>
app.componet('comp',{
template:'
<div @click="$emit('update:modelValue','new value')">
{{modeleValue}}
</div>
',
props:['modelValue']
}
- 渲染函数api修改
不再传入h函数,需要我们手动导入:拍平的props结构,scopedSlots删掉了
- 组件emits选项
该选项用于标注自定义事件及其校验等
createApp({}).componet("comp",{
template:'...',
//emits标明组件对外事件
emits:['buy','..']
//还能对事件进行校验
emits:{
'update:modeleValue':null, //不做校验
buy(p){
if(p==='nothing'){
console.warn('参数非法')
return false
}else {
return true
}
}
}
})