Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

news2025/6/12 17:09:37

使用详解

Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。

核心特性与用法

基本属性

  • v-model:绑定右侧列表的值(key数组)

  • data:组件数据源,需包含 key 和 label 属性

  • props:配置数据源的字段别名

  • filterable:是否启用搜索功能

  • titles:自定义左右两侧标题

  • button-texts:自定义按钮文本

  • left-default-checked/right-default-checked:设置默认选中项

关键事件

  • change:当右侧列表变化时触发

  • left-check-change:左侧选中项变化时触发

  • right-check-change:右侧选中项变化时触发

插槽

  • 默认插槽:自定义列表项内容

  • left-footer/right-footer:自定义左右列表底部内容

filter-method 用法详解

1. 基本概念

filter-method 是 Element Plus Transfer 组件的一个属性,用于自定义穿梭框的搜索过滤逻辑。它接受一个函数,该函数有两个参数:

  • query: 用户输入的搜索关键词

  • item: 当前遍历的数据项

函数应返回布尔值:

  • true: 保留该项

  • false: 过滤掉该项

default 插槽用法详解

1. default 插槽基础用法

default 插槽允许完全自定义每个列表项的显示内容:

html

复制

下载

运行

<el-transfer>
  <template #default="{ option }">
    <!-- 自定义内容 -->
    <div>{{ option.label }}</div>
  </template>
</el-transfer>

使用示例

MaterialApplyDialog.vue

<script setup lang="ts" name="MaterialApplyDialog">
import { ref } from "vue";

// 模态框显示标识
const dialogVisible = ref(false);
interface Option {
  key: number;
  label: string;
  disabled: boolean;
}

const generateData = () => {
  const data: Option[] = [];
  for (let i = 1; i <= 500; i++) {
    data.push({
      key: i,
      label: `Option${i}`,
      disabled: i % 4 === 0
    });
  }
  return data;
};

const data = ref<Option[]>(generateData());
const value = ref([]);

// 打开模态框
const openDialog = async () => {
  dialogVisible.value = true;
};

// 隐藏模态框
const closeDialog = () => {
  dialogVisible.value = false;
};

// 过滤方法
const filterMethod = (keywords: string, item: Option) => {
  // 默认的过滤方法,使用关键字与选项对象的label属性进行匹配
  // return item.label.toLowerCase().includes(keywords.toLowerCase());

  // 自定义过滤方法,搜索以关键字结尾的选项,区分大小写
  return item.label.endsWith(keywords);
};

// 确定
const onConfirmClick = async () => {
  // 关闭模态框
  closeDialog();
};

defineExpose({
  openDialog
});
</script>

<template>
  <el-dialog
    class="receive-dialog"
    title="穿梭框应用示例"
    width="1200px"
    top="0vh"
    style="border-radius: 10px"
    v-model="dialogVisible"
    :close-on-press-escape="true"
    :close-on-click-modal="false"
    :show-close="true"
    @close="closeDialog">
    <template #default>
      <el-container class="container">
        <el-transfer
          class="custom-transfer"
          v-model="value"
          :data="data"
          :titles="[`待选内容`, `已选内容`]"
          :button-texts="[`移除`, `添加`]"
          :filterable="true"
          :filter-placeholder="`请输入关键字搜索以其结尾的内容`"
          :filter-method="filterMethod" />
      </el-container>
    </template>
    <template #footer>
      <div>
        <el-button class="dialog-btn" type="primary" @click="onConfirmClick">确定</el-button>
        <el-button class="dialog-btn" @click="closeDialog">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style scoped lang="scss">
