目录
1.props
//父给子组件Categorys 传了一个categoryList属性
<Categorys :categoryList="categoryList"></Categorys>
子组件使用:
ts写法:
//ts写法
import type { categoryPanel } from "@/types/index"
defineProps<{
categoryList: categoryPanel[]
}>()
@/types/index文件:
export interface categoryPanel {
id: string,
name: string,
icon: string,
}
普通写法:
defineProps({
categoryList:Object
)
2.v-model
父组件:
//一个响应式通信
<Child v-model="money"></Child>
//多个响应式通信
<Child1 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></Child1>
Child:
let props = defineProps(["modelValue"]);
let $emit = defineEmits(['update:modelValue']);
//子组件内部按钮的点击回调
const handler = ()=>{
//触发自定义事件
$emit('update:modelValue',props.modelValue+1000);
}
Child1:
let props = defineProps(["pageNo", "pageSize"]);
let $emit = defineEmits(["update:pageNo", "update:pageSize"]);
//第一个按钮的事件回调
const handler = () => {
$emit("update:pageNo", props.pageNo + 3);
};
它其实是个语法糖,其底层原理为:
父组件:
let money = ref(10000);
//自定义事件的回调
const handler = (num) => {
//将来接受子组件传递过来的数据
money.value = num;
};
//给子组件child传入modelValue属性 和 @update:modelValue方法
<Child :modelValue="money" @update:modelValue="handler"></Child>
子组件:
<h3>钱数:{{ modelValue }}</h3>
//接受props
let props = defineProps(["modelValue"]);
let $emit = defineEmits(['update:modelValue']);
//子组件内部按钮的点击回调
const handler = ()=>{
//触发自定义事件
$emit('update:modelValue',props.modelValue+1000);
}
这样就实现了父子响应式通信;
3.自定义事件
自定义事件和v-model差不多
父组件:
let money = ref(0);
//自定义事件的回调
const handler = (num) => {
//将来接受子组件传递过来的数据
money.value = num;
};
//给子组件child传入modelValue属性 和 @update:modelValue方法
<Child @hander="handler"></Child>
子组件:
//接受props
let $emit = defineEmits(['hander']);
//子组件内部按钮的点击回调
const handler = ()=>{
//触发自定义事件
$emit('hander',1000);
}
这样子组件通过调用 handler 方法,改变了父组件的 money.
4. 全局事件总线 $bus
vue3没有全局事件总线 $bus,但可以通过引入mitt插件实现全局事件总线。
$bus文件:
// 引入全局事件总线
import mitt from 'mitt'
const $bus = mitt()
export default $bus
兄弟组件1:
//引入$bus
import $bus from '@/bus/index'
//创建一个taggleImg事件,并传入参数index
let taggleImg = (index) => {
$bus.emit('taggleImg', index)
}
兄弟组件2:
//引入$bus
import $bus from '@/bus/index'
let imgIndex = ref(0)
$bus.on('taggleImg',(index)=>{
imgIndex.value = index
})
当兄弟组件1调用taggleImg方法,就会改变兄弟组件2的imgIndex值
5.ref和$parent
ref:父组件通过拿到子组件实例,就可以拿到子组件暴露的属性,方法
ref使用方法:
父组件:
//给子组件绑定ref
<Child ref="son"></Son>
//变量名必须为son
const son= ref()
//父组件内部按钮点击回调
const handler = ()=>{
son.value.money-=10;
}
子组件:
let money = ref(666);
//组件内部数据对外关闭的,别人不能访问
//如果想让外部访问需要通过defineExpose方法对外暴露
defineExpose({
money,
})
这样父组件通过ref调用子组件实例暴露的money属性 。
$parent:和自定义事件、props类似,实现子组件获取父组件属性、方法,不过它需要父组件暴露对应的属性、方法
$parent使用方法:
父组件:
let money = ref(100)
defineExpose({
money
})
子组件:
//直接调用$parent,拿到父组件暴露的属性、方法
const handler = ($parent)=>{
$parent.money-=10000;
}
6.provide-inject 订阅
vue3提供provide(提供)与inject(注入),可以实现隔辈组件传递数据(数据为响应式数据,父子相互响应)
祖先:
import { ref, provide } from "vue";
let car = ref("法拉利");
//两个参数:第一个参数就是提供的数据key
//第二个参数:祖先组件提供数据
provide("TOKEN", car);
后辈:
import {inject} from 'vue';
let car = inject('TOKEN');
const updateCar = ()=>{
//可以修改祖先的值
car.value = '自行车';
}
7.其他
useAttrs方法,它和defineEmits几乎一样,但defineEmits的优先级更高
//父组件:
<Child @handler = "handler ">
const handler = ()=>{
alert(12306);
}
//子组件
import {useAttrs} from 'vue';
//此方法执行会返回一个对象
let $attrs = useAttrs();
用一些插件(pinia、vuex...)