VUE 父组件与子组件交互
1. 概述
1.1 说明
在项目过程中,会有很多重复功能在多个页面中处理,此时则需要把这些重复的功能进行单独拎出,编写公用组件(控件)进行引用。在VUE中,组件是可复用的VUE实例,此时组件中的data必须是一个函数,因为data是一个函数时,每次引用此组件时相当于重新对返回对象进行独立的拷贝(实例化/new),如果data不是一个函数而是一个对象,那么多个引用同一组件时其中一个引用更改数据,其他引用中的数据都会更改。由于业务的不同,组件中的数据交互也会不同。
1.2 父组件向组件传递数据(Prop)
Prop可以在组件上注册一些自定义特性,当一个值传递给一个prop特性的时候,它就变成了那个组件(子组件)实例的一个属性,可以像访问data中的值一样去访问prop中的特性(属性列表)。任何类型的值都可以传给一个prop,prop使得其父子prop之间形成一个单向下行绑定,即数据是在父组件中更改后才绑定到子组件中,父组件每次发生更新,子组件中所有的prop都将会刷新为最新的值。
prop的常见书写方式如:
- props: ['name', 'address', 'desc']
- props: { name: String, address: String, desc: String, userInfo: Object }
1.2.1 子组件示例代码
子组件props中需要包含父组件流向的数据信息,以便显示在子组件中(可以直接页面绑定{{}},也可数据接收处理)。
<template>
<div class="child-wrap">
<p>姓名:{{name}}</p>
<p>性别:{{sex}}</p>
<p>年龄:{{age}}</p>
</div>
</template>
<script>
export default {
props:{
name:{
type:String,
default:''
},
sex:{
type:String,
default:''
},
age:{
type:Number,
default:0
}
}
}
</script>
<style scoped>
</style>
1.2.2 父组件示例代码
父组件中对子组件传递的数据像使用属性一样的去传递。
<template>
<div class="parent-wrap">
<child-component :sex="pSex" :name="pName" :age="pAge"></child-component>
</div>
</template>
<script>
import child from './child/child'
export default {
data() {
return {
pSex:'男',
pName:'张三',
pAge:28
}
},
components: {
"child-component": child
},
}
</script>
<style scoped>
</style>
1.3 父组件调用子组件事件
父组件直接访问子组件时,需要使用ref为子组件指定一个引用ID,渲染完成后即为指定子组件的实例,即可操作其内方法。
1.3.1 子组件示例代码
子组件methods中需要包含父组件所调用的子组件方法,可以传递参数值从父组件至子组件,以便来更改或操作子组件中的某些数据。
<template>
<div class="child-wrap">
<button @click="confirmClick">子组件按钮</button>
</div>
</template> <script>
export default {
methods: {
confirmClick(val) {
console.log(val)
}
}
}
</script> <style scoped> </style>
1.3.2 父组件示例代码
在父组件中,子组件使用ref来注册引用信息,引用信息将会注册在父组件的$refs对象上。
注意:ref被用来给元素或子组件注册引用信息,如果是dom元素,引用只想的就是dom元素,如果是组件,引用就指向组件实例。
ref注册时间:ref本身是作为渲染结果被创建的,在初始渲染的时候不能够进行访问它。
<template>
<div class="parent-wrap">
<child-component ref="child"></child-component>
<button @click="parentClick" class="btnClass">父组件按钮</button>
</div>
</template> <script>
import child from './child/child'
export default {
data() {
return {}
},
components: {
"child-component": child
},
methods: {
parentClick() {
this.$refs.child.confirmClick("父组件调用");
}
}
}
</script>
<style scoped> </style>
1.4 子组件触发父组件事件
在子组件里用$emit向父组件触发一个事件,父组件监听这个事件。
1.4.1 子组件示例代码
子组件methods中去注册能够调用父组件方法的入口。
<template>
<div class="child-wrap">
<button @click="confirmClick">子组件按钮</button>
</div>
</template>
<script>
export default {
methods: {
confirmClick() {
this.$emit('child-click','点击了子组件按钮')
}
}
}
</script>
<style scoped>
</style>
1.4.2 父组件示例代码
父组件的子组件中使用事件进行监听所需调用的方法,其中@后跟随的是子组件中注册的自定义事件名,后边所调用的方法为父组件中所定义的方法名。
<template>
<div class="parent-wrap">
<child-component @child-click="childClick"></child-component>
<p>{{strChild}}</p>
</div>
</template>
<script>
import child from './child/child'
export default {
data() {
return {
strChild:''
}
},
components: {
"child-component": child
},
methods: {
childClick(val) {
this.$data.strChild=val;
}
}
}
</script>
<style scoped>
</style>
注意:也可直接props传递方法进行子组件调用父组件方法。
2. 数据交互
在实际项目应用中,很多时候需要实时的获取到子组件中的数据信息,即子组件数据更改父组件数据。此时就需要监控子组件数据是否更改(watch),而子组件则需要进行计算其数据集(computed)
2.1 代码示例
2.1.1 父组件示例代码
子组件每次调用时都需要是重新实例化的(每次调用子组件才会是单独的组件),故可以使用v-if来进行处理
<template>
<div>
<Button
type='primary'
@click='addPerson()'>新增</Button>
<Button
type='primary'
@click='editPerson()'>编辑</Button> <Modal
v-model='childModalVisible'
title="新增人员"
width='800'
@on-cancel='cancleModal'
closable>
<child-update v-if="childModalVisible" ref="childUpdate" :data='objChild' />
<div slot='footer'>
<Button @click='cancleModal'>取消</Button>
<Button @click='submitModal' type='primary'>确定</Button>
</div>
</Modal>
<Row style="margin-top: 20px; background: #f5f5f5;font-size: 40px;font-weight: 600;">
<Col span="6">姓名:{{objChild.name}}</Col>
<Col span="6">性别:{{objChild.sex}}</Col>
<Col span="6">电话:{{objChild.phoneNo}}</Col>
<Col span="6">地址:{{objChild.address}}</Col>
</Row>
</div>
</template> <script>
import ChildUpdate from '../components/updateChild'
export default {
name: "updateParent.vue",
components: {
ChildUpdate,
},
data(){
return {
childModalVisible:false,
objChild:{}
}
},
methods:{
addPerson(){
this.objChild={
name: '',
sex: 0,
phoneNo: '',
address:''
};
this.childModalVisible=true
},
editPerson(){
this.objChild={
name: '张三',
sex: 0,
phoneNo: '15136466666',
address:'浙江省杭州市'
}
this.childModalVisible=true
},
cancleModal(){
this.childModalVisible=false
},
submitModal(){
if(this.$refs.childUpdate.validateForm('childPersonForm')){
let bSubmit=true
if (this.objChild.phoneNo) {
const reg = /^[1][3,4,5,7,8][0-9]{9}$/
if (!reg.test(this.objChild.phoneNo)) {
bSubmit=false
}
}
if(bSubmit){
this.childModalVisible=false
} else {
this.$Message.error('请输入正确的电话号码!')
}
} else {
this.$Message.error('请输入正确的人员信息!')
}
}
}
}
</script> <style scoped> </style>
2.1.2 子组件示例代码
通过监控子组件数据更新去更新父组件数据信息,使用watch;
通过计算属性去判断父组件数据更新赋值于子组件数据,使用 computed
<template>
<div>
<Form
ref='childPersonForm'
:model='childPersonForm'
:rules='formRules'
:label-width='90'>
<Row>
<Col span='12'>
<FormItem label='姓名' prop='name'>
<Input
v-model='childPersonForm.name'
:maxlength='20'
type='text'
placeholder='请输入'></Input>
</FormItem>
</Col>
<Col span='12'>
<FormItem label='性别' prop='sex'>
<Select v-model='childPersonForm.sex' clearable>
<Option
v-for='item in personSexOption'
:value='item.value'
:label='item.name'
:key='item.value'>{{item.name}}</Option>
</Select>
</FormItem>
</Col>
</Row>
<Row>
<Col span='12'>
<FormItem label='电话' prop='phoneNo'>
<Input
v-model='childPersonForm.phoneNo'
:maxlength='11'
type='text'
@on-blur='telNoValidate'
placeholder='请输入'></Input>
</FormItem>
</Col>
<Col span='12'>
<FormItem label='住址' prop='address'>
<Input
v-model='childPersonForm.address'
:maxlength='20'
type='text'
placeholder='请输入'></Input>
</FormItem>
</Col>
</Row>
</Form>
</div>
</template> <script>
export default {
props: {
data: {
type: Object,
default() {
return {
name: '',
sex: 0,
phoneNo: '',
address:''
}
},
},
},
data() {
// eslint-disable-next-line
const nameRules = (rule, value, callback) => {
const reg = /[0-9]/
const regEn = /[`~!@#$%^&*()_+<>?:"{},\\.\/;'[\]]/im
const regCn = /[·!#¥(——):;“”‘、,|《。》?、【】[\]]/im
if (value === '') {
callback(new Error('姓名不能为空'))
} else if (regEn.test(value) || regCn.test(value)) {
callback(new Error('姓名不能包含特殊字符'))
} else if (reg.test(value)) {
callback(new Error('姓名不能包含数字'))
} else {
callback()
}
}
return {
formRules: {
name: [{ required: true, validator: nameRules, trigger: 'blur' }],
},
}
},
computed: {
personSexOption() {
return [{value:0,name:'男'},{value:1,name:'女'}]
},
childPersonForm() {
console.log(this.data)
return this.data
},
},
watch: {
childPersonForm: {
handler(oldVal, newVal) {
this.data.name = newVal.name
this.data.sex = newVal.sex
this.data.phoneNo = newVal.phoneNo
this.data.address = newVal.address
},
deep: true,
},
},
methods: {
telNoValidate() {
if (this.childPersonForm.phoneNo) {
const reg = /^[1][3,4,5,7,8][0-9]{9}$/
if (!reg.test(this.childPersonForm.phoneNo)) {
this.$Message.error('请输入正确的电话号码!')
}
}
},
/**
* 表单验证
*/
validateForm(name) {
let bReturn = false
this.$refs[name].validate(valid => {
if (valid) {
bReturn = true
} else {
bReturn = false
}
})
return bReturn
},
},
}
</script> <style scoped> </style>
3. 父子组件生命周期钩子执行顺序
- 加载渲染过程
- 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
- 子组件更新过程
- 父beforeUpdate->子beforeUpdate->子updated->父updated
- 父组件更新过程
- 父beforeUpdate->父updated
- 销毁过程
- 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
VUE 父组件与子组件交互的更多相关文章
- vue学习之父组件与子组件之间的交互
1.父组件数据传给子组件 父组件中的msgfather定义数据 在之组件中通过设置props来取得希望从父组件中获得的值 通过设置这两个属性就可以从父组件传数据到子组件 2.子组件传数据给父组件(这里 ...
- vue 父组件传递子组件事件
在开发中,碰到一个需要从父组件传入方法,子组件点击触发,说白了就是,把方法传入给子组件调用 <el-col v-for='data in spreadFormat.icons' class=&q ...
- Vue中,父组件向子组件传值
1:在src/components/child/文件夹下,创建一个名为:child.vue的子组件 2:在父组件中,设置好需要传递的数据 3:在App.vue中引入并注册子组件 4:通过v-bind属 ...
- Vue父组件向子组件传递一个动态的值,子组件如何保持实时更新实时更新?
原文:https://blog.csdn.net/zhouweixue_vivi/article/details/78550738 2017年11月16日 14:22:50 zhouweixue_vi ...
- Vue 组件&组件之间的通信 之 父组件向子组件传值
父组件向子组件传值:父组件通过属性向下传值的方式和子组件通信: 使用步骤: 定义组件:现有自定义组件com-a.com-b,com-a是com-b的父组件: 准备获取数据:com-b要获取父组件dat ...
- vue+elementUI项目,父组件向子组件传值,子组件向父组件传值,父子组件互相传值。
vue+elementUI项目,父组件向子组件传值,子组件向父组件传值,父子组件互相传值. vue 父组件与子组件相互通信 一.父组件给子组件传值 props 实现父组件向子组件传值. 1父组件里: ...
- Vue系列之 => 父组件向子组件传值
父组件向子组件传递数据 1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta c ...
- vue 父组件给子组件传值 Vue父组件给子组件传方法 Vue父组件把整个实例传给子组件
Home.vue <template> <!-- 所有的内容要被根节点包含起来 --> <div id="home"> <v-header ...
- vue 的父组件和子组件互相获取数据和方法
父组件主动获取子组件的数据和方法 一.ref(但不能实时更新获取) 1.调用子组件的时候 定义一个ref <child ref="headerChild"></c ...
随机推荐
- 题解 P2763 【试题库问题】
这题可以用网络流,但我用的是匈牙利算法 进入正题 设第个类型需要个.将每个类型拆成个点,用一个边集数组记录它拆成的点. 第个试题有个类型,分别将与拆成的点连边,这样便构成了一个二分图. 使用匈牙利算法 ...
- 【MySQL 读书笔记】当我们在使用索引的时候我们在做什么
我记得之前博客我也写过关于索引使用的文章,但是并不全面,这次尽量针对重点铺全面一点. 因为索引是数据引擎层的结构我们只针对最常见使用的 Innodb 使用的 B+Tree 搜索树结构进行介绍. 每一个 ...
- Iterator和Enumeration的区别
从源码可以看出,Iterator除了能读取集合的数据之外,也能数据进行删除操作:而Enumeration只能读取集合的数据,而不能对数据进行修改. Iterator支持fail-fast机制,而Enu ...
- Python openpyxl : Excel 文档简单操作
安装方法 使用 pip 或通过专门python IDE(如pyCharm)进行安装 其中pip安装方法,命令行输入: pip install openpyxl 基本使用 第一步先是要导入 openp ...
- NC 命令引用了一个高手的文章做收藏
什么是nc nc是netcat的简写,有着网络界的瑞士军刀美誉.因为它短小精悍.功能实用,被设计为一个简单.可靠的网络工具 nc的作用 (1)实现任意TCP/UDP端口的侦听,nc可以作为server ...
- oracle wm_concat 函数无法使用的情况下,使用LISTAGG()函数
http://dacoolbaby.iteye.com/blog/1698957 --20180327 重写wm_concat函数,解决行数超过上限问题 /*执行前请将APPS替换为当前登录用户*/ ...
- SpringBoot之常用注解
在spring boot中,摒弃了spring以往项目中大量繁琐的配置,遵循约定大于配置的原则,通过自身默认配置,极大的降低了项目搭建的复杂度.同样在spring boot中,大量注解的使用,使得代码 ...
- 学习STM32F769DK-OTA例程之APP中断向量表重映射
2019-04-17 [小记] APP的IAR工程中的中断向量表偏移是在系统库中的 __iar_program_start 处实现的 启动代码 stm32f769xx.s ;;;;;;;;;;;;;; ...
- Nginx与前端开发
Nginx与Node.js "Nginx是一款轻量级的HTTP服务器,采用事件驱动的异步非阻塞处理方式框架,这让其具有极好的IO性能,时常用于服务端的反向代理和负载均衡." 作为前 ...
- Educational Codeforces Round 63 (Rated for Div. 2) D. Beautiful Array(动态规划.递推)
传送门 题意: 给你一个包含 n 个元素的序列 a[]: 定义序列 a[] 的 beauty 为序列 a[] 的连续区间的加和最大值,如果全为负数,则 beauty = 0: 例如: a[] = {1 ...