/* 穿梭框容器样式 */
.container {
  width: 100%;
  height: 80vh;
}
/* 穿梭框样式 - 已通过 Element Plus v2.7.4 测试 */
.custom-transfer {
  flex: 1;
  display: flex;
  justify-content: space-between; /* 首尾元素贴边,中间元素等距 */
  /* 面板样式 */
  :deep(.el-transfer-panel) {
    /**
    如果所在容器没有设置justify-content: space-between; 又需要穿梭框占满容器,
    需通过浏览器调试工具,获取到穿梭框容器宽度为1168px,按钮区域占用200px,则面板宽度应该设置为 (1168-200)/2 = 484px,
    如果所在容器已经设置justify-content: space-between; 又需要穿梭框占满容器,面板宽度可以不用精细计算
     */
    width: 450px;
    height: 100% !important;
    display: flex;
    flex-direction: column;
  }
  /* 面板头部样式 */
  :deep(.el-transfer-panel__header) {
    background-color: #d3e2f1;
    display: flex;
  }
  /* 面板主体 */
  :deep(.el-transfer-panel__body) {
    flex: 1;
    display: flex;
    flex-direction: column;
  }
  /* 列表区域 - 关键滚动区域 */
  :deep(.el-transfer-panel__list) {
    flex: 1;
    overflow-y: auto;
  }
  /* 按钮区域样式 */
  :deep(.el-transfer__buttons) {
    display: flex;
    flex-direction: row; /* 水平排列 */
    justify-content: center; /* 水平居中 */
    align-items: center; /* 垂直居中 */
    padding: 0 10px;
  }
  /* 按钮样式 */
  :deep(.el-transfer__buttons .el-button) {
    margin: 0 10px;
    width: 70px;
    padding: 8px 15px;

    /* 蓝色渐变背景 */
    // background: linear-gradient(135deg, #409eff 0%, #3375b9 100%);
    // border: none;
    // color: white;
    // box-shadow: 0 2px 5px rgba(64, 158, 255, 0.3);
  }
  /* 按钮方向指示 */
  :deep(.el-transfer__buttons .el-button:first-child::after) {
    content: "<=";
  }
  :deep(.el-transfer__buttons .el-button:last-child::after) {
    content: "=>";
  }
  /* 按钮文字提示 */
  :deep(.el-transfer__buttons .el-button span) {
    display: none; /* 隐藏按钮文字 */
  }
}
.dialog-btn {
  width: 100px;
}
</style>

应用效果:

项目实例

MaterialApplyDialog.vue

特点:

1、自定义过滤方法 filter-method

2、数据项属性别名 props

3、插槽 default

4、插槽 left-footer

5、输入框控制数字输入

6、遍历数组元素检查数据合法性,聚焦元素,全选元素内容

7、结合实际情况调整样式

<script setup lang="ts" name="ReagentApplyDialog">
import { branchWarehouseApplyGenerateForReagentService } from "@/api/branchWarehouse";
import { useReagentOptionList } from "@/hooks/useReagentOptionList";
import { formatToNumber } from "@/utils/formatter";
import { Search } from "@element-plus/icons-vue";
import type { TransferInstance } from "element-plus";
import { ElMessage } from "element-plus";
import { debounce } from "lodash-es";
import { nextTick, ref } from "vue";
import type { IReagentOption } from "../types";

// 模态框显示标识
const dialogVisible = ref(false);
// 试剂选项列表,组合式函数 hook
const { reagentOptionList, fetchReagentOptionList, resetReagentOptionData } = useReagentOptionList();
// 搜索内容
const searchVal = ref("");
// 已选试剂id集合
const selectedOptionIds = ref<number[]>([]);
// 穿梭框实例对象
const transferRef = ref<TransferInstance | null>(null);

// 打开模态框
const openDialog = async () => {
  initPageData();
  await nextTick();
  dialogVisible.value = true;
};

// 隐藏模态框
const closeDialog = () => {
  dialogVisible.value = false;
  initPageData();
};

// 过滤方法
const filterMethod = (keywords: string, item: IReagentOption) => {
  // 默认的过滤方法,使用关键字与选项对象的label属性进行匹配
  return item.reagentName.toLowerCase().includes(keywords.toLowerCase());

  // 自定义过滤方法,搜索以关键字结尾的选项,区分大小写
  // return item.reagentName.endsWith(keywords);
};

// 确定
const onConfirmClick = async () => {
  // 检查数据合法性
  if (!checkValid()) {
    return;
  }

  let selectedOptions = selectedOptionIds.value
    .map((id) => reagentOptionList.value.find((option) => option.id === id))
    .filter((option): option is IReagentOption => !!option); // 过滤掉 undefined 并缩小类型

  // 生成申领单
  if (selectedOptions.length > 0) {
    await branchWarehouseApplyGenerateForReagentService(selectedOptions);
  }

  // 关闭模态框
  closeDialog();
};

