Vue—shuttle box component

1. Language: vue
2. Realization effect: 1. After the left box is selected, it will be displayed on the right side. Click the icon behind each item in the right box to delete the one displayed on the right side. At the same time, the multi-selection box on the left side will be unchecked. . 2. There is a local fuzzy search box on the left. 3. To complete the component effect, multiple adaptations are required.
insert image description here
3. HTML+css style

   <div class="transfer-box">
   //左边的部分
        <div class="transfer-box-left">
            <div class="box-title">
            //左边的标题
                <h5><span class="box-title-icon">*</span>{
    
    {
    
     render.leftTitle }}:</h5>
                // 搜索框单写了一个组件
                <search @search="handleSearch" />
                <div class="box-left-check mt-10">
                    <div v-for="item in listData" :key="item.valueCode">
                        <input :id="item.valueCode" v-model="item.checked" type="checkbox" /><label
                            :for="item.valueCode"
                            >{
    
    {
    
     item.valueName }}</label
                        >
                    </div>
                </div>
            </div>
        </div>
        // 右边的部分
        <div class="transfer-box-right">
            <div class="box-title">
                <h5>{
    
    {
    
     render.rightTitle }}:</h5>
            </div>
            <div>
                <ul class="box-ul">
                    <li v-for="item in dataSource.filter((i) => i.checked)" :key="item.valueCode">
                        {
    
    {
    
     item.valueName }} <span class="icon-delete" @click="delFn(item)"></span>// 右边展示的文字和删除图标
                    </li>
                </ul>
            </div>
        </div>
    </div>
    //   样式
<style lang="less" scoped>
.transfer-box {
    
    
    display: flex;
    .transfer-box-left {
    
    
        flex: 1;
        height: 240px;
        .box-left-check {
    
    
            height: 180px;
            overflow-y: scroll;
            font-size: 12px;
            line-height: 1.5em;
        }
    }
    .transfer-box-right {
    
    
        width: 300px;
        height: 240px;
        overflow-y: scroll;
        margin-left: 20px;
        .box-ul {
    
    
            list-style: none;
            line-height: 1.5em;
        }
    }
    .box-title-icon {
    
    
        color: #f0463f;
    }
}
</style>

Fourth, the data that needs to be passed in

  1. dataSource – the data of the option, the data format is [{valueCode:1,valueName:1}]
  2. render – the text to be rendered, the format is render: { leftTitle: "Position", rightTitle: "Selected Position" },
<script>
import {
    
     ref } from "vue";
import search from "./search.vue"; // 搜索框组件
export default {
    
    
   components: {
    
    
       search,
   },
   props: {
    
    
       dataSource: Object,
       render: Object,
   },

   setup(props, {
     
      emit }) {
    
    
       const listData = ref(props.dataSource);  
       // 删除功能
       const delFn = (item) => {
    
    
           item.checked = false;
       };
       // 搜索框输入的值在已有的数据里面筛选
       const handleSearch = (e) => {
    
    
           if (e.value) {
    
    
               listData.value = listData.value.filter((item) => {
    
    
                   if (item.valueName.indexOf(e.value) != -1) {
    
    
                       return item;
                   }
               });
           } else {
    
    
               listData.value = props.dataSource;
           }
       };
       return {
    
     listData, delFn, handleSearch };
   },
};
</script>

Five, the search box component:

<template>
   <div class="search-box">
       <span class="input-group">
           <input v-model="searchValue" class="search-box-input" type="text" :placeholder="placeholder" />
           <span v-if="searchValue" class="icon-close" @click="clearFn"></span>
       </span>
       <button type="button" class="icon-search search-box-icon btn" @click="handleSearch"></button>
   </div>
</template>
<script>
import { ref } from "vue";
export default {
   props: {
       placeholder: { type: String, default: "输入节点名称搜索" },
   },
   emits: ["search"],
   setup(props, { emit }) {
       const searchValue = ref();
       const handleSearch = () => {
           emit("search", searchValue);
       };
       const clearFn = () => {
           searchValue.value = "";
       };
       return { handleSearch, searchValue, clearFn };
   },
};
</script>
<style lang="less">
.search-box {
   display: flex;
   align-items: center;
   height: 26px;
   line-height: 26px;
   width: 200px;
   position: relative;
   .input-group {
       border: 1px solid #ccc;
       height: 26px;
       padding: 0;
       margin: 0;
       width: 165px;
   }
   .search-box-input {
       outline: none;
       border: none;
   }
   .search-box-icon {
       position: absolute;
       right: 0;
       text-align: center;
       font-size: 16px;
       height: 28px;
       border-radius: 2px;
       border: 1px solid #ccc;
       width: 34px;
       padding: 0;
   }
}
</style>

6. The simple and rough version of the shuttle box is completed, and it will be perfected when it comes to mind. Or give us suggestions

Guess you like

Origin blog.csdn.net/qq_45234274/article/details/124810687