现有一个需求如下

 

 

 

 

 

 

 

 

点击“存包记录”,出现弹窗(如下图) ,通过上图传过来的参数:订单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,弹窗,并查出相应的关联表记录,并显示在弹窗中