vue三级联动组件

发布于:2024-05-21 ⋅ 阅读:(156) ⋅ 点赞:(0)

背景

  • 项目中经常出现三级下拉框组件的要求,这种组件其中一级发生变化,子级的组件就会发生变化
  • 如果这一个组件,单独作为搜索条件使用,很好写,同时作为搜索条件和form回写组件,回显就比较困难

子组件代码

  • 将与父组件通信的属性定义在props中: 在这里插入图片描述
  • 定义三个handler处理值的变化 ,同时绑定在对应下拉框
    在这里插入图片描述
  • 对于prop的值,不可以直接在子组件中修改,只能通知父组件修改

在这里插入图片描述

  • 有时候子组件的根性有延迟,导致出现问题,可以使用父组件传递过来的值,或者使用next函数
    在这里插入图片描述
<script>
import {getSonMenuList} from "@/api/maintain/classfiy";

export default {
  name: "costClassify",
  props: {
    proProcedureId: Number,
    costElementId: Number,
    costPartitionId: Number,
  },
  data() {
    return {
      proProcedureList: [],
      costElementList: [],
      costPartitionList: [],
    };
  },
  watch: {},
  methods: {
    proProcedureIdHandler(value) {
      this.$emit('update:proProcedureId', value);

      this.costElementList = []
      // this.costElementId = null  避免这种操作 不要在子组件中直接修改prop的值, 一般来说,prop是不应该被修改的,它是父组件传递给子组件的数据,子组件应该保持对prop只读,不应该修改它的值。
      // 如果一定要修改,可以通过$emit事件的方式,通知父组件修改prop的值,再通过prop的值的变化,来触发子组件的重新渲染。
      this.costElementIdHandler(null)

      if (!value) {
        return
      }

      getSonMenuList(value).then((response) => {
        this.costElementList = response.data
      })
    },
    costElementIdHandler(value) {
      this.$emit('update:costElementId', value);

      this.costPartitionList = []
      // this.costPartitionId = null

      // 通知外层
      this.costPartitionIdHandler(null)

      if (!value) {

        return
      }
      getSonMenuList(value).then((response) => {
        this.costPartitionList = response.data
      })

    },
    costPartitionIdHandler(value) {
      this.$emit('update:costPartitionId', value);
      if (!value) {
        return
      }

    },
    // 初始化
    init() {
      console.log('costClassify init')
      console.log(this)
      // 获取一级目录  生产工序
      getSonMenuList(-1).then((response) => {
        this.proProcedureList = response.data
      })
      // 如果是打开的编辑页面  自带参数  需要初始化
      if (this.proProcedureId) {
        this.proProcedureIdHandler(this.proProcedureId)
      }
      if (this.costElementId) {
        this.costElementIdHandler(this.costElementId)
      }
      if (this.costPartitionId) {
        this.costPartitionIdHandler(this.costPartitionId)
      }
    },
    refresh(proProcedureId, costElementId, costPartitionId) {
      this.$nextTick(() =>{
        console.log('costClassify refresh')
        // 获取一级目录  生产工序
        getSonMenuList(-1).then((response) => {
          this.proProcedureList = response.data
        })
        // 如果是打开的编辑页面  自带参数  需要初始化
        if (proProcedureId) {
          getSonMenuList(proProcedureId).then((response) => {
            this.costElementList = response.data
          })
        }
        if (costElementId) {
          console.log('三级列表执行'+costElementId)
          getSonMenuList(costElementId).then((response) => {
            this.costPartitionList = response.data
          })
          console.log('三级列表执行成功')
        }
        if (costPartitionId) {

        }
      })

    }
  },
  mounted() {
    console.log('costClassify mounted')
    this.init()
  },
};

</script>

<template>
  <span>
    <el-form-item label="生产工序" prop="proProcedureId">
      <el-select v-model="proProcedureId" placeholder="请输入生产工序" clearable size="mini"
                 @change="proProcedureIdHandler">
        <el-option v-for="proProcedure in proProcedureList" :key="proProcedure.id" :label="proProcedure.name"
                   :value="proProcedure.id"/>
      </el-select>
    </el-form-item>
    <el-form-item label="成本要素" prop="costElementId">
      <el-select v-model="costElementId" placeholder="请输入成本要素" clearable size="mini"
                 @change="costElementIdHandler">
        <el-option v-for="costElement in costElementList" :key="costElement.id" :label="costElement.name"
                   :value="costElement.id"/>
      </el-select>
    </el-form-item>
    <el-form-item label="费用细分" prop="costPartitionId">
      <el-select v-model="costPartitionId" placeholder="请输入费用细分" clearable size="mini"
                 @change="costPartitionIdHandler">
        <el-option v-for="costPartition in costPartitionList" :key="costPartition.id" :label="costPartition.name"
                   :value="costPartition.id"/>
      </el-select>
    </el-form-item>
  </span>
</template>

<style scoped lang="scss">

</style>

父组件调用

  • refs获取子组件的引用
  • 第一次的时候子组件没有渲染完毕,找不到refresh函数,要使用nextTick延迟调用
/** 修改按钮操作 */
handleUpdate(row) {
  this.reset();
  const id = row.id || this.ids
  this.form = Object.assign({}, row);
  this.open = true;
  this.editFlag = true;
  this.title = "修改月度费用";
  console.log(this.form.proProcedureId, this.form.costElementId, this.form.costPartitionId)
  this.$nextTick(() => {
    this.$refs.costClassifyRef.refresh(this.form.proProcedureId, this.form.costElementId, this.form.costPartitionId);
  })
},

网站公告

今日签到

点亮在社区的每一天
去签到