最近在想做个cloud项目,gitee上找了个模板项目,前端使用到vue3 + typeScript,最近使用到vue3 的父子组件之间的传值,顺便学习一下,在此总结一下,若有不足之处,望大佬们可以指出。
vue3官网:https://cn.vuejs.org/
<template>
<div>
<child :num="nums.num" :doubleNum="nums.doubleNum" @increase="handleIncrease">child>
div>
template>
<script setup lang="ts">
import child from './child.vue';
import { ref,reactive } from 'vue';
// 对象默认
const nums = reactive({
num: 0,
doubleNum: 0
});
// 点击事件
const handleIncrease = () => {
// 每次+1
nums.num++
// 每次+2
nums.doubleNum += 2
};
script>
defineEmits: defineEmits() 宏仅限于 setup 语法糖 使用,用来声明组件要触发的事件。
<template>
<div>
<span>点击次数:{{ props.num }}span><br/>
<span>双倍次数:{{ props.doubleNum }}span><br/>
<el-button @click="handelClick">点击el-button>
div>
template>
<script setup lang="ts">
import { ref } from 'vue';
// 声明组件要触发的事件
const emits = defineEmits(['increase']);
// 声明接收参数
const props = defineProps({
num: String,
doubleNum: String
});
// 点击事件
const handelClick = () => {
console.log('触发子组件点击')
// 触发父组件事件
emits('increase')
};
script>
官方文档:https://cn.vuejs.org/guide/components/props.html#prop-passing-details
<template>
<div>
<child v-bind="nums" @increase="handleIncrease">child>
div>
template>
这实际上等价于:
<template>
<div>
<child :num="nums.num" :doubleNum="nums.doubleNum" @increase="handleIncrease">child>
div>
template>
<template>
<div>
<el-input v-model="dataForm.name" placeholder="请输入我的名字" style="width: 120px"/>
<br />
<el-input v-model="dataForm.age" placeholder="请输入我的年龄" style="width: 120px"/>
<br />
<el-button @click="handelClick">完成el-button>
div>
template>
<script setup lang="ts">
import { ref, reactive } from 'vue';
const emits = defineEmits(['increase']);
// 对象
const dataForm = reactive({
name: '',
age: ''
})
const handelClick = () => {
console.log('触发子组件点击', dataForm.name, ' ', dataForm.age)
// 传递对象
emits('increase',dataForm)
};
script>
<template>
<div>
<child @increase="handleIncrease">child>
<br />
我是父组件,我接收到的参数:<span v-if="data.name">姓名:{{data.name}}span> <span v-if="data.age">, 年龄:{{data.age}}span>
div>
template>
<script setup lang="ts">
import child from './child.vue';
import { ref,reactive } from 'vue';
// 接收对象封装
const data = reactive({
name: '',
age: ''
});
// 点击事件
const handleIncrease = (val : any) => {
data.name = val.name
data.age = val.age
};
script>
概述: 这是我在 clone 项目模板中看到的使用方式,也属于最常用的方式。
<template>
<div>
<child ref="data">child>
<br />
<span>我是父组件span>
// 输入姓名
<el-input v-model="name" placeholder="请输入我的姓名" style="width: 120px"/>
// 点击完成
<el-button @click="handelClick()">完成el-button>
div>
template>
<script setup lang="ts">
import child from './child.vue';
import { ref,reactive } from 'vue';
// 绑定的data
const data = ref()
// 姓名事件
const name = ref('' as string)
// 点击完成事件
const handelClick = () => {
console.log('name:', name.value)
// 初始化
data.value.init(name.value)
console.log('data: ', data.value)
}
script>
<template>
<div>
<span>我是子组件span>
<el-input v-model="dataForm.name" placeholder="请输入我的名字" style="width: 120px"/>
<br />
<el-input v-model="dataForm.age" placeholder="请输入我的年龄" style="width: 120px"/>
<br />
div>
template>
<script setup lang="ts">
import { ref, reactive } from 'vue';
// 组件对应的数据
const dataForm = reactive({
name: '',
age: ''
})
// 假设后端返回list
const listDate: Array<object> = [{name: "lanys", age: 23}]
// 初始化方法 name 指的就是父组件传过来的name
const init = (name : string) => {
if (name) {
listDate.forEach((val : any) => {
// 如果name 相同就 渲染 就类似更新功能
if (val.name === name) {
dataForm.name = val.name
dataForm.age = val.age
}
})
}
}
// 暴露组件
defineExpose(
{init}
)
script>
从项目中能看出新增和更新功能可以做到通用,节省开发时间及成本。项目中是这么设计的,
在子组件 init(初始化中)
const init = (id?: number) => {
// id 存在则为修改
if (id) {
getUser(id)
}
// 获取下面的列表数据 可以忽略
getOrgList()
// 忽略
getPostList()
// 忽略
getRoleList()
}
// 暴露组件
defineExpose({
init
})