当前位置: 首页 > 知识库问答 >
问题:

前端 - 为什么vue2+antdv render()创建下拉框滚动事件绑定不生效?

钮出野
2023-08-10

项目中有许多form表单提交,前辈就封装了一个组件
使用动态render()函数创建表单,对antdv 组件进行二次封装
上代码
----------------------------------正常界面,

<template>  <page-header-wrapper :title="false">    <div class="add-frame-list" style="height: 100%;">      <div class="add-frame">        <span class="title">{{ supplier_id? $t("edit")+$t('supplier') : $t("plus")+$t('supplier') }}</span>      </div>      <div class="content">        <form-container          v-if="Object.values(dictObj).length > 0"          :formParams="productInfo"          :dictObj="dictObj"          ref="formContainer"        ></form-container>        <div class="action-button">          <a-button type="primary" @click="saveData">{{ $t('save') }}</a-button>        </div>      </div>    </div>  </page-header-wrapper></template><script>import FormContainer from "@/views/common/components/FormContainer.vue";import { dictAPI } from "@/utils/dict.js";import industrialEnt from "@/mixin/industrialEnt.js";export default {  mixins: [industrialEnt],  components: {    FormContainer  },  data() {    let that = this;    return {      productInfo: {        industry_id: {          category: "customer-select",          value: undefined,          title: "产业",          require: true,          isUserDefind: true,          teledata: true,          params: {            options: []          },          events: {            change(value) {              that.changeIndustry(value,'这里正常触发,change事件');            },            popupScroll(value) {              console.log(value,'问题就在这,这里是不会触发的,我要在这里使用滚动事件,下拉框数据很多,足够触发这滚动事件');            },          }        },        ent_id: {          category: "customer-select",          value: undefined,          title: "企业",          require: true,          isUserDefind: true,          teledata: true,          params: {            options: []          },          events: {            change(value) {              // console.log(value, "***************");            }          }        }      },      dictObjCopy: {},      supplier_id: ""    };  },  computed: {    dictObj() {      if (this.industryList.length > 0 && this.industryEntList.length > 0) {        return {          ...this.dictObjCopy,          industry_id: this.dealDict(this.industryList, [            "industry_id",            "industry_name",            "org_id"          ]),          ent_id: this.dealDict(this.industryEntList, [            "ent_id",            "ent_name",            "model_class_id"          ])        };      } else {        return {};      }    }  },  created() {    this.getDict();  },  methods: {    dealDict(arr, list) {      return arr.map(item => {        return {          dic_key: item[list[0]],          dic_v1: item[list[1]],          dic_type_id: item[list[2]]        };      });    },    async getDict() {      let res = await dictAPI(["project_type_id"]);      this.dictObjCopy = res;    },  }};</script>

--------------------------- FormContainer 表单 组件

<template>  <a-form-model    :class="coverDefineClass"    ref="formContainer"    :layout="layout"    :model="formParams"    :hideRequiredMark="true"  >    <a-form-model-item      v-for="(node, name) in formParams"      :key="name"      :prop="`${name}.value`"      v-show="!node.isHiddenCurItem"      :rules="addRules(node)"      :class="{ 'holder-one-row': node.holderOneRow }"    >      <label v-if="(node.title ?node.title: '') !== ''" :title="node.title" slot="label">        {{ node.title }}        <span v-if="node.unit">({{ node.unit }})</span>        <span class="user-defind-required" v-if="node.require">*</span>      </label>      <FormsDistribution        v-bind="node"        v-model="node.value"        :class="{ 'is-view-state': isViewModel }"      ></FormsDistribution>    </a-form-model-item>  </a-form-model></template><script>import FormsDistribution from "./FormsDistribution.vue";import getTeledata from "@/utils/getTeledata";import { dealDict } from "@/utils/dict.js";let computedValueFn = null;export default {  name: "FormContainer",  components: {    FormsDistribution  },  watch: {    formParams: {      deep: true,      handler(val) {        if (!this.needComputedValue || !computedValueFn) return;        // 当需要有计算值时 计算当前功能        computedValueFn.bind(val)();      }    },    isViewModel() {      this.setViewModel();    }  },  props: {    // 序列化参数    formParams: {      type: Object,      default() {        return {};      },      required: true    },    dictObj: {      type: Object    },    // 排列方式,同Ant form 表单    layout: {      type: String,      default: "vertical"    },    // 需要计算值    needComputedValue: {      type: Boolean,      default: false    },    // 覆盖当前默认样式    coverDefineClass: {      type: String,      default: "user-defind-form"    },    // 切换至查看转态    isViewModel: {      type: Boolean,      default: false    }  },  watch: {    dictObj: {      deep: true,      handler(val, oldVal) {        this.dealObject();      }    }  },  created() {},  mounted() {    this.dealObject();  },  methods: {    dealObject() {      // 当需要远程数据填充表单数据      // 则执行相关操作      Object.keys(this.formParams).forEach(name => {        const item = this.formParams[name];        if (item.teledata) {          item.params.options = dealDict(this.dictObj[name]);        }        // 计算出当前是否有计算函数        if (item.computedValue) {          computedValueFn = item.computedValue;        }        // 如果当前为查看转态,则将每个表单置为disabled        if (this.isViewModel) {          this.setViewModel();        }      });    },    // 设置当前为查看状态,当为查看状态是,所有输入表单为不显示    setViewModel() {      Object.keys(this.formParams).forEach(name => {        const item = this.formParams[name];        if (!item.params) {          item.params = {};        }        item.params.disabled = this.isViewModel;      });    },    addRules(node) {      const temp = [];      if (node.require) {        temp.push({          required: true,          message: `${node.title}不能为空!`,          trigger: ["change", "blur"]        });      }      // 另外添加的规则      if (node.extendRule) {        temp.push(...node.extendRule);      }      return temp;    },    // 清空或填入当前表单内的数据    handleCurInputValue(rowData) {      return {        setData: () => {          Object.keys(this.formParams).forEach(name => {            this.formParams[name].value = rowData[name];          });        },        clearAllData: () => {          Object.keys(this.formParams).forEach(name => {            this.formParams[name].value = "";          });        }      };    },    // 输出当前键值对以及extraParams中额外参数数据JSON数据需要的字段    outputSaveFormater() {      let temp = {};      Object.keys(this.formParams).forEach(name => {        const node = this.formParams[name];        temp[name] = node.value;        // 如果有额外参数,直接转入传参结构数据中        if (node.extraParams) {          temp = { ...temp, ...node.extraParams };        }      });      return temp;    },    // 校验所有需要检验的数据    validAllData() {      return new Promise((resolve, reject) => {        this.$refs.formContainer.validate(valid => {          if (valid) {            const data = this.outputSaveFormater();            resolve(data);          } else {            reject(false);          }        });      });    },    // 清空所有表单内的数据    resetFormValue() {      this.$refs.formContainer.resetFields();    },    // 校验单列表单    triggerOneColumn(name) {      this.$refs.formContainer.validateField(`${name}.value`);    }  }};</script><style lang="less" scoped>.user-defind-required {  color: #f5222d;  font-family: SimSun, sans-serif;}// 查看转态下的样式.is-view-state {  background-color: #fafafa;  color: rgba(0, 0, 0, 0.85);  border: 0;  cursor: text;  /deep/ .ant-input.ant-input-disabled {    border: 0;    color: rgba(0, 0, 0, 0.85);    cursor: text;  }  /deep/ .ant-cascader-picker-arrow {    display: none;  }  /deep/ .ant-calendar-range-picker-input {    cursor: text;  }}</style>

------------------------- FormsDistribution 这个是创建组件rander函数

<!-- 根据传入表单类型,派发一个ant表单 --><script>// import Vue from "vue";export default {  name: "functionalComponents",  functional: true,  props: {    value: undefined,    category: {      type: String,      default: "",      required: true    },    params: {      type: Object,      default() {        return {};      }    },    events: {      type: Object,      default: () => {}    }  },  // a-input组件,需明确指明functional的绑定事件为 change.value  model: {    prop: "value",    // 这里好像不影响,无论怎么写好像都不对    // event: "change.value", // 最原始只有这行代码    // events: ["change","popupScroll"]  // 这行代码为了测试添加的,不生效  },  render(h, context) {    const { props, data, children, scopedSlots,listeners } = context;    console.log(props.events, data.on,'props.events 是可以输出我绑定的popupScroll 函数,但是不执行**********');    let tempParams = props.params;    // 添加上自定义事件    data.on = { ...data.on, ...props.events };    // console.log(data.on,'最终data。on 也是有我绑定的 popupScroll 函数了,是不执行的 **********');    // 如果为自定义组件,遵从预定数据格式传参,则转换prop参数类型    if ((tempParams.placeholder ?? "") === "") {      const labelTxt = props.category.match(/(select|cascader)/g)        ? "选择"        : "输入";      tempParams.placeholder = `请${labelTxt}${data.attrs.title}`;    }    if (data.attrs.isUserDefind) {      tempParams = { params: tempParams };    }    return h(      props.category,      {        ...data,        props: tempParams,        listeners,        scopedSlots      },      children    );  }};</script>

各位大佬们求指教 为什么我创建出来的下拉框,无法正确执行滚动事件,而同样创建出来的change就能触发
因为代码是前辈写的,而且找不到人,我自己对rander()也不熟悉,求指教,已经一天了,如果在无法解决,我就得 在 FormContainer 表单 组件 中手动写各种输入框了
求大佬指教

共有1个答案

焦博实
2023-08-10
<template>  <a-select v-model="selectedValue" @dropdownVisibleChange="handleDropdownVisibleChange">    <template #dropdownRender="{ menu }">      <div @scroll="handleScroll">        {{ menu }}      </div>    </template>    <a-select-option value="option1">Option 1</a-select-option>    <a-select-option value="option2">Option 2</a-select-option>     </a-select></template><script>export default {  data() {    return {      selectedValue: null    };  },  methods: {    handleDropdownVisibleChange(visible) {      if (visible) {        this.$nextTick(() => {          const dropdownMenu = document.querySelector('.ant-select-dropdown-menu');          if (dropdownMenu) {            dropdownMenu.addEventListener('scroll', this.handleScroll);          }        });      }    },    handleScroll(event) {      console.log('滚动事件触发', event);      // 处理滚动事件    }  }};</script>
 类似资料:
  • <van-pull-refresh v-model="isLoading" :style="{ height }" success-text="刷新成功" @refresh="onRefresh"> height 在 activated 里修改了一次后,页面并没有监听到变化,为什么?

  • 本文向大家介绍下拉框select的绑定示例,包括了下拉框select的绑定示例的使用技巧和注意事项,需要的朋友参考一下 根据文本绑定text 根据值绑定value

  • 问题内容: 在6.2章的CSS PositionedLayout Module Level(工作草案)中。粘性定位我们有以下定义:(强调我的) 甲粘粘定位的盒类似地定位到一个相对定位的盒子,但计算参考最近的祖先与偏移 滚动框 ,或者如果没有祖先具有视口 滚动框 。 这些滚动框是什么? 在文档的更下方,有一个关于术语的问题 问题6 粘性定位应真正根据最接近的可滚动祖先定义,但是CSS中其他地方目前没

  • 我已经在我的页面上实现了平滑滚动条,它的工作相当不错,但我也想在滚动内容中添加一些过渡效果。基本上,我想在一个滚动事件上做这件事,但我不知道scrollbar的工作有多流畅,以及在滚动事件上执行什么对象。我检查了#my-scrollbar没有执行此操作: 滚动事件的原因是什么?或者有没有其他的方法可以做一些额外的效果而不检查滚动事件? 编辑:我正在粘贴我的代码(我正在使用react.js)来进行更

  • 我有一个vanilla javascript系统在下拉菜单上触发“更改”事件: 它可以通过addEventListener()或$('select').on()完美地处理事件,但如果.on()函数被设置为目标动态元素,它就不起作用了: 我错过了什么?

  • 这个对象里的属性个数和key都是未知的