1.props(父传子)
需要使用defineProps方法接受父组件传递来的数据,defineProps是v3提供的方法,不需要要引入,直接使用。
父组件:
<template>
<div class="father">
<CHILD01 msg="Vite Vue" />
</div>
</template>
<script setup lang="ts">
import CHILD01 from './components/CHILD01.vue'
</script>
子组件:
//ts
<template>
<h1>{{props.msg}}</h1>
</template>
<script setup lang="ts">
interface IPROPS {
msg?:string
}
const props:IPROPS = defineProps(['msg'])
</script>
//js
<template>
<h1>{{props.msg}}</h1>//或者直接msg 不用写props
</template>
<script setup>
const props = defineProps(['msg'])
</script>
2.自定义事件
1.子组件
需要使用defineEmits方法触发自定义事件,defineProps是v3提供的方法,不需要要引入,直接使用。
<template>
<button @click="handler">点我触发自定义事件</button>
</template>
<script setup lang="ts">
const $emit =defineEmits(['xxx'])
const handler=()=>{
$emit('xxx','传来的数据1','传来的数据2')
</script>
父组件:
<template>
<div class="father">
<CHILD01 @xxx="handle" />
</div>
</template>
<script setup lang="ts">
import CHILD01 from './components/CHILD01.vue'
const handle=(params1:string,params2:string)=>{
console.log(params1,params2)
}
</script>
<style scoped>
.father {
width: 1000px;
height: 400px;
background-color: red;
margin: 0 auto;
}
</style>
3.全局数据总线(任意组件)
需要安装插件mitt:mitt - npm
src\bus.js
//引入mitt插件:mitt一个方法,方法执行会返回bus对象
import mitt from 'mitt';
const $bus = mitt();
export default $bus;
组件1:
<template>
<div class="child01">
<h4>子组件01</h4>
<button @click="handler">点我给child02传值</button>
</div>
</template>
<script setup lang="ts">
import $bus from "../bus";
const handler = () => {
$bus.emit("car", { car: "奔驰" });
};
</script>
<style scoped>
.child01 {
width: 400px;
height: 100px;
background-color: skyblue;
margin: 0 auto;
}
</style>
组件2:
<template>
<div class="child02">
<h4>子组件02</h4>
<span>{{ states.car }}</span>
</div>
</template>
<script setup lang="ts">
import $bus from "../bus"; //组合式API函数
import { onMounted, reactive } from "vue";
const states=reactive({
car:''
})
//组件挂载完毕的时候,当前组件绑定一个事件,接受将来兄弟组件传递的数据
onMounted(
() => {
$bus.on("car", (car: string) => {
states.car=car
});
}
//第一个参数:即为事件类型第二个参数:即为事件回调
);
</script>
<style scoped>
.child02 {
width: 400px;
height: 100px;
background-color: purple;
margin: 0 auto;
}
/* .read-the-docs {
color: #888;
} */
</style>
4.v-model(父子)
1.绑定一个v-model
父组件
<template>
<div class="father">
<h1>v-model:{{ money }}{{ pageNo }}--{{ pageSize}}</h1>
<input type="text" v-model="info">
<!-- <CHILD01 :modelValue="money" @update:modelValue="handler"></CHILD01> -->
<!--
v-model组件身上使用
第一:相当有给子组件传递props[ modelValue] = 10000
第二:相当于给子组件绑定自定义事件update : modelValue-->
<CHILD01 v-model="money"></CHILD01>
<!-- 绑定多个v-model -->
<CHILD02 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></CHILD02>>
</div>
</template>
<script setup lang="ts">
import CHILD01 from './components/CHILD01.vue'
import CHILD02 from './components/CHILD02.vue'
import {ref} from 'vue'
//v-model指令:收集表单数据,数据双向绑定
// v-model也可以实现组件之间的通信,实现父子组件数据同步的业务
//父亲给子组件数据props
//子组件给父组件数据·自定义事件//引入子组件
let info = ref('');
//父组件的数据钱数
let money = ref (10000);
// const handler =(num:number) => {
// //接受子组件数值
// money.value=num
// }
let pageNo=ref(0)
let pageSize=ref(3)
</script>
<style scoped>
.father {
width: 1000px;
height: 400px;
background-color: red;
margin: 0 auto;
}
</style>
子组件01
<template>
<div class="child01">
<h4>子组件01</h4>
<div>钱:{{ modelValue }}</div>
<button @click="handle">父子数据同步</button>
</div>
</template>
<script setup lang="ts">
interface IPROPS {
modelValue:string
}
let props:IPROPS = defineProps(['modelValue'])
let $emit = defineEmits( [ 'update:modelValue' ]);
const handle =() => {
// console.log(props)
$emit('update:modelValue',props.modelValue + 1000);
}
</script>
<style scoped>
.child01 {
width: 400px;
height: 100px;
background-color: skyblue;
/* margin: 0 auto; */
}
</style>
2.绑定一个v-model
子组件02
<template>
<div class="child02">
<h4>子组件02绑定多个v-model</h4>
<button @click="$emit('update:pageNo',pageNo+1)">pageNo{{ pageNo }}</button>
<button @click="$emit('update:pageSize',pageSize+1)">pageSize{{pageSize }}</button>
<span> </span>
</div>
</template>
<script setup lang="ts">
defineProps(["pageNo", "pageSize"]);
let $emit = defineEmits([ 'update:pageNo' , 'update:pageSize'])
</script>
<style scoped>
.child02 {
width: 400px;
height: 100px;
background-color: purple;
margin: 0 auto;
}
/* .read-the-docs {
color: #888;
} */
</style>
5.useAttrs
父组件
<template>
<div class="father">
<H1>父组件</H1>
<!-- <el-button type="primary" size="small" :icon="Edit">Primary</el-button> -->
<CHILD01
type="primary"
size="small"
:icon="Edit"
title="编辑按钮"
@click="handle"
></CHILD01>
</div>
</template>
<script setup lang="ts">
import CHILD01 from "./components/CHILD01.vue";
import { Edit } from "@element-plus/icons-vue";
const handle = () => {};
</script>
<style scoped>
.father {
width: 1000px;
height: 400px;
background-color: red;
margin: 0 auto;
}
</style>
子组件
<template>
<div class="child01">
<h4>子组件01</h4>
<el-button :="$attrs">Primary</el-button>
</div>
</template>
<script setup lang="ts">
//接受父组件传递过来数据
// defineProps(["type ", "size", "icon"]);
//引入useAttrs方法:获取组件标签身上属性与事件 包括函数和自定义事件
import { useAttrs } from "vue";
//此方法执行会返回一个对象
let $attrs = useAttrs();
//万一用props接受title
let props = defineProps(["title"]);
// props 与useAttrs方法都可以获取父组件传递过来的属性与属性值
//但是props接受了,usekttrs方法就获取不到了
console.log($attrs);
</script>
<style scoped>
.child01 {
width: 400px;
height: 100px;
background-color: skyblue;
/* margin: 0 auto; */
}
</style>
会发现没有title了
6.ref与$parent
父组件
<template>
<div class="father">
<h1>父组件:{{ money }}</h1>
<button @click="handle">找组件1借100</button>
<hr />
<CHILD01 ref="son"></CHILD01>
<hr />
<CHILD02 ref="dau"></CHILD02>
</div>
</template>
<script setup lang="ts">
import CHILD01 from "./components/CHILD01.vue";
import CHILD02 from "./components/CHILD02.vue";
// ref:可以获取真实的DOM节点,可以获取到子组件实例vC
// $parent:可以在子组件内部获取到父组件的实例
import { ref } from "vue";
//父组件钱数
let money = ref(100000000);
let son = ref();
let dau = ref();
const handle = () => {
money.value += 100;
son.value.money += 100;//获取子组件的值
son.value.ddd();
};
//对外暴露
defineExpose({ money });
</script>
<style scoped>
.father {
width: 1000px;
height: 400px;
background-color: red;
margin: 0 auto;
}
</style>
组件1
<template>
<div class="child01">
<h4>子组件01</h4>
<hr />
<span>
{{ money }}
</span>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
let money = ref(666);
const ddd = () => {
console.log("122");
};
//对外暴露
defineExpose({ money, ddd });//暴露数据给父组件
//父组件钱数
</script>
<style scoped>
.child01 {
width: 400px;
height: 100px;
background-color: skyblue;
/* margin: 0 auto; */
}
</style>
组件2
<template>
<div class="child02">
<h4>子组件02 {{ money }}</h4>
<hr />
<button @click="handle($parent)">点我父组件给我传100</button>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue"; //儿子钱数
let money = ref(666);
const handle = ($parent) => {
money.value += 100;
$parent.money -= 100;//获取父组件的数据,子给父传值
};
</script>
<style scoped>
.child02 {
width: 400px;
height: 100px;
background-color: purple;
/* margin: 0 auto; */
}
/* .read-the-docs {
color: #888;
} */
</style>
7.provide与inject
父组件
<template>
<div class="father">
<h1>父组件{{ car }}</h1>
<hr />
<button @click="handle">点我改车</button>
<CHILD01 ref="son"></CHILD01>
<!-- <CHILD02 ref="dau"></CHILD02> -->
</div>
</template>
<script setup lang="ts">
import CHILD01 from "./components/CHILD01.vue";
// import CHILD02 from "./components/CHILD02.vue";
//vue3提供provide(提供)与inject(注入),可以实现隔辈组件传递数据
import { ref, provide } from "vue";
let car = ref("法拉利");
//祖先组件给后代组件提供数据
//两个参数:第一个参数就是提供的数据key//第二个参数:祖先组件提供数据
provide("TOKEN", car);
const handle = () => {
car.value = "bench";
};
</script>
<style scoped>
.father {
width: 1000px;
height: 400px;
background-color: red;
margin: 0 auto;
}
</style>
子组件
<template>
<div class="child01">
<h4>子组件01{{ car }}</h4>
<CHILD02></CHILD02>
</div>
</template>
<script setup lang="ts">
import CHILD02 from "../components/CHILD02.vue";
import { inject } from "vue";
let car = inject("TOKEN");
console.log(car);
</script>
<style scoped>
.child01 {
width: 400px;
height: 100px;
background-color: skyblue;
/* margin: 0 auto; */
}
</style>
孙子组件
<template>
<div class="child02">
<h4>子组件02:{{ car }}</h4>
<button @click="handle">点我改车</button>
</div>
</template>
<script setup lang="ts">
type car = object;
import { inject } from "vue";
let car = inject("TOKEN");
const handle = () => {
car.value = "zixingche";
};
</script>
<style scoped>
.child02 {
width: 400px;
height: 100px;
background-color: purple;
/* margin: 0 auto; */
}
/* .read-the-docs {
color: #888;
} */
</style>