简单介绍
父组件:当组件A中嵌套一个组件B时,组件A即为父组件
子组件:当组件A中嵌套一个组件B时,组件B即为子组件
兄弟组件:当组件C中嵌套了两个子组件,组件D和组件E;且组件D和组件E并不存在嵌套关系时,可以称组件D和组件E为兄弟组件
父组件传值给子组件
方式一:
父组件 EditCase.vue
<template>
<AddAndEditForm :productList="productList" :moduleList="moduleList" :versionList="versionList" pageTitle="编辑用例" ref="addAndEditFormObj" @childCaseFormEdit="childCaseFormEdit"/>
</template>
<script>
import AddAndEditForm from "./common/AddAndEditForm"
export default {
name: "EditCase",
components: {
AddAndEditForm
},
data(){
return {
visible: false,
productName: '',
modulePath: '',
moduleId: -1,
productList: [],
moduleList: [],
versionList: [],
rowRecord: {},
stepTableData: []
}
},
methods: {
showDrawer() {
// this.visible = true;
console.log("编辑页面的rowRecord:"+JSON.stringify(this.rowRecord))
this.$refs.addAndEditFormObj.rowRecord = this.rowRecord;
this.$refs.addAndEditFormObj.showDrawer();
//flag=1 代表添加 flag=2 代表更新/编辑 flag=3 代表添加
this.$refs.addAndEditFormObj.flag = 2;
},
getProductListByCurrentProduct(){
var _this = this;
this.axios
.get('/api/manualcase/findAllProductName',{
params: { product_name: _this.productName}
})
.then(function (response) {
console.log("Product"+response.data)
_this.productList = response.data;
});
},
getModuleListByCurrentProduct() {
var _this = this;
this.axios
.get('/api/manualcase/findAllModuleByProductNameAndModulesPath', {
params: {product_name: _this.productName, modules_path: _this.modulePath}
})
.then(function (response) {
console.log("Module:"+response.data)
_this.moduleList = response.data;
})
},
getVersionListByCurrentProduct(){
var _this = this;
this.axios
.get('/api/manualcase/findAllVersionByProductName',{
params: { product_name: _this.productName}
})
.then(function (response) {
console.log(response.data)
_this.versionList = response.data;
});
},
getAllStepsByManualCaseId(){
console.log("diaoyong;")
var _this = this;
this.axios
.get('/api/manualcase/findAllStepsOfOneCaseByManualCaseId',{
params: { manualcase_id: _this.rowRecord.id}
})
.then(function (response) {
console.log("用例步骤:"+JSON.stringify(response.data))
_this.stepTableData = response.data.data;
_this.$refs.addAndEditFormObj.data = _this.stepTableData;
})
},
childCaseFormEdit(flag){
console.log("编辑用例页")
this.$emit('childCaseForm', flag)
}
}
}
</script>
<style scoped>
</style>
子组件 AddAndEditForm.vue
在子组件中使用props接收父组件传递的值,props中存在的变量无需再次在data中声明,可直接使用。使用方式:this.props中变量名。
props中变量与data中声明的变量区别:
原则上props中的变量只可读,不可更改(不可写);data中的变量可读可写。
<template>
<a-drawer
:title="pageTitle"
:width="720"
@close="onClose"
:visible="visible"
:wrapStyle="{height: 'calc(100% - 108px)',overflow: 'auto',paddingBottom: '108px'}"
>
<a-form
id="components-form-demo-validate-other"
:form="form"
layout="vertical"
hideRequiredMark
v-bind="formItemLayout"
@submit="handleSubmit"
>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="所属产品" has-feedback>
<a-select
v-decorator="['productselect',{initialValue: productList[0], rules: [{ required: true, message: 'Please select product!' }] },]"
placeholder="Please select a product"
@change="handleSelectChange">
<a-select-option v-for="(item) in productList" :key="item" :value="item">{{ item }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="所属模块" has-feedback>
<a-select
v-decorator="['moduleselect',{initialValue: moduleList[0], rules: [{ required: true, message: 'Please select module!' }] },]"
placeholder="Please select a module"
@change="handleSelectChange">
<a-select-option v-for="(item) in moduleList" :key="item" :value="item">{{ item }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="版本号" has-feedback>
<a-select
v-decorator="['version',{initialValue: versionList[0], rules: [{ required: true, message: 'Please select version!' }] },]"
placeholder="Please select a version"
@change="handleSelectChange">
<a-select-option v-for="(item) in versionList" :key="item" :value="item">{{ item }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="用例类型" has-feedback>
<a-select
v-decorator="['type',{initialValue: rowRecord.type, rules: [{ required: true, message: 'Please select case type!' }] },]"
placeholder="Please select a case type"
@change="handleSelectChange">
<a-select-option value="功能测试">功能测试</a-select-option>
<a-select-option value="UI测试">UI测试</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="优先级" has-feedback>
<a-select
v-decorator="['priority',{initialValue: rowRecord.priority, rules: [{ required: true, message: 'Please select priority!' }] },]"
placeholder="Please select priority"
@change="handleSelectChange">
<a-select-option value="P1">P1</a-select-option>
<a-select-option value="P2">P2</a-select-option>
<a-select-option value="P3">P3</a-select-option>
<a-select-option value="P4">P4</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="自动化">
<a-switch checkedChildren="是" unCheckedChildren="否" v-decorator="['auto', {initialValue: auto, valuePropName: 'checked' }]"/>
</a-form-item>
</a-col>
</a-row>
<a-form-item label="前置条件">
<a-textarea :rows="4"
v-decorator="['preCondition',{initialValue: rowRecord.preCondition, rules: [{ required: true, message: 'Please select your country!' }] },]"></a-textarea>
</a-form-item>
<a-form-item label="用例标题">
<a-textarea :rows="4"
v-decorator="['title',{initialValue: rowRecord.title, rules: [{ required: true, message: 'Please select your country!' }] },]"></a-textarea>
</a-form-item>
<a-form-item label="用例步骤">
<div class="table-operations">
<a-button @click="handleAddOneStep">添加一行</a-button>
<!-- <a-button>删除一行</a-button>-->
</div>
<a-table :columns="columns" :dataSource="data" bordered rowKey="number" v-decorator="['steps']">
<template slot="description" slot-scope="text, record">
<editable-cell :text="text" @change="onCellChange(record.number, 'description', $event)"/>
</template>
<template slot="expect" slot-scope="text, record">
<editable-cell :text="text" @change="onCellChange(record.number, 'expect', $event)"/>
</template>
<template slot="action" slot-scope="text, record">
<a-popconfirm v-if="data.length" title="Sure to delete?" @confirm="() => onDelete(record.number)">
<a href="javascript:;">Delete</a>
</a-popconfirm>
</template>
</a-table>
</a-form-item>
<a-form-item :wrapper-col="{ span: 12}">
<a-button type="primary" html-type="submit">
Submit
</a-button>
</a-form-item>
</a-form>
</a-drawer>
</template>
<script>
import AFormItem from "ant-design-vue/es/form/FormItem";
import ACol from "ant-design-vue/es/grid/Col";
import EditableCell from '../../table/EditableCell.vue';
var stepId = 0;
const columns = [
{
title: '编号',
dataIndex: 'number',
key: 'number',
// slots: { title: 'customTitle' },
// scopedSlots: { customRender: 'name' },
},
{
title: '步骤',
dataIndex: 'description',
key: 'description',
scopedSlots: { customRender: 'description' },
},
{
title: '预期',
dataIndex: 'expect',
key: 'expect',
scopedSlots: { customRender: 'expect' },
},
{
title: '操作',
key: 'action',
scopedSlots: { customRender: 'action' },
}
]
export default {
name: "AddAndEditForm",
components: {ACol, AFormItem, EditableCell},
// 接受父组件的值
props: [
'productList',
'moduleList',
'versionList',
'pageTitle'
],
data: () => ({
visible: false,
productName: '',
modulePath: '',
moduleId: -1,
version: '',
formItemLayout: {
// labelCol: { span: 2 },
// wrapperCol: { span: 6 },
},
columns,
stepId,
data: [],
flag: 1,
auto: false,
rowRecord: {}
}),
beforeCreate() {
this.form = this.$form.createForm(this, {name: 'validate_other'});
},
methods: {
showDrawer() {
this.visible = true;
// this.data = this.rowRecord.steps;
console.log("stepdata:"+this.data)
this.moduleId = this.rowRecord.module_id;
console.log("record123:"+JSON.stringify(this.rowRecord),"auto: "+this.rowRecord.auto, " version:"+this.rowRecord.version)
if(this.rowRecord.auto === "Y"){
this.auto = true;
}else {
this.auto = false;
}
this.version = this.rowRecord.version;
},
onClose() {
this.visible = false;
},
onCellChange(key, dataIndex, value) {
console.log("编辑单元格:key="+key, " dataIndex="+dataIndex, " value="+value)
const data = [...this.data];
const target = data.find(item => item.number === key);
console.log("编辑单元格: target:"+JSON.stringify(target))
if (target) {
target[dataIndex] = value;
console.log("修改后的编辑单元格:"+JSON.stringify(target))
this.data = data;
}
},
onDelete(key) {
const data = [...this.data];
console.log("del before: "+JSON.stringify(this.data))
this.data = data.filter(item => {
if(item.number !== key){
if(item.number > key){
item.number -= 1;
}
return item;
}
});
console.log("del after: "+JSON.stringify(this.data))
},
updateNewManualCaseAndStep(formData){
console.log("formData: "+JSON.stringify(formData))
var _this = this
this.axios
.post('/api/manualcase/updateManualCaseAndStep', formData)
.then(function (response) {
console.log(response.data)
_this.$emit('childCaseFormEdit', true)
});
},
insertNewManualCaseAndStep(formData){
var _this = this
console.log("formData: "+JSON.stringify(formData))
this.axios
.post('/api/manualcase/insertNewManualCaseAndStep', formData)
.then(function (response) {
console.log(response.data)
_this.$emit('childCaseFormCopy', true)
_this.$emit('childCaseFormAdd', true)
});
},
handleAddOneStep(){
console.log("传递过来的data:"+this.data)
this.data = this.data || [];
this.stepId = this.data.length + 1;
var oneStep = {"number":this.stepId, "type": "step", "manualcase_id": 0, "description":" ", "expect":" ", "version":this.rowRecord.version};
this.data.push(oneStep)
},
handleSubmit(e) {
var _this = this;
e.preventDefault();
this.form.validateFields((err, values) => {
console.log("提交表单中的值:"+JSON.stringify(values))
if (!err) {
console.log('Received values of form: ', values);
console.log("_this.moduleID: "+_this.moduleId);
values['module_id'] = _this.moduleId;
values['id'] = _this.rowRecord.id;
values['creater'] = "孙东平"
if(values.auto){
values.auto = "Y"
}else {
values.auto = "N"
}
values['steps'] = _this.data;
// _this.insertNewManualCaseAndStep(values)
if(_this.flag === 2){
_this.updateNewManualCaseAndStep(values);
}else {
_this.insertNewManualCaseAndStep(values);
}
_this.onClose();
}
});
},
normFile(e) {
console.log('Upload event:', e);
if (Array.isArray(e)) {
return e;
}
return e && e.fileList;
},
handleSelectChange(value) {
console.log("下拉选择框change:" + value);
if(value.indexOf('/') > -1){
console.log("用例模块的下拉列表change:" + value);
}else if(value.indexOf('.') > -1){
console.log("版本号的下拉列表change:"+value)
this.version = value;
}
},
},
}
</script>
<style scoped>
#components-form-demo-validate-other .dropbox {
height: 180px;
line-height: 1.5;
}
</style>
方式二:
使用ref和$refs,父组件和子组件代码同方式一。其中,addAndEditFormObj代表自定义的子组件对象(名称随意);
<template>
<AddAndEditForm
:productList="productList" :moduleList="moduleList" :versionList="versionList" pageTitle="编辑用例"
ref="addAndEditFormObj"
@childCaseFormEdit="childCaseFormEdit"/>
</template>
接下来,还是在父组件中使用$refs;
- 父组件调用子组件中方法的使用格式:
this.$refs.自定义的子组件对象.子组件的methods中的某一方法; - 父组件给子组件中变量赋值的使用格式:
this.$refs.自定义的子组件对象.子组件的data中的某一变量 = 父组件中的某个值;
showDrawer() {
console.log("编辑页面rowRecord:"+JSON.stringify(this.rowRecord))
this.$refs.addAndEditFormObj.rowRecord = this.rowRecord;
this.$refs.addAndEditFormObj.showDrawer();
//flag=1 代表添加 flag=2 代表更新/编辑 flag=3 代表添加
this.$refs.addAndEditFormObj.flag = 2;
},
子组件传值给父组件
父组件 同上(截取代码片段)
<template>
<AddAndEditForm :productList="productList" :moduleList="moduleList" :versionList="versionList" pageTitle="编辑用例" ref="addAndEditFormObj" @childCaseFormEdit="childCaseFormEdit"/>
</template>
##methods中自定义一个监听事件的方法,方法名称同子组件中的@childCaseFormEdit="childCaseFormEdit"。
##注意:=前后的名称必须一致
childCaseFormEdit(flag)
{
console.log("编辑用例页")
}
子组件 同上(截取代码片段)
在子组件需要向父组件传递值的位置使用this.$emit(‘方法名’,参数)
##methods中的方法
updateNewManualCaseAndStep(formData){
console.log("formData: "+JSON.stringify(formData))
var _this = this
this.axios
.post('/api/manualcase/updateManualCaseAndStep', formData)
.then(function (response) {
console.log(response.data)
_this.$emit('childCaseFormEdit', true)
});
},
非父子组件间的传值
非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果。
公共bus.js
//bus.js
import Vue from 'vue'
export default new Vue()
组件A: child1.vue
<template>
<div>
A组件:
<span>{{elementValue}}</span>
<input type="button" value="点击触发" @click="elementByValue">
</div>
</template>
<script>
// 引入公共的bug,来做为中间传达的工具
import Bus from '../bus/bus.js'
export default {
name: "child1",
data () {
return {
elementValue: 4
}
},
methods: {
elementByValue: function () {
//重点代码:A组件将值传给B组件
Bus.$emit('val', this.elementValue)
}
}
}
</script>
<style scoped>
</style>
B组件:child2.vue
<template>
<div>
B组件:
<input type="button" value="点击触发" @click="getData">
<span>{{name}}</span>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data () {
return {
name: 0
}
},
mounted: function () {
var vm = this
// 用$on事件来接收A组件传给B组件的参数
Bus.$on('val', (data) => {
console.log(data)
vm.name = data
})
},
methods: {
getData: function () {
this.name++
}
}
}
</script>
参考链接:https://blog.csdn.net/lander_xiong/article/details/79018737