Vue---组合式API---穿梭框---完整版代码

<template>
    <div class="main-box">
        <div class="List">
            <div class="ltitle title">
                <input type="checkbox" v-model="lcheck" name="" id="list1" @click="lallChecked">
                <label for="list1">List 1</label>
                <span class="num1">{{lnum}}/{{lAllNum}}</span>
            </div>
            <ul class="eul">
                <li v-for="jsonList in leftJsonArrayList">
                    <div><input class="check" @change="loneCheck" type="checkbox" v-model="jsonList.check"
                            :disabled="jsonList.disabled">{{jsonList.content}}</div>
                </li>
            </ul>
        </div>
        <div class="btn">
            <button class="lBtn" @click="leftBtnCurr">&lt;</button>
            <button class="rBtn " @click="rightBtnCurr">&gt;</button>
        </div>
        <div class="List">
            <div class="rtitle title">
                <input type="checkbox" v-model="rcheck" @click="rallChecked" name="" id="list2">
                <label for="list2">List 2</label>
                <span class="num2">{{rnum}}/{{rAllNum}}</span>
            </div>
            <ul class="eul rul">
                <li v-for="jsonList in rightJsonArrayList">
                    <div><input class="check" @change="roneCheck" type="checkbox"
                            v-model="jsonList.check">{{jsonList.content}}</div>
                </li>
            </ul>
        </div>
    </div>
</template>
<script setup>
import { ref, watch, onUpdated, nextTick, onMounted } from "vue";
// 左边框子数据
let leftJsonArrayList = ref([
    { check: true, content: "Opsition1", disabled: false },
    { check: false, content: "Opsition2", disabled: true },
    { check: false, content: "Opsition3", disabled: false },
    { check: false, content: "Opsition4", disabled: false },
    { check: false, content: "Opsition5", disabled: false },
    { check: true, content: "Opsition6", disabled: false },
    { check: true, content: "Opsition7", disabled: false },
    { check: true, content: "Opsition8", disabled: false },
    { check: true, content: "Opsition9", disabled: false },
    { check: true, content: "Opsition10", disabled: false },
    { check: true, content: "Opsition11", disabled: false },
    { check: true, content: "Opsition12", disabled: false },
    { check: true, content: "Opsition13", disabled: false },
    { check: true, content: "Opsition14", disabled: false },
    { check: true, content: "Opsition15", disabled: false },
]);

// 右边框子数据
let rightJsonArrayList = ref([]);

// 左侧列表数据
let lcheck = ref(false);//list1默认不选中
let lnum = ref(0); // 左边框子--选中条数
let lAllNum = ref(leftJsonArrayList.value.length); // 左边框子--总共条数

// 右侧列表数据
let rcheck = ref(false);
let rnum = ref(0);
let rAllNum = ref(rightJsonArrayList.value.length);

// 穿梭--右侧按钮
const rightBtnCurr = () => {
    let selectArr = leftJsonArrayList.value.filter(item => item.check); // 筛选左侧数组中所有check为true的项目
    rightJsonArrayList.value.push(...selectArr); // 把数组结构为对象,并添加到右侧数组
    leftJsonArrayList.value = leftJsonArrayList.value.filter((item) => !item.check);// 将左侧数组替换为除了check为true的数组
    rightJsonArrayList.value.forEach(item => item.check = false);// 将穿梭过来的数据check值改为false
    lcheck.value = false;
    rcheck.value = false;
}

// 穿梭--左侧按钮
const leftBtnCurr = () => {
    let selectArr = rightJsonArrayList.value.filter(item => item.check);
    leftJsonArrayList.value.push(...selectArr); // 把数组结构为对象,并添加到右侧数组
    rightJsonArrayList.value = rightJsonArrayList.value.filter((item) => !item.check);
    leftJsonArrayList.value.forEach(item => item.check = false);
    rcheck.value = false;
    lcheck.value = false;
}

// 左侧数据监听
watch(
    () => leftJsonArrayList.value,
    (valNew, valOld) => {
        // console.log(valNew)
        let jsonArrayResult = valNew.filter(item => item.check); // 筛选所有check==true
        lnum.value = jsonArrayResult.length;                     // 把所有check==true的长度赋给lnum
        let jsonArrayResultAll = valNew.filter(item => !item.disabled);// 筛选出所有可以选中的
        if (lnum.value > 0 && lnum.value == jsonArrayResultAll.length) {// 被动全选
            lcheck.value = true;
        } else {
            lcheck.value = false;
        }
        nextTick(() => {
            lightBtn(); //按钮渲染
        })
    },
    { deep: true, immediate: true }// deep 深度..immediate 是否开局监听
)

