无需在vue中单击即可将数据从子组件传递到父组件
pass data from child component to parent component without any click in vue
我有一个父组件ChangeInfo,里面有一个子组件ShowWorkInfo。在 ShowWorkInfo 组件中,我有几个输入表单来更新工作信息。我创建了一个变量 work_info ,它是一个对象,然后将 v-model 用于其中的字段。但是我不知道如何让父组件从子组件获取数据。我的子组件中没有任何按钮,我将尝试使用父组件中的按钮处理来自 WorkInfo 的数据。这是我的代码。我是否应该直接写入 ChangeInfo 而不将其拆分为子组件
ChangeInfo(父组件)
export default class ChangeInfo extends Vue {
public isUpdated: boolean = false
updateWorkInfo(workInfo: any) {
if (
workInfo.company == '' ||
workInfo.department == '' ||
workInfo.position == '' ||
workInfo.postcode == '' ||
workInfo.prefectures == '' ||
workInfo.municipality == '' ||
workInfo.address == '' ||
workInfo.building == '' ||
workInfo.phone_number == '' ||
workInfo.url == ''
) {
alert('完全な情報を入力してください')
this.isUpdated = false
} else {
axios
.put('https://609b82962b549f00176e394f.mockapi.io/work_info/1', {
status: workInfo.status,
company: workInfo.company,
department: workInfo.department,
position: workInfo.position,
postcode: workInfo.postcode,
prefectures: workInfo.prefectures,
municipality: workInfo.municipality,
address: workInfo.address,
building: workInfo.building,
phone_number: workInfo.phone_number,
url: workInfo.url
})
.then(response => {
workInfo = response.data
console.log(workInfo)
InformationModule.CHANGE_WORK_INFO(workInfo)
})
.catch(error => console.log(error))
this.isUpdated = false
workInfo.status = false
workInfo.company = ''
workInfo.department = ''
workInfo.position = ''
workInfo.postcode = ''
workInfo.prefectures = ''
workInfo.municipality = ''
workInfo.address = ''
workInfo.building = ''
workInfo.phone_number = ''
workInfo.url = ''
}
}
updatePersonalInfo(personalInfo: any) {
if (
personalInfo.nearest_station == '' ||
personalInfo.postcode == '' ||
personalInfo.prefectures == '' ||
personalInfo.municipality == '' ||
personalInfo.address == '' ||
personalInfo.building == '' ||
personalInfo.phone_number == '' ||
personalInfo.url == ''
) {
alert('完全な情報を入力してください')
this.isUpdated = false
} else {
axios
.put('https://609b82962b549f00176e394f.mockapi.io/personal_info/1', {
gender: personalInfo.gender,
nearest_station: personalInfo.nearest_station,
postcode: personalInfo.postcode,
prefectures: personalInfo.prefectures,
municipality: personalInfo.municipality,
address: personalInfo.address,
building: personalInfo.building,
phone_number: personalInfo.phone_number,
url: personalInfo.url
})
.then(response => {
personalInfo = response.data
console.log(personalInfo)
InformationModule.CHANGE_PERSONAL_INFO(personalInfo)
})
.catch(error => console.log(error))
this.isUpdated = false
personalInfo.gender = false
personalInfo.nearest_station
personalInfo.postcode = ''
personalInfo.prefectures = ''
personalInfo.municipality = ''
personalInfo.address = ''
personalInfo.building = ''
personalInfo.phone_number = ''
personalInfo.url = ''
}
}
triggerSubmit() {
this.isUpdated = true
}
我这样调用两个函数
<template>
<div class="d-block">
<ShowProfile />
<ShowWorkInfo :isUpdated="isUpdated" @update-work-info="updateWorkInfo" />
<ShowPersonalInfo
:isUpdated="isUpdated"
@update-personal-info="updatePersonalInfo"
/>
<div class="w--27 mw-100 mx-auto my-9">
<button
@click="triggerSubmit"
v-b-modal="'update-success'"
class="btn btn-primary w-100"
>
{{ $t('common.btn.btn_update') }}
</button>
</div>
<ModalUpdateSuccess />
</div>
</template>
嗯...有多种方法可以做到这一点:
- 快速而肮脏:
从父组件传递另一个 prop 到组件,当
common.btn.btn_update
被按下时,这将被设置为 true,在 updateWorkInfo
函数中,你在子组件中为这个 prop 设置一个观察者,当这个pro 更改为 true,您执行 emit('submitted', data)
,这会将数据发送到您的父组件,然后仅在父组件中将此事件作为提交事件处理。在行动:
//#region Parent script
import {
Component,
Vue
} from 'vue-property-decorator'
import ShowWorkInfo from './Components/ShowWorkInfo.vue'
import ModalUpdateSuccess from '@/components/Modal/ModalUpdateSuccess.vue'
@Component({
components: {
ShowWorkInfo,
ModalUpdateSuccess
}
})
export default class ChangeInfo extends Vue {
private isFormSubmitted: boolean = false;
private validationMessage: string = '';
updateWorkInfo(workInfo) {
console.log('recieved workinfo: ', workInfo);
const { isFormValid, validationMessage } = await validateForm(workInfo);// function that validates your data, and returns a message and a boolean.
if(!isFormValid) { //if form is not valid, you have to set the variable that triggers
//the submit to false so the child component can set it to true and trigger submit once again
this.isFormSubmitted = false;
this.validationMessage = validationMessage;
return;
}
//...data handling logic and stuff... you can make the PUT request here, or anuy other data related action
}
triggerSubmit() {
//this triggers the watch in the child component
this.isFormSubmitted = true;
}
}
//# endRegion Parent script
//# region Child script
@Component({
components: {
Title
}
//the prop
props: {
isFormSubmitted: {
default: false,
type: boolean,
},
}
})
export default class ShowWorkInfo extends Vue {
private showWorkInfo: boolean = false
private workInfo: any = { ...
}
//watch for change (you can also put it in a computed if it does not trigger change)
watch: {
isFormSubmitted: function(newValue) {
if (newValue) {
console.log('form-submitted', this.workInfo)
emit('form-submitted', this.workInfo);
}
}
}
}
//#endRegion Child script
现在我不太喜欢这种方法...但它确实有效,正是您想要的!
- 传统上:您会在子组件中拥有提交按钮并发出提交的事件以及数据,这种方法更好、更可重用:
#region Parent script
@Component({
components: {
ShowWorkInfo,
ModalUpdateSuccess
}
})
export default class ChangeInfo extends Vue {
updateWorkInfo(workInfo) {
console.log('recieved workinfo: ', workInfo);
//...data handling logic and stuf...
}
}
ShowWorkInfo (child component)
#endRegion Parent script
#region Child script
@Component({
components: {
Title
}
})
export default class ShowWorkInfo extends Vue {
private showWorkInfo: boolean = false
private workInfo: any = { ... }
//watch for change (you can also put it in a computed if it does not trigger change)
submitForm() {
console.log('submit form: ', this.workInfo);
//you could also validate the form at this point and dont emit unti the data is valid
this.$emit('form-submitted', this.workInfo);
}
}
#endRegion Child script
<!-- parent template -->
<template>
<div class="d-block">
<ShowWorkInfo @form-submitted="updateWorkInfo"/>
<ModalUpdateSuccess />
</div>
</template>
<!-- parent template end -->
<!-- child template -->
<template>
<div class="form">
<!-- your form fields -->
<div class="w--27 mw-100 mx-auto my-9">
<button
@click="submitForm"
v-b-modal="'update-success'"
class="btn btn-primary w-100"
>
{{ $t('common.btn.btn_update') }}
</button>
</div>
</div>
</template>
<!-- child template end -->
注意 1:如果我误用了这些变量和 this,我深表歉意,因为我不熟悉这个版本的 Vue 和打字稿,而且我已经有一年没有接触过 vue.2,但概念保持不变,基本上我只是想向您展示如何使用 vue 提供的功能的方法,上面的代码远非完美,但我认为它说明了您的问题的用途和答案。
注意2:还有很多方法可以做到这一点,如果你对它们感兴趣请告诉我。以上两种方式是我见过最常见的
更新:第一个块中的表单验证。试一试,这是一个整体的表单验证。
免责声明:如果您想逐个字段验证,那将非常困难,建议您将提交逻辑移至您的子组件。
正如我所说,这可能不是最佳做法。我的想法是,如果您没有按钮并且我们想将信息发送到我们的父组件,我们可以使用 watch 和 v-model with lazy。
这是一个小例子,与您的代码无关。
子组件:
<template>
<div class="hello">
<input type="text" placeholder="Enter something" v-model.lazy="myObj.message">
<input type="text" placeholder="Enter something" v-model.lazy="myObj.name">
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String
},
data () {
return {
myObj : {
message:"",
name : ""
}
}
},
watch: {
myObj : {
handler (newVal) {
this.$emit('change', newVal)
},
deep: true
}
}
};
</script>
父组件:
<template>
<div id="app">
<HelloWorld @change="change"/>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
components: {
HelloWorld
},
methods: {
change (obj) {
console.log(obj)
}
}
};
</script>
控制台将在您单击外部输入后记录您的消息。如果我们不使用 v.model.lazy 那么只要输入发生变化,它就会发送这样的数据。你可以试一试,看看是否有效。
编辑:我添加了 deep:true 来观看整个对象。现在在父组件中你实际上可以 console.log(obj.name) 或 (obj.message)
我有一个父组件ChangeInfo,里面有一个子组件ShowWorkInfo。在 ShowWorkInfo 组件中,我有几个输入表单来更新工作信息。我创建了一个变量 work_info ,它是一个对象,然后将 v-model 用于其中的字段。但是我不知道如何让父组件从子组件获取数据。我的子组件中没有任何按钮,我将尝试使用父组件中的按钮处理来自 WorkInfo 的数据。这是我的代码。我是否应该直接写入 ChangeInfo 而不将其拆分为子组件
ChangeInfo(父组件)
export default class ChangeInfo extends Vue {
public isUpdated: boolean = false
updateWorkInfo(workInfo: any) {
if (
workInfo.company == '' ||
workInfo.department == '' ||
workInfo.position == '' ||
workInfo.postcode == '' ||
workInfo.prefectures == '' ||
workInfo.municipality == '' ||
workInfo.address == '' ||
workInfo.building == '' ||
workInfo.phone_number == '' ||
workInfo.url == ''
) {
alert('完全な情報を入力してください')
this.isUpdated = false
} else {
axios
.put('https://609b82962b549f00176e394f.mockapi.io/work_info/1', {
status: workInfo.status,
company: workInfo.company,
department: workInfo.department,
position: workInfo.position,
postcode: workInfo.postcode,
prefectures: workInfo.prefectures,
municipality: workInfo.municipality,
address: workInfo.address,
building: workInfo.building,
phone_number: workInfo.phone_number,
url: workInfo.url
})
.then(response => {
workInfo = response.data
console.log(workInfo)
InformationModule.CHANGE_WORK_INFO(workInfo)
})
.catch(error => console.log(error))
this.isUpdated = false
workInfo.status = false
workInfo.company = ''
workInfo.department = ''
workInfo.position = ''
workInfo.postcode = ''
workInfo.prefectures = ''
workInfo.municipality = ''
workInfo.address = ''
workInfo.building = ''
workInfo.phone_number = ''
workInfo.url = ''
}
}
updatePersonalInfo(personalInfo: any) {
if (
personalInfo.nearest_station == '' ||
personalInfo.postcode == '' ||
personalInfo.prefectures == '' ||
personalInfo.municipality == '' ||
personalInfo.address == '' ||
personalInfo.building == '' ||
personalInfo.phone_number == '' ||
personalInfo.url == ''
) {
alert('完全な情報を入力してください')
this.isUpdated = false
} else {
axios
.put('https://609b82962b549f00176e394f.mockapi.io/personal_info/1', {
gender: personalInfo.gender,
nearest_station: personalInfo.nearest_station,
postcode: personalInfo.postcode,
prefectures: personalInfo.prefectures,
municipality: personalInfo.municipality,
address: personalInfo.address,
building: personalInfo.building,
phone_number: personalInfo.phone_number,
url: personalInfo.url
})
.then(response => {
personalInfo = response.data
console.log(personalInfo)
InformationModule.CHANGE_PERSONAL_INFO(personalInfo)
})
.catch(error => console.log(error))
this.isUpdated = false
personalInfo.gender = false
personalInfo.nearest_station
personalInfo.postcode = ''
personalInfo.prefectures = ''
personalInfo.municipality = ''
personalInfo.address = ''
personalInfo.building = ''
personalInfo.phone_number = ''
personalInfo.url = ''
}
}
triggerSubmit() {
this.isUpdated = true
}
我这样调用两个函数
<template>
<div class="d-block">
<ShowProfile />
<ShowWorkInfo :isUpdated="isUpdated" @update-work-info="updateWorkInfo" />
<ShowPersonalInfo
:isUpdated="isUpdated"
@update-personal-info="updatePersonalInfo"
/>
<div class="w--27 mw-100 mx-auto my-9">
<button
@click="triggerSubmit"
v-b-modal="'update-success'"
class="btn btn-primary w-100"
>
{{ $t('common.btn.btn_update') }}
</button>
</div>
<ModalUpdateSuccess />
</div>
</template>
嗯...有多种方法可以做到这一点:
- 快速而肮脏:
从父组件传递另一个 prop 到组件,当
common.btn.btn_update
被按下时,这将被设置为 true,在updateWorkInfo
函数中,你在子组件中为这个 prop 设置一个观察者,当这个pro 更改为 true,您执行emit('submitted', data)
,这会将数据发送到您的父组件,然后仅在父组件中将此事件作为提交事件处理。在行动:
//#region Parent script
import {
Component,
Vue
} from 'vue-property-decorator'
import ShowWorkInfo from './Components/ShowWorkInfo.vue'
import ModalUpdateSuccess from '@/components/Modal/ModalUpdateSuccess.vue'
@Component({
components: {
ShowWorkInfo,
ModalUpdateSuccess
}
})
export default class ChangeInfo extends Vue {
private isFormSubmitted: boolean = false;
private validationMessage: string = '';
updateWorkInfo(workInfo) {
console.log('recieved workinfo: ', workInfo);
const { isFormValid, validationMessage } = await validateForm(workInfo);// function that validates your data, and returns a message and a boolean.
if(!isFormValid) { //if form is not valid, you have to set the variable that triggers
//the submit to false so the child component can set it to true and trigger submit once again
this.isFormSubmitted = false;
this.validationMessage = validationMessage;
return;
}
//...data handling logic and stuff... you can make the PUT request here, or anuy other data related action
}
triggerSubmit() {
//this triggers the watch in the child component
this.isFormSubmitted = true;
}
}
//# endRegion Parent script
//# region Child script
@Component({
components: {
Title
}
//the prop
props: {
isFormSubmitted: {
default: false,
type: boolean,
},
}
})
export default class ShowWorkInfo extends Vue {
private showWorkInfo: boolean = false
private workInfo: any = { ...
}
//watch for change (you can also put it in a computed if it does not trigger change)
watch: {
isFormSubmitted: function(newValue) {
if (newValue) {
console.log('form-submitted', this.workInfo)
emit('form-submitted', this.workInfo);
}
}
}
}
//#endRegion Child script
现在我不太喜欢这种方法...但它确实有效,正是您想要的!
- 传统上:您会在子组件中拥有提交按钮并发出提交的事件以及数据,这种方法更好、更可重用:
#region Parent script
@Component({
components: {
ShowWorkInfo,
ModalUpdateSuccess
}
})
export default class ChangeInfo extends Vue {
updateWorkInfo(workInfo) {
console.log('recieved workinfo: ', workInfo);
//...data handling logic and stuf...
}
}
ShowWorkInfo (child component)
#endRegion Parent script
#region Child script
@Component({
components: {
Title
}
})
export default class ShowWorkInfo extends Vue {
private showWorkInfo: boolean = false
private workInfo: any = { ... }
//watch for change (you can also put it in a computed if it does not trigger change)
submitForm() {
console.log('submit form: ', this.workInfo);
//you could also validate the form at this point and dont emit unti the data is valid
this.$emit('form-submitted', this.workInfo);
}
}
#endRegion Child script
<!-- parent template -->
<template>
<div class="d-block">
<ShowWorkInfo @form-submitted="updateWorkInfo"/>
<ModalUpdateSuccess />
</div>
</template>
<!-- parent template end -->
<!-- child template -->
<template>
<div class="form">
<!-- your form fields -->
<div class="w--27 mw-100 mx-auto my-9">
<button
@click="submitForm"
v-b-modal="'update-success'"
class="btn btn-primary w-100"
>
{{ $t('common.btn.btn_update') }}
</button>
</div>
</div>
</template>
<!-- child template end -->
注意 1:如果我误用了这些变量和 this,我深表歉意,因为我不熟悉这个版本的 Vue 和打字稿,而且我已经有一年没有接触过 vue.2,但概念保持不变,基本上我只是想向您展示如何使用 vue 提供的功能的方法,上面的代码远非完美,但我认为它说明了您的问题的用途和答案。
注意2:还有很多方法可以做到这一点,如果你对它们感兴趣请告诉我。以上两种方式是我见过最常见的
更新:第一个块中的表单验证。试一试,这是一个整体的表单验证。 免责声明:如果您想逐个字段验证,那将非常困难,建议您将提交逻辑移至您的子组件。
正如我所说,这可能不是最佳做法。我的想法是,如果您没有按钮并且我们想将信息发送到我们的父组件,我们可以使用 watch 和 v-model with lazy。
这是一个小例子,与您的代码无关。
子组件:
<template>
<div class="hello">
<input type="text" placeholder="Enter something" v-model.lazy="myObj.message">
<input type="text" placeholder="Enter something" v-model.lazy="myObj.name">
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String
},
data () {
return {
myObj : {
message:"",
name : ""
}
}
},
watch: {
myObj : {
handler (newVal) {
this.$emit('change', newVal)
},
deep: true
}
}
};
</script>
父组件:
<template>
<div id="app">
<HelloWorld @change="change"/>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
components: {
HelloWorld
},
methods: {
change (obj) {
console.log(obj)
}
}
};
</script>
控制台将在您单击外部输入后记录您的消息。如果我们不使用 v.model.lazy 那么只要输入发生变化,它就会发送这样的数据。你可以试一试,看看是否有效。
编辑:我添加了 deep:true 来观看整个对象。现在在父组件中你实际上可以 console.log(obj.name) 或 (obj.message)