Vue中不同组件之间传值方法

简单介绍

父组件:当组件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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值