// 右侧数据监听
watch(
    () => rightJsonArrayList.value,
    (valNew, valOld) => {
        let jsonArrayResult = valNew.filter(item => item.check);
        rnum.value = jsonArrayResult.length;
        let jsonArrayResultAll = valNew.filter(item => !item.disabled);
        rAllNum.value = jsonArrayResultAll.length;
        if (rnum.value > 0 && rnum.value == jsonArrayResultAll.length) {
            rcheck.value = true;
        } else {
            rcheck.value = false;
        }
        nextTick(() => {
            lightBtn();
        })
    },
    { deep: true, immediate: true }
);


// 左边 点击--全选/全不选
const lallChecked = () => {
    if (!lcheck.value) {
        let notdisabled = leftJsonArrayList.value.filter((item) => !item.disabled);
        notdisabled.filter((item) => { item.check = true });
        lightBtn()
    } else {
        let notdisabled = leftJsonArrayList.value.filter((item) => !item.disabled);
        notdisabled.filter((item) => { item.check = false });
        lightBtn()
    }
}

// 右边 点击--全选/全不选
const rallChecked = () => {
    if (rcheck.value == false) {
        let notdisabled = rightJsonArrayList.value.filter((item) => !item.disabled);
        notdisabled.filter((item) => { item.check = true });
    } else {
        let notdisabled = rightJsonArrayList.value.filter((item) => !item.disabled);
        notdisabled.filter((item) => { item.check = false });
    }
}
// 高亮--按钮
function lightBtn() {
    let rBtn = document.querySelector(".rBtn");
    let lBtn = document.querySelector(".lBtn");
    // 左侧数据 右侧按钮
    lnum.value > 0 ? rBtn.classList.add("currBtn") : rBtn.classList.remove("currBtn");
    // 右侧数据 左侧按钮
    rnum.value > 0 ? lBtn.classList.add("currBtn") : lBtn.classList.remove("currBtn");
}

</script>
<style scoped>
* {
    margin: 0;
    padding: 0;
    list-style: none;
    box-sizing: border-box;
}

.main-box {
    /* background: skyblue; */
    width: 800px;
    /* height: 600px; */
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 20px;
}

.btn {
    margin: 0px 20px;
}

.lBtn,
.rBtn {
    border: 0;
    background-color: #8CB5E7;
    padding: 10px 20px;
    color: #fff;
    border-radius: 5px;
    cursor: pointer;
}

.lBtn {
    margin-right: 5px;
}

.currBtn {
    background-color: #3086EB;
}

.currops {
    color: #3086EB;
}

.List {
    /* padding:10px 20px; */
    border: 1px solid rgba(170, 170, 170, 0.339);
    border-radius: 5px;
    overflow: hidden;

    width: 200px;
    height: 300px;
}

.title {
    background-color: #F1F1F3;
    padding: 10px 20px;
}

.num1,
.num2 {
    float: right;
}

ul {
    width: 100%;
    height: 85%;
    overflow-x: hidden;
}

li>div {
    padding: 10px 20px;
}

li>div:hover {
    color: #3086EB;
}

li>div>input {
    margin-right: 10px;
    ;
}



/* 默认 */
.title>input[type="checkbox"] {
    margin-top: 7px;
    cursor: pointer;
    position: relative;
    width: 14px;
    height: 14px;
    font-size: 14px;
    margin-right: 8px;
    background-color: #fff;
}

/* 选中后修改 */
.title>input[type="checkbox"]::after {
    position: absolute;
    top: 0;
    /* 修改默认背景色 */
    /* 修改默认对勾颜色 */
    color: #fff;
    width: 14px;
    height: 14px;
    display: inline-block;
    visibility: visible;
    text-align: center;
    border-radius: 2px;
    content: " ";
}

/* 被选中 */
.title>input[type="checkbox"]:checked::after {
    border: none;
    border-radius: 2px;
    content: "✔";
    background-color: #0075FF;
    border-radius: 2px;
    content: "-";
    font-size: 12px;
    font-weight: lighter;
}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值