el-transfer:实现单选效果

el-transfer作为element重要的组件之一,可以完美实现在两个列表之间移动元素。但有时我们可能需要它实现单选效果,就比如给某个部门设置部门负责人。部门负责人只能有一个,因此右侧窗口只能保留一个选项,而左侧窗口中的选项需要实现单选。并且,当我们把左侧选项填充到右侧栏框中时,右侧原有的记录应该被更新。 就如同下面图片展示出来的效果一样:

当然,可以不使用el-transfer而改用单选框radio,但显示效果肯定没有这个好。因此有必要对el-transfer的事件进行处理,已达到我们想要的单选效果。

其实实现起来并不难,解决方案:

1.给el-transfer增加@left-check-change事件"handleLeftCheckChange",监控左侧选项框中选中事件,只允许一个选项被选中,当有新的选项被选中时,将原有选中项取消选中;

// 处理左侧菜单只能选择一个选项的问题
const handleLeftCheckChange = (value,direction,movedKeys) => {
  // 当左侧栏选中一个以上选项时,就从被选中id数组value中从第0个元素开始删除1个元素
  // 也就是说,当选择一个以上选项时,就将数组中第一个元素删除,只保留一个最新选中项的id
  if(value.length > 1){
    value.splice(0,1);
  }
}

splice方法会将数组中指定元素移除,这里设置的是从第0个元素开始移除一个元素,也就是将数组开头的元素移除,已达到移除上一次选中项的效果

2.给el-transfer增加@change事件"handleChange",监控右侧选项框中选项数量变化情况,只保留一个选项,当有新的选项填充进来时,将原有选项移除;

// 监听职务绑定变化情况,记录变化后的职务id数组
const handleChange = (value,direction,movedKeys) => {
  // 将添加到右侧菜单栏的选项的id数组赋值给rightValue
  rightValue.value = value;
  // 判断当前rightValue数组长度是否大于1
  if(rightValue.value.length>1){
    // 若数组长度大于1,就通过shift方法将数组中起始元素移除,保证数组中只保留一个最新添加的元素id
    // 若要移除末尾元素,可使用pop方法
    rightValue.value.shift();
  }
  // 监听右侧列表元素变化情况,一旦原有状态发生变化,就将提交按钮至于可用状态
  // 以此避免在没有配置任何职务信息及原有职务信息无变化的情况下提交表单
  butDisabled.value = false;
}

当然前提是在el-transfer组件中v-model属性绑定的是"rightValue",shift方法会将数组中起始元素移除,其功能与splice(0,1)相同

到此为止,el-transfer单选效果就实现了。

当然,通常实现了这样的效果,是为了将右侧选项框中选项信息返回给父组件,这就要说到父子组件参数传递的问题。比如此时,我在父组件中向子组件AddDepHead.vue传递以下参数值,并做了双向绑定:

<AddDepHead v-model="userDialogVisible" :userDialogVisible="userDialogVisible" :depHeadDialogTitle="depHeadDialogTitle" v-model:leaderName="leaderName" v-model:leaderID="leaderID" />

在子组件AddDepHead.vue中通过vue提供的defineProps方法进行接收:

// 从父组件接收参数
const props = defineProps(
    {
      leaderID: {
        type: Number,
        default: -1,
        required: true
      },
      leaderName: {
        type: String,
        default: '',
        required: true
      },
      userDialogVisible: {
        type: Boolean,
        default: false,
        required: true
      },
      depHeadDialogTitle: {
        type: String,
        default: '',
        required: true
      },
    }
)

并通过defineEmits提供了响应式参数更新操作:

// 定义父组件中的参数监控类型
let emits = defineEmits(['update:modelValue', 'update:leaderName', 'update:leaderID'])

当在子组件AddDepHead.vue中的操作完成,需要提交信息并关闭窗口时,执行confirmSubmit方法:

// 提交时,将右侧菜单栏的用户id和用户名通过emits方法更新到父组件对应参数变量中
const confirmSubmit = () => {
  data.value.forEach((user, index) => {
    if(user.id == rightValue.value[0]){
      emits('update:leaderName',user.userName);
      return;
    }
  })
  emits('update:leaderID',rightValue.value[0]);
  unSubmit();
}

const unSubmit = () => {
  rightValue.value = [];
  emits('update:modelValue', false);
}

在该方法中可以看到,我们将右侧选项框中唯一元素的id,也就是rightValue所代表的id数组唯一元素赋值给了父组件的leaderID变量,又将与该id对应的用户名赋值给了父组件的leaderName变量,这就完成了子组件对父组件参数的响应式操作,在子组件中更新了父组件的参数值。

如果在组件参数传递时,你是直接传递了父组件中的参数名,那问题到此也就结束了。但如果说leaderID和leaderName也只是父组件中定义的一个中间变量,最终这两个参数的值还要更新到form表单的某个属性上去,那就还得再进行一步参数值的转移,才能实现对表单属性值的更新。

比如我这里,就是这种情况,leaderID和leaderName只是父组件中定义的一个中间变量,分别从form表单获取到id属性值和name属性值,并将其传递给子组件AddDepHead.vue。在子组件中经过操作,将两个属性更新后,先通过leaderID和leaderName接收来自子组件的参数值的更新,然后还得将leaderID和leaderName更新后的值赋值给form表单对应属性上去。

这里就有两种方式处理主:一是在父组件定义一个方法initialFormAttr,用于处理中间变量与表单属性间的值传递问题,然后将这个方法传递给子组件,在子组件触发这个操作;二是在父组件中通过watch监听子组件的操作,当条件触发时自动完成中间变量与表单属性间的值传递。我这里用的是第二个方案,在父组件添加watch监听,自动更新表单属性值:

const userDialogVisible = ref(false);

watch(
    () => userDialogVisible.value,
    () => {
      form.value.depLeaderId = leaderID.value;
      form.value.depLeaderName = leaderName.value;
    }
)
userDialogVisible用来控制子组件AddDepHead.vue的显示与隐藏,默认隐藏,再付组件中点击打开对话框按钮后,该值设为true,子组件处于显示状态,以便进行操作

每次userDialogVisible参数变化都会触发watch事件,就会执行一次中间变量与表单属性间的值传递操作。当然,为了防止由于watch自动触发导致在子组件AddDepHead.vue没有进行任何配置的情况下将leaderID和leaderName两个中间变量初始值更新到form表单对应属性,使得更新结果出错,需要在开启子组件AddDepHead.vue方法上添加对leaderID和leaderName的初始化操作,将表单原有属性值初始化到两个参数中:

const openUserSelectDialog = ()=>{
  userDialogVisible.value = true;
  depHeadDialogTitle.value = "Assign department heads for ["+form.value.depName+"] department";
  leaderName.value = form.value.depLeaderName;
  leaderID.value = form.value.depLeaderId;
}

到此为止,大功告成。这就是如何实现el-transfer穿梭框单选,以及如何将右侧选择框内容信息传递给父组件的全部过程,希望对大家的开发能有所帮助。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值