右侧菜单导航(vue实现)

253 阅读1分钟

html结构:

:class的用法很多种:
:class="[class1,flag?class2:'']"// 数组
:class="{'class1':flag}"// 对象
:class="addClass()"// 函数形式
<ul>
	<li class="p_item" v-for="(item,i) in items" :key="i">
		<a class="p_title" @click="n=i" :class="{'selected':n==i}">
			<i class="iconfont" :class="item.icon"></i>{{item.name}}
			<b :class="n==i?'down':'up'">^</b>
		</a>
		<ul class="c_item" v-show="n==i">
			<li v-for="(sub,j) in item.child" :key="j">
				<a>{{sub.name}}</a>
			</li>
		</ul>
	</li>
</ul>

js数据:

    new Vue({
        el:"#my",
        data:{
            n:1, //用于菜单的动态效果实现操作,这里也可以在数据加上flag去判断,但是这样不能保证后端数据是否能给到,所以优先采用这种
            items:[
                {
                    name:'肥羊',
                    icon:'icon-nnc',
                    child:[
                        {name:'标题肥羊'},
                        {name:'肥羊'},
                        {name:'肥羊一'}
                    ]
                },
                ...
            ]
        },
        methods:{
            getList(){
                axios({
                    method:'get',
                    url:'/menus'
                }).then(res=>{
                    this.items = res?.data?.result;// ?.可选链
                }).catch(error=>{
                    console.log(error)
                })
            }
        },
        mounted(){
            this.getList()// 或者数据也可以通过这里获取,而不是写死的数据
        }
    })

css:

.selected {
    color: #1890ff;
    border-bottom: 1px solid #1890ff;
}
.down {
    transform: rotate(180deg);
}
.up {
    transform: rotate(0deg);
}
....

此外还有一种方式: 不过这种需要处理一下每条数据是否有flag字段。

<ul>
    <li class="p_item" v-for="(item,i) in items" :key="i">
            <a class="p_title" @click="flagChange(item)" :class="{'selected':item.flag}">
                    <i class="iconfont" :class="item.icon"></i>{{item.name}}
                    <b v-show="!item.flag">^</b>
                    <b v-show="item.flag"></b>
            </a>
            <ul class="c_item" v-show="item.flag">
                    <li v-for="(sub,j) in item.subItems" :key="j">
                            <a>{{sub.name}}</a>
                    </li>
            </ul>
    </li>
</ul>

items:[
    {
        name:'标题一',
        icon:'icon-yonghu',
        flag:true,
        subItems:[
            {name:'标题一'},
            {name:'标题一'},
            {name:'标题一'}
        ]
    },
    ....
]

methods:{
    flagChange(item){
       //item.flag  = !item.flag;
       this.items.forEach(function(v){
           v.flag = false;
       });
       item.flag = true;
    }
},

每条数据是否有flag字段,这种方法在列表选中状态时特别有用。 使用引入模式时,可以用template模块或者v-cloak清除一闪而过的模版语言{{}}

<link rel="stylesheet" type="text/css" href="css/index.css">
<script src='js/vue.js'></script>
<script src='js/index.js'></script>

<!--左侧所有好友-->
<div class="col-xs-6 col-sm-6" >
        <div class="panel panel-success">
                <!--标题-->
                <div class="panel-heading">
                        <template><h3 class="panel-title">所有好友({{items.length}})/选中好友({{selectItems.length}})</h3></template>
                </div>
                <!--内容-->
                <div class="panel-body panel-height">
                        <ul>
                                <li v-for="item in items" :key="item.id" @click="addItemfn(item)" :class="item.flag?'active':''">
                                        <span class="glyphicon glyphicon-fire photo"></span>
                                        <span v-cloak>{{item.name}}({{item.iphone}})</span>
                                </li>
                        </ul>
                </div>
        </div>
</div>
<!--右侧选择联系人-->
<div class="col-xs-6 col-sm-6" >
        <div class="panel panel-success">
                <!--标题-->
                <div class="panel-heading">
                        <h3 class="panel-title" v-cloak>已选择联系人({{selectItems.length}})</h3>
                </div>
                <!--内容-->
                <div class="panel-body panel-height">
                        <ul >
                                <li v-for="(item,i) in selectItems" :key="item.id" @mouseover="isShow=i" @mouseout="isShow='hide'">
                                        <template><span class="glyphicon glyphicon-fire photo"></span>{{item.name}}({{item.iphone}})</template>
                                        <span class="glyphicon glyphicon-trash del" v-show="isShow===i" @click="delItem(item,i)"></span>
                                </li>
                        </ul>
                </div>
        </div>
</div>  

// index.js
window.onload = function(){
    new Vue({
        el:'#app',
        data:{
            isShow:'hide',
            items:[],
            selectItems:[]
        },
        mounted(){
            for (let i = 0; i < 20; i++) {
                this.items = [...this.items,{name:'肥羊'+i+2,id:i,iphone:'1856374879'+i,flag:false}]
            }
        },
        methods:{
            addItemfn:function(item){
                item.flag = true// 选中状态
                if(this.selectItems.length>0){
                    // 方法1 数组去重
                    // for (let i = 0; i < this.selectItems.length; i++) {
                    //     const el = this.selectItems[i];
                    //     if(item.id===el.id) return;
                    // }
                    // 方法二
                    let filterArr = this.selectItems.filter(v=>v.id===item.id)
                    if(filterArr.length>0) return
                    // // 方法三
                    // let mapArr = this.selectItems.map(v=>v.name)
                    // if(mapArr.includes(item.name)) return
                }
                this.selectItems.push(item)
                // 方法四
                // this.selectItems = [...new Set(this.selectItems)]
            },
            delItem(v,i){
                this.selectItems.splice(i,1)// 删除第i个
                this.items.forEach(item => {
                    if(item.id===v.id){
                        item.flag = false;//删除选中好友时,所有好友的列表也需要状态对应
                    }
                });
            }
        }
    })
}

部分css:

...
.active{
    color: #f60;
}
[v-cloak]{
    display: none;/* 去掉一闪而过的模版{{}}*/
}