props
props可以实现父子组件通信,不管是在vue2或者vue3,props数据还是只读的!!!不能直接修改其值;在vue3中,我们可以通过defineProps获取父组件传递的数据,且在组建内部不需要引入defineProps方法可以直接使用,如下面例子
Parent.vue
//父组件
<
template
>
<
h3
>
props组件案例
</
h3
>
<
div
class
=
"text_div"
>
props可以实现父子组件通信,不管是在vue2或者vue3,props数据还是只读的!!!不能直接修改其值;在vue3中,我们可以通过defineProps获取父组件传递的数据,且在组建内部不需要引入defineProps方法可以直接使用,如下面例子
</
div
>
<
div
class
=
"box"
>
<
h1
>
这是父组件
</
h1
>
<
Child1
info
=
"我是父组件传过来的值"
:money
=
"money"
>
</
Child1
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
Child1
from
"@/views/props/Child1.vue"
;
import
{ref}
from
"vue"
;
let
money =
ref
(
10000
)
</
script
>
<
style
scoped
>
.text_div
{
width
:
70%
;
height
:
50px
;
background
:
#1db393
;
}
.box
{
width
:
500px
;
height
:
300px
;
background
: hotpink;
}
</
style
>
Child1.vue
<
template
>
<
div
class
=
"son"
>
<
h3
>
这是子组件
</
h3
>
<
p
>
{{ props.info }}
</
p
>
<
p
>
{{ props.money }}
</
p
>
<
button
@
click
=
"updateProps"
>
修改props数据
</
button
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
let
props =
defineProps
([
'info'
,
'money'
]);
const
updateProps
=(
) =>{
console
.
log
(props.
info
)
}
</
script
>
<
style
scoped
>
.son
{
width
:
200px
;
height
:
200px
;
background
: yellow;
}
</
style
>
实现效果:
使用props,子组件获取父组件传递数据方式有两种:
方式一:
let
props = defineProps({
info:{
type:String,
//接受的数据类型
default
:
'默认参数'
,
//接受默认数据
},
money:{
type:Number,
default
:
0
}})
方式二:
let
props = defineProps([
"info"
,
'money'
]);
原生DOM事件
在vue框架中,事件可以分为两种:
一种是原生DOM事件(比如click、abclick、change、mouseenter、mouseleave.....),原生事件可以让用户与网页进行交互;
一种是自定义事件,自定义事件可以实现子组件给父组件传递数据
<!-- 原生DOM事件,默认会给事件回调注入event事件对象,无需写入 --><pre @click="handler"> 我是DOM原生事件</pre>
如果想给点击事件注入多个参数时,注入的事件对象必须叫做$event
<div @click="handler1(1,2,3,$event)">我要传递多个参数</div>
在vue3中click、dbclick、change(这类原生DOM事件),不管是在标签、自定义标签上(组件标签)都是原生DOM事件,而在vue2中组件、标签都需要通过.native修饰符才能变为原生DOM事件。
自定义事件
在vue3中,原生DOM事件不管是放在元素标签身上、组件标签上都是原生DOM事件,在vue2中,则需要通过.native修饰符变为原生DOM事件,如下:
父组件:
<
template
>
<
h1
>
自定义事件案例
</
h1
>
<
div
class
=
"fu"
>
<
h2
>
这是父组件
</
h2
>
<!-- 原生DOM事件-->
<
pre
@
click
=
"handler"
>
大江东去浪淘尽,千古分流人物
</
pre
>
<
hr
>
<
button
@
click
=
"handler1(1,2,3,$event)"
>
点击我传递多个参数
</
button
>
<!--
vue2框架当中:这种写法自定义事件,可以通过.native修饰符变为原生DOM事件
vue3框架下面写法其实即为原生DOM事件
vue3:原生的DOM事件不管是放在标签身上、组件标签身上都是原生DOM事件
-->
<
hr
>
<
zizujian1
@
click
=
"handler2"
>
</
zizujian1
>
<
hr
>
<!-- 绑定自定义事件
xxx:
实现子组件给父组件传递数据 -->
<
zizujian2
@
xxx
=
"handler3"
@
click
=
"handler4"
>
</
zizujian2
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
zizujian1
from
"@/views/zdy/zizujian1.vue"
;
import
Zizujian2
from
"@/views/zdy/zizujian2.vue"
;
// 回调事件-1
const
handler
= (
event
) =>{
console
.
log
(event)
}
//事件回调--2
const
handler1
= (
a,b,c,$event
)=>{
console
.
log
(a,b,c,$event)
}
//事件回调--3
const
handler2
= (
)=>{
console
.
log
(
"测试123"
)
}
//事件回调---4
const
handler3
= (
param1,param2
)=>{
console
.
log
(param1,param2);
}
//事件回调--5
const
handler4
= (
param1,param2
)=>{
console
.
log
(param1,param2);
}
</
script
>
<
style
scoped
>
.fu
{
width
:
700px
;
height
:
700px
;
background
:
#1db393
;
}
</
style
>
子组件1
<
template
>
<
div
class
=
"son1"
>
<
p
>
我是子组件1
</
p
>
<
button
>
点击我也执行
</
button
>
</
div
>
</
template
>
<
style
>
.son1
{
width
:
200px
;
height
:
200px
;
background
:
#1b6d85
;
}
</
style
>
子组件2
<
template
>
<
div
class
=
"child"
>
<
p
>
我是子组件2
</
p
>
<
button
@
click
=
"handler"
>
点击我触发自定义事件xxx
</
button
>
<
button
@
click
=
"$emit('click','AK47','J20')"
>
点击我触发自定义事件click
</
button
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
let
$emit =
defineEmits
([
'xxx'
,
'click'
]);
//按钮点击回调
const
handler
= (
) => {
//第一个参数:事件类型 第二个|三个|N参数即为注入数据
$emit(
'xxx'
,
'东风导弹'
,
'航母'
);
};
</
script
>
<
style
scoped
>
.child
{
width
:
400px
;
height
:
200px
;
background
: pink;
}
</
style
>
正常情况下,组件标签@click应该为原生DOM事件,但是如果子组件内部通过defineEmits定义就变为自定义事件了。
mitt
mitt是一个方法,会返回一个对象,该对象上挂载了四个方法,分别为all、on、off、emit
官网:https://www.npmjs.com/package/mitt
在src文件下新建文件bus/index.ts
//引入mitt插件:mitt一个方法,方法执行会返回bus对象
import
mitt
from
'mitt'
;
const
$bus =
mitt
();
export
default
$bus;
父组件:
<
template
>
<
div
class
=
"container"
>
<
Child1
>
</
Child1
>
<
Child2
>
</
Child2
>
</
div
>
</
template
>
<
script
setup
lang
=
"ts"
>
//引入子组件
import
Child1
from
"./Child1.vue"
;
import
Child2
from
"./Child2.vue"
;
</
script
>
<
style
scoped
>
.box
{
width
:
100vw
;
height
:
400px
;
background
: yellowgreen;
}
.container
{
display
: flex;
justify-content
: space-between;
}
</
style
>
Child1.vue
<template> <div class="child1"> <h3>我是子组件1:曹植</h3> </div></template><script setup lang="ts">import $bus from "../../bus";//组合式API函数import { onMounted } from "vue";//组件挂载完毕的时候,当前组件绑定一个事件,接受将来兄弟组件传递的数据onMounted(() => { //第一个参数:即为事件类型 第二个参数:即为事件回调 $bus.on("car", (car) => { console.log(car); });});</script><style scoped>.child1 { width: 300px; height: 300px; background: hotpink;}</style>
Child2.vue
<
template
>
<
div
class
=
"child2"
>
<
h2
>
我是子组件2:曹丕
</
h2
>
<
button
@
click
=
"handler"
>
点击我给兄弟送一台法拉利
</
button
>
</
div
>
</
template
>
<
script
setup
lang
=
"ts"
>
//引入$bus对象
import
$bus
from
'../../bus'
;
//点击按钮回调
const
handler
= (
)=>{
$bus.
emit
(
'car'
,{
car
:
"法拉利"
});
}
</
script
>
<
style
scoped
>
.child2
{
width
:
300px
;
height
:
300px
;
background
: skyblue;
}
</
style
>
v-model
v-model有两个功能,
一个是收集表单数据(实现数据双向绑定);
一个是实现父子组建数据同步。
父组件
<
template
>
<
div
>
<
h1
>
v-model:钱数{{ money }} {{ pageNo }} {{ pageSize }}
</
h1
>
<
input
type
=
"text"
v-model
=
"info"
/>
<
h5
>
v-model数据同步输入框信息:{{info}}
</
h5
>
<
hr
/>
<!-- props:父亲给儿子数据 -->
<!-- <Child :modelValue="money" @update:modelValue="handler"></Child> -->
<!--
v-model组件身上使用
第一:相当有给子组件传递props[modelValue] = 10000
第二:相当于给子组件绑定自定义事件update:modelValue -->
<
zizujian1
v-model
=
"money"
>
</
zizujian1
>
<
hr
/>
<
zizujian2
v-model:pageNo
=
"pageNo"
v-model:pageSize
=
"pageSize"
>
</
zizujian2
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
//父亲给子组件数据 props
// 子组件给父组件数据 自定义事件
// 引入子组件
import
zizujian1
from
"@/views/v-model/zizujian1.vue"
;
import
zizujian2
from
"@/views/v-model/zizujian2.vue"
;
import
{ ref }
from
"vue"
;
let
info =
ref
(
""
);
//父组件的数据钱数
let
money =
ref
(
10000
);
//自定义事件的回调
const
handler
= (
num
) => {
money.
value
= num;}
//将来接受子组件传递过来的数据
//父亲的数据
let
pageNo =
ref
(
1
);
let
pageSize =
ref
(
3
);
</
script
>
子组件1
<
template
>
<
div
class
=
"child"
>
<
h3
>
钱数:{{ modelValue }}
</
h3
>
<
button
@
click
=
"handler"
>
父子组件数据同步
</
button
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
//子组件获取父组件的值接受props
let
props =
defineProps
([
"modelValue"
]);
let
$emit =
defineEmits
([
'update:modelValue'
]);
//子组件内部按钮的点击回调
const
handler
= (
)=>{
//触发自定义事件
$emit(
'update:modelValue'
,props.
modelValue
+
1000
);
}
</
script
>
<
style
scoped
>
.child
{
width
:
600px
;
height
:
300px
;
background
: skyblue;
}
</
style
>
子组件2
<
template
>
<
div
class
=
"child2"
>
<
h1
>
同时绑定多个v-model
</
h1
>
<
button
@
click
=
"handler"
>
pageNo{{ pageNo }}
</
button
>
<
button
@
click
=
"$emit('update:pageSize', pageSize + 4)"
>
pageSize{{ pageSize }}
</
button
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
let
props =
defineProps
([
"pageNo"
,
"pageSize"
]);
let
$emit =
defineEmits
([
"update:pageNo"
,
"update:pageSize"
]);
//第一个按钮的事件回调
const
handler
= (
) => {
$emit(
"update:pageNo"
, props.
pageNo
+
3
);
};
</
script
>
<
style
scoped
>
.child2
{
width
:
300px
;
height
:
300px
;
background
: hotpink;
}
</
style
>
useAttrs
在Vue3中可以利用useAttrs方法获取组件的属性与事件(包含:原生DOM事件或者自定义事件),此函数功能类似于Vue2框架中attrs属性与listeners方法
父组件
<
template
>
<
h1
>
useAttrs组件学习
</
h1
>
<
div
class
=
"fu"
title
=
"这是编辑按钮"
>
<
h2
>
这是父组件
</
h2
>
<!-- 自定义组件-->
<
el-button
type
=
"primary"
size
=
"default"
:icon
=
"Edit"
@
click
=
"handler"
@
xxx
=
"handler"
>
修改按钮
</
el-button
>
<!-- 给子组件1传入参数-->
<
zizujian1
type
=
"primary"
size
=
"default"
:icon
=
"Edit"
@
click
=
"handler"
@
xxx
=
"handler"
>
</
zizujian1
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
zizujian1
from
"@/views/useAttrs/zizujian1.vue"
;
import
{
Edit
,
}
from
'@element-plus/icons-vue'
const
handler
= (
) =>{
alert
(
"点击了编辑按钮"
)
}
</
script
>
<
style
scoped
>
.fu
{
width
:
100vw
;
height
:
600px
;
background
:
#1db393
;
}
</
style
>
子组件
<
template
>
<
div
class
=
"son"
>
<
h2
>
这是子组件1
</
h2
>
<
el-button
:
=
"$attrs"
>
</
el-button
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
{useAttrs}
from
"vue"
;
let
$attrs =
useAttrs
();
console
.
log
($attrs)
</
script
>
<
style
scoped
>
.son
{
width
:
300px
;
height
:
200px
;
background
:
#42b983
;
}
</
style
>
ref与$parent
父组件
<
template
>
<
h1
>
这是父组件
</
h1
>
<
div
class
=
"fu"
>
<
h2
>
我是父亲刘备:{{ money }}
</
h2
>
<
button
@
click
=
"handler"
>
点我向儿子刘封借100元
</
button
>
<
zizujian2
ref
=
"son1"
>
</
zizujian2
>
<
zizujian1
>
</
zizujian1
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
{ref}
from
"vue"
;
import
zizujian1
from
"@/views/ref_parent/zizujian1.vue"
;
import
zizujian2
from
"@/views/ref_parent/zizujian2.vue"
;
import
Zizujian1
from
"@/views/ref_parent/zizujian1.vue"
;
let
money =
ref
(
10000000
);
let
son1 =
ref
()
const
handler
= (
) => {
money.
value
+=
100
;
son1.
value
.
money
-=
100
;
son1.
value
.
fly
()
}
defineExpose
(
{
money,
}
)
</
script
>
<
style
scoped
>
.fu
{
width
:
100vw
;
height
:
600px
;
background
:
#1db393
;
}
</
style
>
子组件1
<
template
>
<
div
class
=
"son"
>
<
h1
>
我是儿子刘婵{{money}}
</
h1
>
<
button
@
click
=
"handler($parent)"
>
点击我爸爸给我10000元
</
button
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
{ref}
from
'vue'
;
let
money =
ref
(
999999
);
const
handler
= (
$parent
)=>{
money.
value
+=
10000
;
$parent.
money
-=
10000
;
}
</
script
>
<
style
scoped
>
.son
{
width
:
300px
;
height
:
300px
;
background
: hotpink;
}
</
style
>
子组件2
<
template
>
<
div
class
=
"son"
>
<
h3
>
我是子组件:刘封{{money}}
</
h3
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
{ref}
from
"vue"
;
let
money =
ref
(
1000
)
const
fly
=(
)=>{
alert
(
"父亲刘备向我借了100"
)
}
defineExpose
(
{
money,
fly
}
)
</
script
>
<
style
scoped
>
.son
{
width
:
300px
;
height
:
200px
;
background
: cyan;
}
</
style
>
provide(提供)与inject(注入)
vue3提供两个方法provide与inject,可以实现隔辈组件传递参数
provide方法用于提供数据,此方法执需要传递两个参数,分别提供数据的key与提供数据value
爷组件
<
template
>
<
div
class
=
"box"
>
<
h1
>
我是父组件
</
h1
>
<
h2
>
car:{{ car }}
</
h2
>
<
hr
>
<
zizujian
>
</
zizujian
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
zizujian
from
"@/views/provide_inject/zizujian.vue"
;
//vue3提供provde与inject可以实现隔辈传递数据
import
{ref, provide}
from
'vue'
;
let
car =
ref
(
"法拉利"
)
//provide 需要传入两个参数 第一个参数提供数据的key 第二个 祖先组件提供的数据
provide
(
"fucar"
, car)
</
script
>
<
style
scoped
>
.box
{
width
:
100vw
;
height
:
500px
;
background
: skyblue;
}
</
style
>
子组件
<
template
>
<
div
class
=
"er"
>
<
h1
>
儿子组件
</
h1
>
<
runzujian
>
</
runzujian
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
runzujian
from
"@/views/provide_inject/runzujian.vue"
;
</
script
>
<
style
scoped
>
.er
{
width
:
400px
;
height
:
300px
;
background
: palevioletred;
}
</
style
>
孙组件
<
template
>
<
div
class
=
"sun"
>
<
h1
>
孙子组件
</
h1
>
<
h2
>
{{car}}
</
h2
>
</
div
>
</
template
>
<
script
setup
lang
=
"js"
>
import
{inject}
from
"vue"
;
let
car =
inject
(
"fucar"
)
</
script
>
<
style
scoped
>
.sun
{
width
:
200px
;
height
:
200px
;
background
: red;
}
</
style
>
pipa
pinia也是集中式管理状态容器,类似于vuex,
但是核心概念没有mutation、modules
solt
插槽:分为默认插槽、具名插槽、作用域插槽
原文始发于微信公众号(小C学安全):【前端VUE】VUE通信组件学习(附源代码)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论