现有一个需求如下
点击“存包记录”,出现弹窗(如下图) ,通过上图传过来的参数:订单id ,查询出来弹窗中的列表, 列表数据来自另一张表,与上图数据的表 关联)
数据库主要涉及两张表
涉及的主表(父组件)
关联的表(子组件:弹窗列表查询的数据来源)
我们可以看到:第二张表的外键是第一张表的主键。通过这两张表把图一页面的弹窗页面数据关联起来。
需求如上,现在开始梳理做该需求的思路:
把图一页面 看做父组件,点击按钮出现 的弹窗看做子组件
插入小知识点:
【1.什么是父子组件?
父子组件就是在一个vue文件中引入另一个vue文件,被引入vue文件就是子组件,引入vue文件的vue文件就是父组件。
比如图一列表中点击存包记录按钮弹窗,弹窗和图一列表 两者关系就是大组件中又定义了一个局部组件
】
贴出父组件部分关键代码 (图一中的表格)
<el-table v-loading="loading" :data="lockerList" @selection-change="handleSelectionChange" :row-class-name="rowClassName" border> <el-table-column type="selection" width="60" align="center" /> <el-table-column label="序号" type="index" width="60" align="center"> <template slot-scope="scope"> <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span> </template> </el-table-column> <el-table-column label="订单编号" width="200" align="center" prop="orderNo" /> <el-table-column label="设备编号" width="200" align="center" prop="deviceCode" /> <el-table-column label="设备名称" width="220" header-align="center" align="left" prop="deviceName" /> <el-table-column label="存包格位置" width="100" align="center" prop="storageLocation" /> <el-table-column label="绿道名称" width="250" header-align="center" align="left" prop="greenwayName" /> <el-table-column label="芯片编号" width="160" align="center" prop="chipNumber" /> <el-table-column label="存包人" width="120" align="center" prop="lockeruserName" /> <el-table-column label="存包时间" align="center" prop="lockerTime" width="180"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.lockerTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> </template> </el-table-column> <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-view" @click="storeRecords(scope.row)" >存包记录</el-button> </template> </el-table-column> </el-table>
弹窗html代码:
<!-- 存包记录--> <el-dialog :title="title" :visible.sync="storeRecordOpen" width="1400px" append-to-body > //:visible.sync="storeRecordOpen" 显示为弹窗 <LockerRecord :orderId="orderId"></LockerRecord> //LockerRecord是声明好的自定义组件 需要在js中声明 在html中这样使用 , :orderId 形式直接使用在data()中声明的 orderId 变量 <div style="margin-top:40px;margin-left: 1266px;" > <el-button @click="storeRecordOpen = false">关 闭</el-button> </div> </el-dialog>
“存包记录”作为一个按钮,加入点击事件。
在javascript 代码中
注: data()是一个html和js交互的 桥梁,变量在data()中定义了可以直接在html及javascript中 method方法 使用
components: {LockerRecord, }, //LockerRecord为自定义的一个组件。需要在js中声明
data() {
return {
orderId:'',
//存包记录窗口
storeRecordOpen:false, //弹窗层定义
},
storeRecords(row) {
this.orderId=row.orderId //row.orderId 是html表格中的传递过来的订单id, this.orderId是js 定义的订单id变量,需要在data()中声明一下。如上
this.storeRecordOpen=true; //显示弹窗
this.title="存包记录" //弹窗标题
},
以上文件都在父组件vue 及Js 定义,
但是子组件 列表数据如何来呢,如何与父组件挂钩呢?
1.父组件调用子组件
首先import 子组件名称 from 子组件地址,接着在components里面添加这个子组件名称,子组件就被调用了。
接着在需要这个子组件的地方,调用这个子组件就可以(如下图,注释“存包记录”下两行代码)
代码详解:
父组件vue中
子组件(弹窗页面)单独做一个vue文件
<template> <div class="app-container"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="98px"> </el-form> <el-table ref="tables" v-loading="loading" :data="list" border> <el-table-column label="序号" type="index" width="60" align="center"> <template slot-scope="scope"> <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span> </template> </el-table-column> <el-table-column label="设备编号" width="150" align="center" prop="deviceCode" /> <el-table-column label="设备名称" header-align="center" align="left" prop="deviceName" /> <el-table-column label="存包格位置" width="160" align="center" prop="storageLocation" /> <el-table-column label="存取时间" align="center" prop="lockerTime" width="250"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.lockerTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> </template> </el-table-column> <el-table-column label="存取操作" width="250" align="center" prop="lockerType" > <template slot-scope="scope"> <dict-tag :options="dict.type.locker_type" :value="scope.row.lockerType"/> </template> </el-table-column> </el-table> <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> </div> </template> <script> import { getRecord} from "@/api/order/locker/lockerRecord"; export default { name: "LockerRecords", dicts: ['locker_type'], props:['orderId'], data() { return { // 遮罩层 loading: true, // 导出遮罩层 exportLoading: false, newOrderId:'', // 选中数组 ids: [], // 非单个禁用 single: true, // 非多个禁用 multiple: true, // 显示搜索条件 showSearch: true, // 总条数 total: 0, // 表格数据 list: [], // 存包记录表格数据 recordList: [], // 弹出层标题 title: "", // 是否显示弹出层 open: false, // 查询参数 queryParams: { pageNum: 1, pageSize: 10, orderNo: null, deviceId: null, orderId: null, storageLocation: null, lockerTime: null, lockerType: null, }, // 表单参数 form: {}, // 表单校验 rules: { } }; }, created() { this.getList(); }, methods: { /** 查询存包记录列表 */ getList() { this.loading = true; getRecord(this.newOrderId).then( response => { this.list = response.rows; this.total = response.total; this.loading = false; }); }, }, watch: { //注 watch 与data 或method同层级,别把watch放入method中否则报错 orderId: { deep: true, immediate: true, // 监听到后,立即执行 handler方法 handler: function(newVal, oldVal) { this.newOrderId=newVal this.getList(); }, } } }; </script>
其中涉及 "watch进行监听" 知识点:
例子示范
watch会监听data中声明的某个属性:
<div> <p>FullName: {{fullName}}</p> <p>FirstName: <input type="text" v-model="firstName"></p> </div> new Vue({ el: '#root', data: { firstName: 'Dawei', lastName: 'Lou', fullName: '' }, watch: { firstName(newName, oldName) { this.fullName = newName + ' ' + this.lastName; } } })
上面的代码的效果是:当我们输入firstName
后,wacth
监听每次修改变化的新值,然后计算输出fullName
。
回到之前需求:
watch 是一个监听处理函数,
当每次监听到orderId值发生改变时,执行该函数。 handler:处理函数中 把 newVal赋值给了 newOrderId
在该vue data()中定义 一个newOrderId:'', 用来接收监听变化之后的参数:订单id ,并把这个新值作为参数通过getRecord函数传递给后台 查数据
当父组件向子组件动态传值时,子组件props首次获取到父组件传来得默认值时,也需要执行函数,此时就需要将immediate设为true.
子组件通过 js文件中 声明 props: ['orderId'], 拿到从父组件的传递过来的参数
import request from '@/utils/request'
// 查询存包订单详细
export function getRecord(orderId) {
return request({
url: '/order/record/getRecord/' + orderId, //把上面监测到的新值作为参数传给后台传值
method: 'get'
})
}
springboot 后台
前端把监听变化的参数传给后台,后台根据这个参数查出list
返回给前端,展示在页面上。
/** * 查询存包记录列表 */ @PreAuthorize("@ss.hasPermi('order:record:list')") @GetMapping(value = "getRecord/{orderId}") @ApiOperation(value = "查询存包记录列表", notes = "传入orderLockerRecord") public TableDataInfo<OrderLockerRecord> list(@PathVariable("orderId") Long orderId) { startPage(); List<OrderLockerRecord> list = orderLockerRecordService.selectOrderLockerRecordList(orderId); return getDataTable(list); //返回list }
查出来的list 返回给子组件的vue table中
这样呢 每点击一次图一的存包记录,会根据不同订单id,弹窗,并查出相应的关联表记录,并显示在弹窗中