vue2 通过父组件props子组件动态添加响应数据

238 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

这是一个动态添加数据的bug

这是一个公共组件,通过传递参数的不同创建不同的参数信息列表

this.loading[this.row.name.replace(/\s+/g, "")] = false; this.identifying[this.row.name.replace(/\s+/g, "")] = { currentPage: 1, dataList: [], pageSize: 20, };

这里创建完后修改属性修改不了因为创建的对象不是响应式的数据,所以需要借助set属性进行动态添加数据

this.$set(this.loading, this.row.name.replace(/\s+/g, ""), false); this.$set(this.identifying, this.row.name.replace(/\s+/g, ""), { currentPage: 1, dataList: [], pageSize: 20, });

row.name === 'Manufacturer' 这个推荐用计算属性,考虑到后面会集中使用,所以判断条件可以放到计算属性里面

identifying: {}, // 下拉所有选项表格 通过传递的参数动态添加下拉表格属性,虽然数据嵌套比较多,但是后续有些属性值需要前端可以把判断改一下,不用在代码里面写入很多的属性和属性判断

<template>
  <div class="part-attr-editing">
    <!-- 下拉单选 -->
        <el-select
          v-if="row.name === 'Manufacturer'"
          v-model="row.editingValue"
          v-scroll-select="(e) => remoteMethod(e, row.name, 'scroll')"
          filterable
          clearable
          remote
          reserve-keyword
          placeholder=""
          :remote-method="(e) => remoteMethod(e, row.name)"
          :loading="loading[row.name.replace(/\s+/g, '')]"
        >
          <el-option
            v-for="item in identifying[row.name.replace(/\s+/g, '')].dataList"
            :key="item.id"
            :label="item.manufacturerName"
            :value="item.manufacturerName"
          >
          </el-option>
        </el-select>
        <div v-else>
            {{row.name}}
        </div>
  </div>
</template>

<script>
import { getCategoryStruct, manufacturerPageSearch } from "../../model/index.js";
// 接口
export default {
  name: "PartAttrEditing",
  // 局部指令
  directives: {
    "scroll-select": {
      // 指令的名称
      bind(el, binding) {
        const SELECTWRAP = el.querySelector(".el-select-dropdown .el-select-dropdown__wrap");
        SELECTWRAP.addEventListener("scroll", function () {
          // scrollTop 这里可能因为浏览器缩放存在小数点的情况,导致了滚动到底部时
          // scrollHeight 减去滚动到底部时的scrollTop ,依然大于clientHeight 导致无法请求更多数据
          // 这里将scrollTop向上取整 保证滚到底部时,触发调用
          const CONDITION = this.scrollHeight - Math.ceil(this.scrollTop) <= this.clientHeight;
          // el.scrollTop !== 0 当输入时,如果搜索结果很少,以至于没看到滚动条,那么此时的CONDITION计算结果是true,会执行bind.value(),此时不应该执行,否则搜索结果不匹配
          if (CONDITION && this.scrollTop !== 0) {
            const Elvalue = el.querySelector(".el-input__inner") || el.querySelector(".el-select__input");
            binding.value(Elvalue.value);
          }
        });
      },
    },
  },
  props: {
    row: {
      type: Object,
      required: true,
    }
  },
  data() {
    return {
      loading: {}, // 加载状态 下拉所有选项表格
      identifying: {}, // 下拉所有选项表格
    };
  },
  mounted() {
    // 特定的属性值创建下拉加载
    if (this.row.name === "Manufacturer") {
      // /\s+/g去掉空格
      // 为什么建空数据要用set,请看上面详述
      this.$set(this.loading, this.row.name.replace(/\s+/g, ""), false);
      this.$set(this.identifying, this.row.name.replace(/\s+/g, ""), {
        currentPage: 1,
        dataList: [],
        pageSize: 20,
      });
    }
    // 下次要加下拉框可以共用一个select
    // else if (this.row.name === "AEC Number") {
    //   this.loading[this.row.name.replace(/\s+/g, "")] = false;
    //   this.identifying[this.row.name.replace(/\s+/g, "")] = {
    //     currentPage: 1,
    //     dataList: [],
    //     pageSize: 20,
    //   };
    // }
  },
  methods: {
    async remoteMethod(val, name, scroll) {
      // 下拉加载
      if (scroll === "scroll") {
        if (name === "Manufacturer") {
          this.loading[name.replace(/\s+/g, "")] = true;
          const res = await manufacturerPageSearch.post({
            // 每次下拉加一
            currentPage: this.identifying[name.replace(/\s+/g, "")].currentPage + 1,
            pageSize: 10,
            name: val,
            isBlacklist: 0,
          });
          if (res.data && res.data.resultCode === "WL-0000") {
            // 添加数组
            this.$set(this.identifying, name.replace(/\s+/g, ""), {
              currentPage: res.data.resultData.currentPage,
              dataList: this.identifying[name.replace(/\s+/g, "")].dataList.concat(res.data.resultData.dataList),
              pageSize: 20,
            });
          }
          this.loading[name.replace(/\s+/g, "")] = false;
        }
      } else {
        // 模糊搜索
        if (name === "Manufacturer") {
          this.loading[name.replace(/\s+/g, "")] = true;
          const res = await manufacturerPageSearch.post({
            currentPage: 1,
            pageSize: 10,
            name: val,
            isBlacklist: 0,
          });
          if (res.data && res.data.resultCode === "WL-0000") {
            this.identifying[name.replace(/\s+/g, "")] = res.data.resultData;
          }
          this.loading[name.replace(/\s+/g, "")] = false;
        }
      }
    },
  },
};
</script>

这个可以做个案例 父组件for循环遍历组件传递参数动态添加属性, mounted里面打印可以看一下