一、vuex 实现组件传值
父子,子子,祖孙
二、setup语法糖
javascript
<!-- 使用组件,通过 :自定义属性名="属性值" 的形式传递数据 -->
<!-- 属性值 是defineProps中的数据-->
<children :le="text" :list="list"></children>
情况一:父传子收
1、父组件传值
- 解构抛出
html
<template>
<div class="father">
<h1>父组件</h1>
<span>{{text}}</span>
</div>
<div class="box">
<!-- 使用组件,通过 :自定义属性名="属性值" 的形式传递数据 -->
<children :le="text" :list="list"></children>
</div>
</template>
<script setup>
// 引入
import {reactive, toRefs,} from 'vue';
// 引入组件
import children from "./views/children";
const data = reactive({
text: '文字',
list: [1, 2, 3, 4, 5]
})
// 解构抛出
const {text, list} = toRefs(data)
</script>
<style scoped>
.father {
width: 100%;
height: 200px;
background: red;
}
</style>
2、子组件
- 通过defineProps()可接收父组件传递的值;
- type属性定义接受的数据类型;
- default属性设置默认值,在当前属性没有值传入时使用;
html
<template>
<div class="box">
<h1>子组件</h1>
<div>{{ le }}</div>
<div v-for="item in list">{{ item }}</div>
</div>
</template>
<script setup>
// 引入
import { defineProps } from 'vue';
// 解构数据
const { le, list } = defineProps({
le: {
type: String, // 接收的参数类型
default: '默认文字', //默认值
},
list: {
type: Array, // 接收的参数类型
default: [], //默认值
}
})
</script>
<style scoped>
.box{
width: 100%;
height: 200px;
background: #25A4BB;
}
</style>
情况二:子传父收
方法一 :defineEmits 需要点击
1、 子组件传值
- 调用defineEmits并定义要给父组件的方法,数组内可定义多个方法
- 第一个参数为要传递的事件名,第二个参数为要传递的值
html
<template>
<div class="box">
<h1>子组件</h1>
<div>{{ le }}</div>
<button @click="giveFather">点击传值给父</button>
</div>
</template>
<script setup>
// 引入defineEmits
import { reactive, defineEmits } from 'vue';
// 接收defineEmits
const emits=defineEmits()
const data = reactive({
text: '文字',
})
function giveFather() {
// 第一个参数为要传递的事件名,第二个参数为要传递的值
emits('giveFather', data.text)
}
</script>
<style scoped>
.box{
width: 100%;
height: 200px;
background: #25A4BB;
}
</style>
2、父组件接收
- 父组件中使用自定义事件接收,自定义事件名称必须与子组件传递的一致(即等号前面名称)
- 等号后面的事件名称可自行定义
- 事件中通过默认参数接收使用子组件传递的值
html
<template>
<div class="father">
<h1>父组件</h1>
<span>{{text}}</span>
</div>
<!-- 父组件中使用自定义事件接收,自定义事件名称必须与子组件传递的一致(即等号前面名称) -->
<!-- 等号后面的事件名称可自行定义 -->
<children @giveFather="receiveSon"></children>
</template>
<script setup>
// 引入
import {reactive, toRefs,} from 'vue';
// 引入组件
import children from "./views/children";
const data = reactive({
text: '',
})
function receiveSon(e) {
// 通过默认参数接收使用子组件传递的值
console.log(e);
data.text = e
}
//解构数据
const {text} = toRefs(data)
</script>
<style scoped>
.father {
width: 100%;
height: 200px;
background: red;
}
</style>
方法二 :defineExpose
1、子组件
html
<template>
{{ name }}
</template>
<script setup>
import { ref } from 'vue'
const name = ref("张三")
defineExpose({
name
});
</script>
5、父组件
- children.value.name 必须在函数中
html
<template>
<child ref="children"></child>
<button @click="aaa"> 点击</button>
</template>
<script setup>
import { ref } from 'vue'
import child from './views/children'
const children = ref(null)
function aaa(){
console.log(children.value.name) // "张三"
// "我叫张三"
}
</script>
三、setup 函数方式
情况一:父传子收
方法一 利用props 刷新便可以传值
1、父组件 ---通过 :自定义属性名="属性值" 的形式传递数据
html
//父组件
<template>
<div class="father">
<h1>父组件</h1>
<span>{{text}}</span>
</div>
<div class="box">
<!-- 使用组件,通过 :自定义属性名="属性值" 的形式传递数据 -->
<children :le="text" :list="list"></children>
</div>
</template>
<script>
// 引入
import { reactive, toRefs, } from 'vue';
// 引入组件
import children from "./views/children";
export default {
name: 'app',
// 注册组件
components: {
children
},
setup() {
const data = reactive({
text: '文字',
list: [1, 2, 3, 4, 5]
})
return {
// 解构抛出
...toRefs(data),
}
}
}
</script>
<style scoped>
.father{
width: 100%;
height: 200px;
background: red;
}
</style>
2、 子组件接收
- props接受父传递的数据;
- type属性定义接受的数据类型;
- default属性设置默认值,在当前属性没有值传入时使用;
html
//子组件
<template>
<div class="box">
<h1>子组件</h1>
<div>{{ le }}</div>
<div v-for="item in list">{{ item }}</div>
</div>
</template>
<script>
// 引入
import { defineComponent } from 'vue';
// 加上defineComponent()之后,可以获得vue2、vue3的自动提示---可有可无
export default defineComponent({
name: 'children',
props: {
le: {
type: String, // 接收的参数类型
default: '默认文字', //默认值
},
list: {
type: Array, // 接收的参数类型
default: [] //默认值
}
},
// props 是一个对象,包含父组件传递给子组件的所有数据。
// context :上下文,包括 attrs 、 emit 、slots。
setup(props, context) {
console.log(props.le, props.list[0]);
},
})
</script>
<style scoped>
.box{
width: 100%;
height: 200px;
background: #25A4BB;
}
</style>
方法二、 父组件中调用子组件的方法
1、父组件
javascript
<template>
<helloworld ref ="val"/>//在父组件中找到子组件的节点
</template>
<script>
import {reactive,ref} from "vue"
import helloworld from "组件路径"
export default {
compoents:{
helloworld
},
setup() {
const val = ref()
const p1 = reactive({name:"小宋",age:12})
function btn(){//点击事件调用子组件的方法
val.vlaue.receive(p1)
}
return{btn,val}
}
</script>
2、子组件
javascript
export default {
name:"helloworld",
setup(){
//被父组件调用的方法
function receive(val){
console.log(val)
}
return{receive}
}
情况二:子传父收
1、 子组件
- setup函数中ctx的emit用于传递事件给父组件
- 第一个参数为要传递的事件名,第一个参数为要传递的值
html
<template>
<div class="box">
<h1>子组件</h1>
<button @click="giveFather">点击传值传给父</button>
</div>
</template>
<script>
// 引入
import { reactive, defineComponent } from 'vue';
// 加上defineComponent()之后,可以获得vue2、vue3的自动提示
export default defineComponent({
name: 'child',
// props 是一个对象,包含父组件传递给子组件的所有数据。
// ctx :上下文,包括 attrs 、 emit 、slots。
setup(props, ctx) {
const data = reactive({
text: '文字',
})
function giveFather() {
// ctx中的emit用于传递事件给父组件
// 第一个参数为要传递的事件名,第一个参数为要传递的值
ctx.emit('giveFather', data.text)
}
return {
// setup函数中定义事件需要抛出才能使用
giveFather
}
},
})
</script>
<style scoped>
.box{
width: 100%;
height: 200px;
background: #25A4BB;
}
</style>
2、父组件接收
- 父组件中使用自定义事件接收,自定义事件名称必须与子组件传递的一致(即等号前面名称)
- 等号后面的事件名称可自行定义
- 事件中通过默认参数接收使用子组件传递的值
html
<template>
<div class="father">
<h1>父组件</h1>
<div>{{ cont }}</div>
</div>
<div class="box">
<!-- 父组件中使用自定义事件接收,自定义事件名称必须与子组件传递的一致(即等号前面名称) -->
<!-- 等号后面的事件名称可自行定义 -->
<children @giveFather="receiveSon"></children>
</div>
</template>
<script>
// 引入
import { reactive, toRefs, } from 'vue';
// 引入组件
import children from "./views/children";
export default {
name: 'app',
// 注册组件
components: {
children
},
setup() {
const data = reactive({
cont: '',
})
function receiveSon(e) {
// 通过默认参数接收使用子组件传递的值
data.cont = e
}
return {
// 解构抛出
...toRefs(data),
// 抛出事件
receiveSon
}
},
}
</script>
<style scoped>
.father{
width: 100%;
height: 200px;
background: red;
}
</style>
情况三:祖传孙收
1、祖组件----利用provide
javascript
//进入页面即刻传值
<template>
<helloworld/>
</template>
<script>
import {reactive} from "vue"
import helloworld from "组件路径"
export default {
compoents:{
helloworld
},
setup() {
const p1 = reactive({name:"小宋",age:12})
provide("p",p1)//祖传 第一个参数是子组件用来识别的参数
}
}
//点击传值
2、子组件--inject
javascript
export default {
name:"helloworld",
setup(){
const res = inject("p")//孙收
}