有么有前端大佬帮忙二开一个组件?

作者站长头像
站长
· 阅读数 4

这是组件地址:https://ext.dcloud.net.cn/plugin?id=13020二开功能:1:增加用户选中数据回显 我自己改了一点代码但是有问题 就放弃了有么有前端大佬帮忙二开一个组件?2:用户从a页面带数据过去回显有么有前端大佬帮忙二开一个组件?

回复
1个回答
avatar
test
2024-06-29

现在支持了 v-model 以及 选中回显,使用方式如下:

<cc-dropDownMenu v-model="value" :titleArr="titles" :dropArr="drops"></cc-dropDownMenu>
export default {
  data() {
    return {
      titles: ["区域", "户型", "面积", "价格"],
      drops: [
        // 区域
        [{
          text: "不限",
          value: ""
        }, {
          text: "荔湾区",
          value: "440103"
        }, {
          text: "越秀区",
          value: "440104"
        }, {
          text: "海珠区",
          value: "440105"
        }, {
          text: "天河区",
          value: "440106"
        }, {
          text: "白云区",
          value: "440111"
        }, {
          text: "花都区",
          value: "440114"
        }, {
          text: "从化区",
          value: "440117"
        }, {
          text: "南海区",
          value: "440605"
        }],
        // 户型
        [{
          text: "不限",
          value: ""
        }, {
          text: "单间",
          value: "10000"
        }, {
          text: "一房一厅",
          value: "11000"
        }, {
          text: "两房一厅",
          value: "21000"
        }, {
          text: "三房一厅",
          value: "31000"
        }, {
          text: "四房两厅",
          value: "42000"
        }],
        // 面积
        [{
          text: "不限",
          value: ""
        }, {
          text: "≤40㎡",
          value: "0-40"
        }, {
          text: "40-60㎡",
          value: "40-60"
        }, {
          text: "60-80㎡",
          value: "60-80"
        }, {
          text: "80-100㎡",
          value: "80-100"
        }, {
          text: "100-120㎡",
          value: "100-120"
        }, {
          text: "≥120㎡",
          value: "120-99999"
        }],
        // 租金
        [{
          text: "不限",
          value: ""
        }, {
          text: "≤1000元",
          value: "0-1000"
        }, {
          text: "1000-1500元",
          value: "1000-1500"
        }, {
          text: "1500-2000元",
          value: "1500-2000"
        }, {
          text: "2000-3000元",
          value: "2000-3000"
        }, {
          text: "3000-4000元",
          value: "3000-4000"
        }, {
          text: "≥4000元",
          value: "4000-99999"
        }]
      ],
      value: []
    };
  }
};

改造代码如下:

<template>
  <view class="dropdown-menu">
    <view class="screen-bar" :style="{height: `${height}rpx`, backgroundColor: bgcolor}">
      <view v-for="(item, index) in innerTitleArr"
            :key="index"
            class="screen-bar-item"
            :style="[barItemStyle(item, index)]"
            @tap.stop="itemClick(index)">
        <view class="bar-item-text">{{ item }}</view>
        <image :src="arrBase64" :style="{'transform': `rotate(${show && currentIndex === index ? 180 : 0}deg)`}"></image>
      </view>

      <view class="dropdown-box"
            :style="{bottom: `-${itemHeight * maxDropdownLength}rpx`, height: `${itemHeight * maxDropdownLength}rpx`, backgroundColor: bgcolor, opacity: show ? '1' : '0', display: show ? 'block' : 'none'}">
        <scroll-view class="dropdown-box__scroller" scroll-y>
          <view v-for="(item, index) in dropArr[currentIndex]"
                :key="index"
                class="dropdown-item"
                :style="[dropdownItemStyle(item)]"
                @tap.stop="subItemClick(item)">
            {{ item[showTag] }}
          </view>
        </scroll-view>
      </view>
    </view>

    <view class="bg-mask" :class="{'bg-mask-show': show}" @tap="maskClose" @touchmove="touchControl"></view>
  </view>
</template>

