Parent component – Manifest page (note: the manifest page is also a child component, see the example figure)

<template>
  <div id="engineeringList">
    <transition name="screening-box">
      <div class="screening-box" v-show="options.isShow" @click.stop="setShow">
        <! -- -->
        <div
          class="screening-box"
          v-show="options.isShow"
          @click.stop="setShow"
        >
          <transition name="screening">
            <div class="screening" v-if="options.isShow" @click.stop>
              <! - the head -- -- >
              <div class="screening-header">{{ options.editMode == "edit" ? "Edit quantities" : "View quantities list"}}<i
                  class="ifca-iconfont ifca-icon-gengduo-left"
                  @click="setShow"
                ></i>
              </div>
              <div class="box-content">
                <! -- Middle content -->
                <div
                  class="content-class"
                  v-for="(item, i) in options.dataSource"
                  :key="i"
                  @click.stop="editClick(item, i)"
                >
                  <div
                    class="projectlist"
                    v-if="item.dataRowState ! = 'Deleted'"
                  >
                    <div class="projectTitle">
                      <div class="left">Bill of Quantities {{I + 1}}</div>
                      <i
                        v-if="options.editMode ! = 'view'"
                        class="right iconfont icon-lajixiang"
                        @click.stop="deleteClick(item, i)"
                      ></i>
                    </div>
                    <div class="projectContent">
                      <div class="contentOne">
                        <span class="titleColor">Content:</span>
                        <span>{{ item.content }}</span>
                      </div>
                      <div class="contentTwo">
                        <div class="subtitle">
                          <span class="titleColor">Units:</span>
                          <span>{{ item.unitOfMeasurement }}</span>
                        </div>
                        <div class="subtitle">
                          <span class="titleColor">Quantity:</span>
                          <span>{{ item.quantities }}</span>
                        </div>
                      </div>
                      <div class="contentTwo">
                        <div class="subtitle">
                          <span class="titleColor">The unit price:</span>
                          <span>{{ item.comprehensiveAmt }}</span>
                        </div>
                        <div class="subtitle">
                          <span class="titleColor">The total price:</span>
                          <span>{{ item.sumComprehensiveAmt }}</span>
                        </div>
                      </div>
                      <div class="contentTwo">
                        <div class="subtitle">
                          <span class="titleColor">Rate:</span>
                          <span>{{ item.taxTotalAmtName.key }}</span>
                        </div>
                        <div class="subtitle">
                          <span class="titleColor">Tax:</span>
                          <span>{{ item.taxRate }}</span>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
                <! -- Add list -->
                <div
                  class="addJect"
                  @click="addClick"
                  v-if="options.editMode ! = 'view'"
                >
                  <span class="icon">+</span>
                  <span>Add bill of quantities</span>
                </div>
              </div>

              <! -- Bottom button -->
              <div class="button-box">
                <div
                  class="buttonClass defaultButtonClass"
                  @click="buttonClick('cancel')"
                >Shut down</div>
                <div
                  class="buttonClass primaryButtonClass"
                  @click="buttonClick('save')"
                  v-if="options.editMode ! = 'view'"
                >save</div>
              </div>
            </div>
          </transition>
        </div>
      </div>
    </transition>

    <! -- Added bottom slider to project list -->
    <engineeringEdit
      v-if="engineeringEditOptions.isShow"
      :options="engineeringEditOptions"
      @callBack="formCallBack"
    ></engineeringEdit>
  </div>
</template>

<script>
import engineeringEdit from "./engineeringEdit";
export default {
  components: {
    engineeringEdit,
  },
  props: {
    // Accept the value from the parent component
    options: {
      type: Object.default: {
        isShow: false.// Note that the editMode attribute has two values:
        // "view" cannot be added or deleted
        // "edit" can be added, modified or deleted
        editMode: "view".// dataSource Specifies the list data
        dataSource[],},},},data() {
    return {
      // Data passed to child components
      engineeringEditOptions: {
        isShow: false.item: {},},engineeringEditIndex: -1.listData: []}; },created() {
     // Deep copy data to listData
    this.listData = JSON.parse(JSON.stringify(this.options.dataSource))
  },
  methods: {
    setShow() {
      this.options.isShow = !this.options.isShow;
    },

    /** * button click event * type: cancel; Save save * /
    buttonClick(type) {
      if (type == "save") {
        this.$emit("callBack".JSON.stringify(this.listData));
      }
      this.setShow();
    },
    /** * click add Project list event */
    addClick() {
      // reset the subscript
      this.engineeringEditIndex = -1;
      // Format the data
      this.engineeringEditOptions.item = {
        // dataRowState Specifies new data by default
        dataRowState: "Added".content: "".unitOfMeasurement: "".quantities: "".comprehensiveAmt: "".sumComprehensiveAmt: 0.taxTotalAmt: 0.taxTotalAmtName: {},
        taxRate: 0};this.engineeringEditOptions.isShow = true;
    },
    // Add callback (save and modify save is a callback, according to engineeringEditIndex)
    formCallBack(formData) {
      let dataList = JSON.parse(formData);
      // As long as engineeringEditIndex is not -1, it changes the data!
      // Replace the dataList from the subcomponent with options.dataSource.
      // The data is pushed directly to the options.dataSource
      if (this.engineeringEditIndex > -1) {
        this.listData[this.engineeringEditIndex] = dataList;
      } else {
        this.listData.push(dataList); }},/ / delete
    deleteClick(item, index) {
      // Delete new data
      if (item.dataRowState == "Added")
        this.listData.splice(index, 1);
      else {
        item.dataRowState = "Deleted"; }},/ / edit
    editClick(item, i) {
      // Record the subscript of the currently edited data, so that the original data can be directly replaced after editing
      this.engineeringEditIndex = i;
      // If dataRowState == "Unchanged", change the dataRowState to changed state
      if (item.dataRowState == "Unchanged") item.dataRowState = "Modified";
      this.engineeringEditOptions.item = item;
      this.engineeringEditOptions.isShow = true; ,}}};</script>

