前端案例分析

CommonAside

prismjs
<el-menu 
    	default-active="1-4-1" 
         class="el-menu-vertical-demo" 
         backgroundColor='#545c64' 
         textColor="#fff"
         active-text-color="#ffd04b" 
         @open="handleOpen" 
         @close="handleClose" 
         :collapse="isCollapse">
        <h3>{{ isCollapse ? '系统' : '通用后台管理系统' }}</h3>
        <el-menu-item @click="clickMenu(item)" v-for="item in noChildren" :index="item.path" :key="item.path">
            <i :class="'el-icon-' + item.icon"></i>
            <span slot="title">{{ item.label }}</span>
        </el-menu-item>
        <el-submenu v-for="item in hasChildren" :index="item.path + ''" :key="item.path">
            <template slot="title">
                <i :class="'el-icon-' + item.icon"></i>
                <span slot="title">导航一</span>
            </template>
            <el-menu-item-group v-for="(subItem, subIndex) in item.children" :key='subItem.path'>
                <el-menu-item @click="clickMenu(subItem)" :index="subItem.path">{{ subItem.label }}</el-menu-item>
            </el-menu-item-group>
        </el-submenu>
</el-menu>

el-menu

属性

  • collapse 是否水平折叠收起菜单(仅在mode为vertical时可用)
  • backgroundColor 菜单的背景颜色
  • textColor 菜单的文字颜色
  • active-text-color 激活当前菜单的文字颜色

事件

  • open

    说明:sub-menu 展开的回调

    回调参数:index: 打开的 sub-menu 的 index, indexPath: 打开的 sub-menu 的 index path

  • close

​ 说明:sub-menu 收起的回调

​ 回调参数:index: 收起的 sub-menu 的 index, indexPath: 收起的 sub-menu 的 index path

SubMenu Attribute

index: 唯一标识

prismjs
 <header>
        <div class="l-content">
            <el-button @click="handleMenu" plain icon="el-icon-menu" size="mini"></el-button>
            <!-- <h3 style="#fff">首页</h3> -->
            <el-breadcrumb separator="/">
                <el-breadcrumb-item v-for="item in tabs" :key="item.path" :to="{ path: 'item.path' }">{{item.label}}</el-breadcrumb-item>
            </el-breadcrumb>
        </div>
        <div class="r-content">
            <!--用来设置触发下拉框的方法和大小-->
            <el-dropdown trigger="click" size="mini">
                <span>
                    <img class="user" :src="userImg">
                </span>
                <!--下拉菜单项-->
                <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item>个人中心</el-dropdown-item>
                    <el-dropdown-item @click.native="logOut">退出</el-dropdown-item>
                </el-dropdown-menu>
            </el-dropdown>
        </div>
    </header>

el-breadcrumb:面包屑

  • separator:用来设置分隔符
  • to:路由跳转对象,同v-router的to

路由钩子

prismjs
router.beforeEach((to,from,next)=>{
  store.commit('getToken');
  const token = store.state.user.token;
  if (!token && to.name !== 'login') {
    next({name: 'login'});
  } else if(token && to.name === 'login') {
    next({name: 'home'})
  }else {
    next();
  }
})

store仓库

prismjs
 state: {
        isCollapse: true,
        tabsList: [
            {
                path: '/',
                name: 'home',
                label: '首页',
                icon: 'home'
            },
        ],
        currentMenu: null,
        menu: [],
    },
  mutations: {
      
  }

自动折叠功能实现

CommonHeader 在(method中实现)

prismjs
handleMenu() {
            this.$store.commit('collapseMenu');
}

CommonAside 在(computed中实现)

prismjs
isCollapse() {
            return this.$store.state.tab.isCollapse;
}

扩展(vuex)


什么是vuex?

vuex是一个专门为Vue.js应用程序开发的状态管理模式,它采用集中式存储管理所有组件的公共状态,并以相应的规则保证状态以一种可预测的方式发生变化。

  1. state中是保存的公共状态,改变公共状态的唯一方式就是通过mutation进行更改。

  2. getters属性理解为所有组件的computed属性, 也就是计算属性. vuex的官方文档也是说到可以将getter理解为store的计算属性, getters的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

  3. Mutations: mutations理解为store的methods,mutations对象中保存着更改数据的回调函数,该函数名官方规定叫type,第一个参数是state,第二个参数是payload,也就是自定义的参数。

注意:调用mutations中回调函数,只能使用store.commit(type,payload)

  1. Actions:
  2. Modules:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、出处。

CommonForm