// 检查数据合法性
const checkValid = () => {
  if (selectedOptionIds.value.length === 0) {
    ElMessage.warning("请选择试剂");
    return false;
  }
  // 循环遍历已选试剂
  for (let i = 0; i < selectedOptionIds.value.length; i++) {
    let option = reagentOptionList.value.find((option) => option.id === selectedOptionIds.value[i]);
    if ((option?.applyAmount ?? 0) === 0 || (option?.applyAmount ?? 0) > option?.amount!) {
      if ((option?.applyAmount ?? 0) === 0) ElMessage.warning("请输入申领数量!");
      else ElMessage.error("申领数量不能大于库存数量!");
      document.getElementById(`input-apply-amount-${option?.id}`)?.focus();
      (document.getElementById(`input-apply-amount-${option?.id}`) as HTMLInputElement)?.select();
      return false;
    }
  }
  return true;
};

// 搜索,加装防抖器,防抖处理(leading: true,立即执行、maxWait: 3000,3秒内至少执行一次)
const onSearchClick = debounce(
  async () => {
    // 清空已选试剂id集合
    selectedOptionIds.value = [];
    // 发送网络请求,获取试剂选项列表
    await fetchReagentOptionList(searchVal.value);
  },
  1000,
  { leading: true, trailing: true, maxWait: 3000 }
);

// 页面初始化
const initPageData = () => {
  // 清空左侧过滤框
  transferRef.value?.clearQuery("left");
  // 清空右侧过滤框
  transferRef.value?.clearQuery("right");
  // 清空搜索框
  searchVal.value = "";
  // 清空已选试剂id集合
  selectedOptionIds.value = [];
  // 重置试剂选项数据
  resetReagentOptionData();
};

defineExpose({
  openDialog
});
</script>

<template>
  <el-dialog
    class="receive-dialog"
    title="试剂耗材申领"
    width="1200px"
    top="0vh"
    style="border-radius: 10px"
    v-model="dialogVisible"
    :close-on-press-escape="true"
    :close-on-click-modal="false"
    :show-close="true"
    @close="closeDialog">
    <template #default>
      <el-container class="container">
        <el-transfer
          ref="transferRef"
          class="custom-transfer"
          v-model="selectedOptionIds"
          :data="reagentOptionList"
          :props="{
            key: `id`,
            label: `reagentName`
          }"
          :titles="[`待选试剂`, `已选试剂`]"
          :button-texts="[`移除`, `添加`]"
          :filterable="reagentOptionList.length > 12"
          :filter-placeholder="`请输入关键字搜索试剂`"
          :filter-method="filterMethod">
          <!-- 自定义列表数据项的内容 -->
          <template #default="{ option }">
            <div class="transfer-list-option">
              <div class="transfer-list-option-left">
                <el-tag type="primary">{{ (option as IReagentOption).reagentName }}</el-tag>
                <el-tag type="info" v-if="(option as IReagentOption).batchNo">{{
                  (option as IReagentOption).batchNo
                }}</el-tag>
              </div>
              <div class="transfer-list-option-right">
                <el-tag type="warning">{{ (option as IReagentOption).validityDate }}</el-tag>
                <el-tag class="transfer-list-option-right-amount" type="success">{{
                  (option as IReagentOption).amount
                }}</el-tag>
                <el-input
                  v-if="selectedOptionIds.includes((option as IReagentOption).id)"
                  :id="`input-apply-amount-${(option as IReagentOption).id}`"
                  class="input-apply-amount"
                  style="width: 85px; text-align: center"
                  v-model="(option as IReagentOption).applyAmount"
                  placeholder="输入申领数量"
                  size="small"
                  clearable
                  @input="(option as IReagentOption).applyAmount = Number(formatToNumber($event, 0))" />
              </div>
            </div>
          </template>
          <!-- 自定义左侧列表底部的内容 -->
          <template #left-footer>
            <div class="transfer-left-footer">
              <el-input v-model="searchVal" placeholder="请输入试剂名称" clearable @keydown.enter="onSearchClick">
                <template #prepend>查找试剂:</template>
                <template #append>
                  <el-button :icon="Search" @click="onSearchClick" />
                </template>
              </el-input>
            </div>
          </template>
          <!-- 自定义右侧列表底部的内容 -->
          <!-- <template #right-footer>
            <div>
              <span>可以自定义右侧列表底部的内容</span>
            </div>
          </template> -->
        </el-transfer>
      </el-container>
    </template>
    <template #footer>
      <div>
        <el-button class="dialog-btn" type="primary" @click="onConfirmClick">确定</el-button>
        <el-button class="dialog-btn" @click="closeDialog">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style scoped lang="scss">
