美文网首页
vue多选/单选效果

vue多选/单选效果

作者: web前端攻城狮 | 来源:发表于2020-04-10 18:04 被阅读0次

    转:https://blog.csdn.net/Number7421/article/details/81002729

    不过我以前都写过这三种方法了,很pang额,怕之后忘记了,偷个懒拿别人的,以免以后忘记了

    一、单选:

    思路:当点击的索引值 == v-for循环的索引值时,给你那个li添加选中样式

    html:

    <ul class="box">
        <li v-for="c,index of cities" :class="{checked:index==n}" @click="changeList(index)">{{c}}</li>
    </ul>
    

    CSS样式如下:

    <style type="text/css">
    body{margin:0;}
    ul{
        padding:0; list-style:none; 
        margin:150px 150px;
    }
    li{
        width:80px; height:50px; 
        display:inline-block;
        border-radius:8px; border:1px #000 solid;
        text-align:center; line-height:50px;
        cursor:pointer; 
        transition:all 0.3s linear;
        margin-left:5px;
    }
    li:hover{
        background-color:#0CF; color:#fff; 
        border:1px #fff solid;
    }    
    li.checked{
        background-color:#0CF; color:#fff; 
        border:1px #fff solid;
    }
    </style>
    

    js:

    var app = new Vue({
        el : ".box",
        data : {
            cities : ["上海","北京","广州","重庆","西安"],
            n : 0
        },
        methods :{
            changeList(index){
                this.n = index;//this指向app
            }
        }
    })
    
    image.png

    二、多选

    方法一和方法二的主要的区别在于数据中有没已有标注是选中状态还是未选中状态

    CSS样式如下:

    <style type="text/css">
    body{margin:0;}
    .box{ margin:150px 150px;}
    ul{
        padding:0; 
        list-style:none;
    }
    li{
        width:50px; height:30px; display:inline-block;
        text-align:center; line-height:30px;
        cursor:pointer;margin-left:5px;
    }
    li:before{ 
        display:inline-block; width:10px; height:10px; 
        line-height:10px; content:""; border:1px #000 solid; 
        margin-right:2px; transition:all 0.3s linear;
    }    
    li.checked:before{ 
        background-color:#0CF; 
        border:1px #fff solid;
    }
    li.checked{color:#0CF;}
    </style>
    

    方法一:

    思路:新增一个新的空数组arr(arr的里元素的索引值表示,表示该索引值对应的li已经处于被选中状态),如果arr数组没有点击的索引值,就添加到arr数组里,如果有就把这个索引,就把这个索引从数组中删除。

    html:

    <ul class="box">
    <li v-for="c,index of cities" :class="{checked:arr.includes(index)}" @click="checkedBox(index)">{{c}}</li>
    </ul>
    

    js:

    var app = new Vue({
        el : ".box",
        data : {
            cities : ["上海","北京","广州","重庆","西安"],
            arr : []
        },
        methods :{
            checkedBox(i){
                if(this.arr.includes(i)){
                    //includes()方法判断是否包含某一元素,返回true或false表示是否包含元素,对NaN一样有效
                    //filter()方法用于把Array的某些元素过滤掉,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素:生成新的数组
                    this.arr=this.arr.filter(function (ele){return ele != i;});
                }else{
                    this.arr.push(i);
                }
            }
        }
    })
    

    方法二:

    思路:这个就更加通俗易懂了,把点击的那个是否选中的标志取反就可以了

    html:

    <ul class="box">
        <li v-for="c,index of cities"
        :class="{checked:c.bOn}"
        @click="checkbox(index)">{{c.city}}</li>
    </ul>
    

    js:

    var app = new Vue({
        el : ".box",
        data : {
            cities : [{city:"北京",bOn:false},
            {city:"上海",bOn:false},
            {city:"重庆",bOn:false},
            {city:"广州",bOn:false},
            {city:"西安",bOn:false}]
        },
        methods : {
            checkbox(i){
                this.cities[i].bOn = !this.cities[i].bOn;
            }
        }
    })
    
    image.png

    项目实战代码

    <template>
        <div>
            <van-search
                v-model="value"
                shape="round"
                show-action
                placeholder="编号/品种/规格/产地"
                @search="onSearch"
            >
                <template #action>
                    <div @click="onSearch" class="onSearchBtn">搜索</div>
                </template>
            </van-search>
            <div class="tips">
                已选 ({{ton}}吨/{{num}}件)
            </div>
            <div class="resultBox">
                <ul>
                    <van-list
                    v-model="loading"
                    :finished="finished"
                    finished-text="没有更多了"
                    @load="getStockLists"
                    >
                        <li v-for="(item,index) in list">
                            <div class="resultBoxTit">
                                <div>
                                    <span class="resultBoxNum">{{item.good_sn}}</span>
                                    <span class="resultBoxPosition">{{item.stock_seat}}</span>
                                </div>
                                <div @click="son(item,index)">
                                    <div v-if="arr.some(({id})=>id==item.id)" class="resultBoxRemove">取消添加</div>
                                    <div v-else class="resultBoxAdd">+添加</div>
                                </div>
                            </div>
                            <div class="resultBoxContent">
                                <div class="resultBoxProduct">
                                    <div class="van-ellipsis ellipsisOne">
                                        {{item.cat_name}}
                                    </div>
                                    <div class="van-ellipsis ellipsisTwo">
                                        {{item.spec_name}}
                                    </div>
                                    <div class="van-ellipsis ellipsisThree">
                                        {{item.brand_name}}
                                    </div>
                                    <div class="van-ellipsis ellipsisFour">
                                        {{item.type_name}}
                                    </div>
                                </div>
                                <div class="resultBoxProduct">
                                    <div>
                                        <span>抄码/过磅:{{item.show_weight}}吨/{{item.weigh_weight}}吨</span>
                                    </div>
                                    <div>
                                        {{item.number | parseIntData}}捆
                                    </div>
                                </div>
                            </div>
                        </li>
                    </van-list>
                </ul>
            </div>
            <div class="footerBtn">
                <div class="footerBtnTop" @click="hideOutBox">
                    完成
                </div>
            </div>
        </div>
    </template>
    
    <script>
    import { Toast } from 'vant';
        export default {
            props: ["newArr"],
            data() {
                return {
                    value: '',
                    list:[],
                    loading: false,
                    finished: false,
                    page:1,
                    arr:[], //多选保存的数组
                };
            },
            watch: {
                //监听父组件的删除列表变化,重新赋值
                newArr(newVal,oldVal){
                    this.arr = newVal
                }
            },
            computed: {
                num: function () {
                    var sum = 0
                    for (let index = 0; index < this.arr.length; index++) {
                        sum += parseInt(this.arr[index].number)*1
                    }
                    return sum
                },
                ton: function () {
                    var sum = 0
                    for (let index = 0; index < this.arr.length; index++) {
                        // sum += parseFloat(this.arr[index].show_weight)*1
                        sum += (parseFloat(this.arr[index].show_weight)*10)/10;
                    }
                    return sum.toFixed(3)
                }
            },
            filters: {
                parseIntData: function (value) {
                    return parseInt(value)
                }
            },
            mounted() {
                this.getStockLists();
            },
            methods: {
                son(item,i){
                    if(this.arr.some(({id})=>id==item.id)){
                        this.arr= this.arr.filter(function (ele){
                            return ele.id != item.id
                        });
                    }else{
                        this.arr.push(item);
                    }
                },
                hideOutBox(){
                    this.$emit('arr',this.arr)
                    this.$emit('hideOutBox',false)
                },
                onSearch(val) {
                    this.page = 1
                    // this.arr = []
                    this.list = []
                    this.getStockLists();
                },
                //获取添加货物数据数组
                getStockLists(){
                    this.value = this.value.trim() //去掉搜索框的空格
                    this.http.get(this.api.stocks_getStockLists,{
                        keyword :this.value,
                        page :this.page,
                        limit :''
                    })
                    .then(res => {
                        if(this.value != ''){
                            this.finished = false;
                            if(res.data.lists == ''){
                                this.list =res.data.lists
                                this.finished = true;
                            }else{
                                var newLists = [].concat(this.list,res.data.lists)
                                this.list = newLists
                                this.page = this.page+1
                                // 加载状态结束
                                this.loading = false;
                                if (Math.ceil(this.list.length/20) >= res.data.total) {
                                    this.finished = true;
                                }
                            } 
                        }else{
                            var newLists = [].concat(this.list,res.data.lists)
                            this.list = newLists
                            this.page = this.page+1
                            // 加载状态结束
                            this.loading = false;
                            if (Math.ceil(this.list.length/20) >= res.data.total) {
                                this.finished = true;
                            }
                        }
                    });
                }
            }
        }
    </script>
    
    <style scoped>
    .onSearchBtn{
        color: #007ce6;
        font-size: 16Px;
    }
    .tips{
        text-align: center;
        height: 60px;
        line-height: 60px;
    }
    /* 列表 */
    .resultBox{
    
    }
    .resultBox li{
        background: #fff;
        padding: 15Px;
        font-size: 14Px;
        margin-bottom: 20px;
    }
    .resultBoxTit{
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 30px;
    }
    .resultBoxNum{
        font-size: 16Px;
        margin-right: 50px;
    }
    .resultBoxPosition{
        color: #666666;
    }
    .resultBoxAdd{
        background: #007ce6;
        border-radius: 4Px;
        color: #fff;
        padding: 6Px 16Px;
    }
    .resultBoxContent{
        background: #f4faff;
        padding: 0 15Px;
    }
    .resultBoxProduct{
        display: flex;
        justify-content: space-between;
        padding: 15Px 0;
    }
    .resultBoxProduct:first-child{
        border-bottom: 1Px solid #eff2f4;
    }
    .ellipsisOne{
        width: 130px;
    }
    .ellipsisTwo{
        width: 300px;
    }
    .ellipsisThree{
        width: 80px;
    }
    .resultBoxRemove{
        background: red;
        border-radius: 4Px;
        color: #fff;
        padding: 6Px 16Px;
    }
    /* 列表结束 */
    .footerBtn{
        position: fixed;
        bottom: 0;
        left: 0;
        background: #fff;
        width: 100%;
        border-top: 1Px solid #e2e2e2;
        height: 126px;
        display: flex;
        padding: 10Px 15Px;
        box-sizing: border-box;
        justify-content: space-between;
    }
    .footerBtnTop{
        background: #007ce6;
        border-radius: 4Px;
        width: 100%;
        font-size: 16Px;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #fff;
    }
    </style>
    
    
    image.png
    image.png

    在搜索页面点击拿到数据,点完成,要把数据带到上一个页面。

    相关文章

      网友评论

          本文标题:vue多选/单选效果

          本文链接:https://www.haomeiwen.com/subject/tdkdmhtx.html