prismjs
<template>
    <el-form ref="form" label-width="100px" :model="form" :inline="inline">
        <el-form-item v-for="item in formLabel" :key="item.label" :label="item.label">
            <el-input v-if="item.type === 'input'" :placeholder="'请输入' + item.label" v-model="form[item.model]">
            </el-input>
            <el-switch v-if="item.type === 'switch'" v-model="form[item.model]"></el-switch>
            <el-date-picker v-if="item.type === 'date'" type="date" value-format="yyyy-MM-dd" placeholder="选择日期"
                v-model="form[item.model]"></el-date-picker>
            <el-select v-if="item.type === 'select'" placeholder="请选择" v-model="form[item.model]">
                <el-option v-for="item in item.opts" :key="item.val" :label="item.label" :value="item.value">
                </el-option>
            </el-select>
        </el-form-item>
        <el-form-item><slot></slot></el-form-item>
    </el-form>
</template>

<script>

export default {
    name: 'CommonForm',
    props: {
        formLabel: Array,
        form: Object,
        inline: Boolean
    },
    data() {
        return {

        }
    }
}
</script>

<style scoped>
</style>

  • label-width 表单域的标签的宽度,作为form直接子元素的form-item会继承该值。

CommonTable

prismjs
<template>
    <div class="common-table">
        <el-table :data="tableData" height="90%" stripe>
            <el-table-column show-overflow-tooltip v-for="item in tableLabel" :key="item.prop" :label="item.label"
                :width="item.width ? item.width : 125">
                <template slot-scope="scope">
                    <span style="margin-left: 10px;">{{ scope.row[item.prop] }}</span>
                </template>
            </el-table-column>
            <el-table-column label="操作" min-width="180">
                <template slot-scope="scope">
                    <el-button size="mini" @click="handleEdit(scope.row)">编辑</el-button>
                    <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>
                </template>                
            </el-table-column>
        </el-table>
        <el-pagination
            class="pager"
            layout="prev,pager,next"
            :total="config.total"
            :current-page.sync="config.page"
            @current-change="changePage"
            :page-size="20">
<!--
	 layout: 组件布局,子组件名用逗号分隔
	 total:总条数目
	 current-page:当前页数(支持.sync)
	 page-size:每页显示条目数(支持.sync)
.sync是一个语法糖。是父组件监听子组件更新某个props的请求的缩写语法。
-->
        </el-pagination>
    </div>
</template>

<script>

export default {
    name: 'CommonTable',
    props: {
        tableData: Array,
        tableLabel: Array,
        config: Object,
    },
    methods: {
        handleEdit(row) {
            this.$emit('edit',row)
        },
        handleDelete(row) {
            this.$emit('del',row)
        },
        changePage(page) {
            this.$emit('changePage',page)
        }
    },
    data() {
        return {

        }
    }
}
</script>

<style lang="less" scoped>
.common-table {
    height: calc(100% - 62px);
    background-color:aliceblue;
    position: relative;
    .pager {
        position: absolute;
        bottom: 0;
        right: 20px;
    }
}
</style>
  • data 显示的数据
  • height: Table的高度,默认为自动高度。如果是数值则单位为px
  • stripe: 是否为斑马纹 默认为false
  • show-overflow-tooltip 当内容过长内隐藏时显示 tooltip

知识回顾: 插槽

作用域插槽就是在父组件中使用子组件中的数组

CommonTag

prismjs
<template>
    <div class="tabs">
        <!--
		closeable 是否可以关闭
		effect 主题
	-->
        <el-tag size="small" v-for="(tag,index) in tags" :key="tag.name" :closable="tag.name !== 'home'"
        :effect="$route.name === tag.name ? 'd' : 'plain'"
        @click="changeMenu(tag)"
        @close="handleClose(tag,index)">
            {{tag.label}}
        </el-tag>
    </div>
</template>

<script>
import { mapState,mapMutations } from 'vuex';
export default {
    name: 'CommonTag',
    data() {
        return {

        }
    },
    computed: {
        ...mapState({
            tags: state => state.tab.tabsList
        })
    },
    methods: {
        ...mapMutations({
            close: 'closeTag'
        }),
        changeMenu(item) {
            this.$router.push({name: item.name});
        },
        handleClose(tag,index) {
            const length = this.tags.length -1;
            this.close(tag);
            // this.$store.commit("closeTag",tag);
            if (tag.name !== this.$route.name) {
                return;
            }
            if (index === length) {
                this.$router.push({
                    name: this.tags[index-1].name
                })
            } else {
                this.$router.push({
                    name: this.tags[index].name
                })
            }
        }
    }
}
</script>

<style lang="less" scoped>
.tabs {
    padding: 20px;
    .el-tag {
        margin-right: 15px;
        cursor: pointer;
    }
}
</style>

Ajax

posted @   wzpro  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示