<script>
export default {
  props: {
    value: {
      type: Array,
      default: () => {
        return [];
      }
    },
    //下拉标题数组
    titleArr: {
      type: Array,
      default: () => {
        return [];
      }
    },
    //下拉选项数组(二维数组)
    dropArr: {
      type: Array,
      default: () => {
        return [];
      }
    },
    // 筛选条高度(rpx)
    height: {
      type: Number,
      default: 92
    },
    // 下拉单项高度
    itemHeight: {
      type: Number,
      default: 88
    },
    // 当前文字活跃颜色
    activeColor: {
      type: String,
      default: "#0377fc"
    },
    //背景颜色
    bgcolor: {
      type: String,
      default: "#ffffff"
    },
    // item数量超过多少开始滚动
    maxItemCount: {
      type: Number,
      default: 6
    },
    // 选项左偏移
    itemPadding: {
      type: Number,
      default: 24
    },
    // 能否遮罩关闭
    maskTouch: {
      type: Boolean,
      default: true
    },
    // 是否需要选择后替换标题
    isNeedChangeTitle: {
      type: Boolean,
      default: true
    },
    // 标题字号
    barFontSize: {
      type: Number,
      default: 26
    },
    //标题颜色
    barTextColor: {
      type: String,
      default: "#666666"
    },
    //下拉字号
    itemFontSize: {
      type: Number,
      default: 26
    },
    // 下拉文字颜色
    itemTextColor: {
      type: String,
      default: "#666666"
    },
    // 需要展示的字段,比如你的数据是item.name 这里填的就是name
    showTag: {
      type: String,
      default: "text"
    },
    // 是否要滑动关闭
    isTouchPrevent: {
      type: Boolean,
      default: true
    },
    // 自定义事件的索引数组
    customIndexArr: {
      type: Array,
      default: () => {
        return [];
      }
    }
  },
  data() {
    return {
      innerValue: [],
      show: false,
      // 主条目选择序列
      currentIndex: 0,
      arrBase64: "data:image/png;base64,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"
    };
  },
  computed: {
    innerTitleArr() {
      const { innerValue, isNeedChangeTitle, titleArr, dropArr, showTag } = this;

      if (!isNeedChangeTitle) {
        return titleArr;
      }

      return innerValue.map((item, index) => {
        const title = titleArr[index];

        if (item == null) {
          return title;
        }

        return dropArr[index].find((it) => it.value === item)?.[showTag] ?? title;
      });
    },
    maxDropdownLength() {
      return this.dropArr[this.currentIndex].length > this.maxItemCount ? this.maxItemCount : this.dropArr[this.currentIndex].length;
    }
  },
  watch: {
    value: {
      handler(value) {
        const { titleArr } = this;

        const array = new Array(titleArr.length).fill(null);

        for (const [index, item] of Object.entries(value)) {
          array[index] = item;
        }

        this.innerValue = array;
      },
      immediate: true
    }
  },
  methods: {
    barItemStyle(item, index) {
      const { titleArr, show, currentIndex, activeColor, barTextColor, barFontSize } = this;

      return {
        width: `${100 / titleArr.length}%`,
        color: (show && currentIndex === index) ? activeColor : barTextColor,
        fontSize: `${barFontSize}rpx`
      };
    },
    dropdownItemStyle(item) {
      const { innerValue, currentIndex, itemHeight, itemPadding, itemFontSize, activeColor, itemTextColor } = this;

      const current = innerValue[currentIndex];

      return {
        height: `${itemHeight}rpx`,
        paddingLeft: `${itemPadding}rpx`,
        color: item.value === current ? activeColor : itemTextColor,
        fontSize: `${itemFontSize}rpx`
      };
    },
    itemClick(index) {
      if (this.customIndexArr.includes(index)) {
        this.show = false;
        this.$emit("customClick", {
          "$index": index
        });
        return;
      }

      if (this.currentIndex === index) {
        this.show = !this.show;
      } else {
        this.currentIndex = index;
        this.show = true;
      }
    },
    subItemClick(item) {
      this.innerValue.splice(this.currentIndex, 1, item.value);

      this.$emit("finishDropClick", this.innerValue);
      this.$emit("input", this.innerValue);

      this.show = false;
    },
    maskClose() {
      if (!this.maskTouch) {
        return;
      }
      this.show = false;
    },
    touchControl() {
      if (this.isTouchPrevent) {
        this.maskClose();
      }
    }
  }
};
</script>

<style>
.screen-bar {
  position: relative;
  z-index: 99;
  display: flex;
  width: 100%;
}

.screen-bar::after {
  content: "";
  position: absolute;
  bottom: -1rpx;
  left: 0;
  z-index: 99;
  width: 100%;
  height: 1rpx;
  background-color: #eeeeee;
}

.screen-bar-item {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

.screen-bar-item image {
  display: block;
  flex-shrink: 0;
  width: 24rpx;
  height: 24rpx;
  margin-left: 12rpx;
  transition: all .3s;
}

.dropdown-box {
  position: absolute;
  left: 0;
  z-index: 99;
  width: 100%;
  overflow: hidden;
}

.dropdown-box__scroller {
  height: 100%;
}

.dropdown-item {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 0 30rpx;
  color: #111111;
  font-size: 26rpx;
  border-bottom: 1rpx solid #eeeeee;
  box-sizing: border-box;
}

.bg-mask {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 98;
  background: rgba(0, 0, 0, 0.3);
  transition: all 0.3s ease-in-out;
  opacity: 0;
  visibility: hidden;
}

.bg-mask-show {
  visibility: visible;
  opacity: 1;
}

.bar-item-text {
  max-width: 120rpx;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}
</style>
另外,以后再有二开需求建议付费咨询,而不是直接伸手~
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容