/* 穿梭框容器样式 */
.container {
  width: 100%;
  height: 80vh;
}
/* 穿梭框样式 - 已通过 Element Plus v2.7.4 测试 */
.custom-transfer {
  flex: 1;
  display: flex;
  justify-content: space-between; /* 首尾元素贴边,中间元素等距 */
  /* 面板样式 */
  :deep(.el-transfer-panel) {
    /**
    如果所在容器没有设置justify-content: space-between; 又需要穿梭框占满容器,
    需通过浏览器调试工具,获取到穿梭框容器宽度为1168px,按钮区域占用200px,则面板宽度应该设置为 (1168-200)/2 = 484px,
    如果所在容器已经设置justify-content: space-between; 又需要穿梭框占满容器,面板宽度可以不用精细计算
     */
    width: 550px;
    height: 100% !important;
    display: flex;
    flex-direction: column;
  }
  /* 面板头部样式 */
  :deep(.el-transfer-panel__header) {
    background-color: #f5f7fa;
    display: flex;
  }
  /* 面板主体 */
  :deep(.el-transfer-panel__body) {
    flex: 1;
    display: flex;
    flex-direction: column;
  }
  /* 列表区域 - 关键滚动区域 */
  :deep(.el-transfer-panel__list) {
    flex: 1;
    overflow-y: auto;
  }
  /* 列表选项 */
  :deep(.el-transfer-panel__item) {
    flex: 1;
    display: flex;
    align-items: center; /* 垂直居中 */
    margin: 0;
    padding-right: 15px;
    height: 32px;
  }
  /* 列表选项 - 最后一个选项 */
  :deep(.el-transfer-panel__item:last-child) {
    padding-right: 15px;
  }
  /* 按钮区域 */
  :deep(.el-transfer__buttons) {
    display: flex;
    flex-direction: column-reverse; /* 垂直反序排列 */
    justify-content: center; /* 水平居中 */
    align-items: center; /* 垂直居中 */
    padding: 0;
  }
  /* 按钮 */
  :deep(.el-transfer__buttons .el-button) {
    margin: 20px 10px;
    width: 40px;
    padding: 8px 15px;

    /* 蓝色渐变背景 */
    // background: linear-gradient(135deg, #409eff 0%, #3375b9 100%);
    // border: none;
    // color: white;
    // box-shadow: 0 2px 5px rgba(64, 158, 255, 0.3);
  }
  /* 按钮文字 */
  :deep(.el-transfer__buttons .el-button span) {
    display: none; /* 隐藏按钮文字 */
  }
  /* 按钮内容 */
  :deep(.el-transfer__buttons .el-button:first-child::after) {
    content: "<="; /* 设置按钮显示内容为 <= */
  }
  :deep(.el-transfer__buttons .el-button:last-child::after) {
    content: "=>"; /* 设置按钮显示内容为 => */
  }

  .transfer-list-option {
    flex: 1;
    display: flex;
    flex-direction: row; /* 水平排列 */
    align-items: center; /* 垂直居中 */
    height: 32px;
    &-left {
      flex: 1;
      display: flex;
      justify-content: start; /* 贴左边 */
      align-items: center; /* 垂直居中 */
      max-width: 220px;
    }
    &-right {
      flex: 1;
      display: flex;
      justify-content: end; /* 贴右边 */
      align-items: center; /* 垂直居中 */
      &-amount {
        width: 40px;
      }
      .input-apply-amount {
        width: 85px;
        // 输入框的内容居中
        & :deep(.el-input__inner) {
          text-align: center;
        }
      }
    }
    .el-tag {
      font-size: 14px;
    }
  }
  .transfer-left-footer {
    display: flex;
    height: 100%;
  }
}
.dialog-btn {
  width: 100px;
}
</style>

应用效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2407859.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…