<style scoped lang="less"></style>

Copy the code

Subcomponents (adding and modifying pages)

<template>
  <div id="engineeringEdit">
    <ifca-popup-balck
      v-model="options.isShow"
      @on-show="onShow"
      @on-hide="onHide"
      maxHeight="90%"
      :headerShow="true"
      head-title="New Bill of Quantities"
      @on-click-left="show = false"
    >
      <div class="formContent">
        <! - form - >
        <ifca-form @submit="submit" :formItem="formItem">
          <ifca-form-cell
            title=Content:"
            v-model="formData.content"
            :required="true"
            :input="true"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
          ></ifca-form-cell>
          <ifca-form-cell
            title="Unit:"
            v-model="formData.unitOfMeasurement"
            :required="true"
            :input="true"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
          ></ifca-form-cell>
          <ifca-form-cell
            title="Quantity:"
            v-model="formData.quantities"
            :required="true"
            inputType="number"
            :input="true"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
            name="myUnit"
            @on-change="numberChange"
          ></ifca-form-cell>
          <ifca-form-cell
            title="Unit Price:"
            v-model="formData.comprehensiveAmt"
            :required="true"
            inputType="number"
            :input="true"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
            name="myUnit"
            @on-change="numberChange"
          ></ifca-form-cell>
          <ifca-form-cell
            title="Total price:"
            v-model="formData.sumComprehensiveAmt"
            inputType="number"
            :input="false"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
            name="myUnit"
          ></ifca-form-cell>
          <ifca-form-radio
            title="Tax rate:"
            v-model="formData.taxTotalAmtName"
            name="Rate"
            :required="true"
            placeholder="Please select tax rate"
            :list="taxRateList"
            @on-change="taxRateChange"
          ></ifca-form-radio>
          <ifca-form-cell
            title="Tax:"
            v-model="formData.taxRate"
            :input="false"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
            name="myUnit"
          ></ifca-form-cell>
        </ifca-form>
        <! -- Button info -->
        <div class="button-box">
          <div class="buttonClass defaultButtonClass" @click="closelClick()">Shut down</div>
          <div class="buttonClass primaryButtonClass" @click="confirmClick()">confirm</div>
        </div>
      </div>
    </ifca-popup-balck>
  </div>
</template>

<script>
import { calculationAmt } from "@/assets/js/formatData.js";
export default {
  props: {
    // Accept the value from the parent component
    options: {
      type: Object.default: {
        isShow: false.editMode: "view".item: {
          dataRowState: "Added".content: "".unitOfMeasurement: "".quantities: "".comprehensiveAmt: "".sumComprehensiveAmt: 0.taxTotalAmt: 0.taxTotalAmtName: {},
          taxRate: 0,},},},},data() {
    return {
      / / rate
      taxRateList: [].// Form data
      formData: {}}; },created() {
    this.getTaxData();
    // Attention!! Here, when the component is opened, the options.item data is given to formData to display!
    this.formData = JSON.parse(JSON.stringify(this.options.item));
  },
  methods: {
    onShow() {},
    onHide() {},
    / / close
    closelClick() {
      this.options.isShow = false;
    },
    / / confirm
    confirmClick() {
      if (!this.checkData()) {
        return;
      }
      console.log(1111.this.formData);
      this.options.isShow = false;
      // Pass the value to the parent component
      this.$emit("callBack".JSON.stringify(this.formData));
    },
    // Form validation
    checkData() {
      if (!this.formData.content) {
        this.messageAlert("Content cannot be empty.");
        return false;
      }
      if (!this.formData.unitOfMeasurement) {
        this.messageAlert("Units can't be empty.");
        return false;
      }
      if (!this.formData.quantities) {
        this.messageAlert("Work quantity cannot be empty.");
        return false;
      }
      if (!this.formData.comprehensiveAmt) {
        this.messageAlert("Unit price cannot be empty");
        return false;
      }
      if (!this.formData.taxTotalAmtName.value) {
        this.messageAlert("Please select tax rate");
        return false;
      }
      return true;
    },
    messageAlert(content) {
      $ifcaPopup.tips({ content: content, time: 1500}); ,}}};</script>

<style scoped lang="less"></style>
Copy the code

Each operation (add, modify, delete) will add the corresponding state to the data, which will tell the background this list of data is added or modified or deleted!!

Fourth, sample diagram