• 【vue后台管理系统】基于Vue+Element-UI+ECharts开发通用管理后台(上)


    项目所用技术栈

    在这里插入图片描述

    项目效果图

    在这里插入图片描述

    Vue-CLI搭建

    首先我们来说说我们为什么需要脚手架?

    以前有的时候我们简单的写个页面代码是直接写在一个html文件中,写完了可以直接打开看效果。但是如果是一个完整的项目涉及模块化以及组件化开发,这个项目想要跑起来我们不可能直接去打开某个页面看效果。毕竟一大堆vue文件我们的浏览器压根不认识。而Vue的脚手架就可以让我们快速的将一个Vue项目跑起来。我们还可以借助它将我们的项目编译成原始的html、css文件,让我们的浏览器可以认得它。

    当然这只是其中一个好处,脚手架还能帮我们进行依赖管理,版本管理等等

    我们直接使用脚手架创建一个项目my-app:

    vue create my-app
    
    • 1

    注意:
    这里不能使用驼峰命名法,不能有大写字母

    Element-UI结合脚手架

    在一个html文件中我们想使用Elemen-UI直接使用script引入外部脚本即可,Element-UI官网上的helloworld就是这么做的:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <!-- import CSS -->
        <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    </head>
    <body>
    <div id="app">
        <el-button @click="visible = true">Button</el-button>
        <el-dialog :visible.sync="visible" title="Hello world">
            <p>Try Element</p>
        </el-dialog>
    </div>
    </body>
    <!-- import Vue before Element -->
    <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
    <!-- import JavaScript -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script>
        new Vue({
            el: '#app',
            data: function() {
                return { visible: false }
            }
        })
    </script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    注意:
    script标签在没有声明类型的情况下,默认是引入外部的脚本,如果引入某个模块,资源就会加载失败。

    那么我们在项目中怎么使用Element-UI呢?

    首先我们要使用包管理工具下载Element-UI的依赖:

    npm i element-ui -S
    
    • 1

    我们来详细说说这个命令:
    在CLI创建的项目中我们使用的是包管理工具。package.json表示我们的项目配置文件:
    在这里插入图片描述
    我们可以看到devDependencies和dependencies这两个属性:

    • devDependencies表示开发环境的依赖
    • dependencies表示项目依赖

    我们项目中的node_modules文件夹就装着我们项目所需的依赖文件。上面的这条命令就是将element-ui下载到我们的node_modules文件夹中。

    对于CLI项目而言,在我们使用启动命令的时候,他会通过webpack将我们项目中的vue文件通过打包的方式变成静态资源,然后运行在我们本地的开发服务器上。(打包包括了我们项目中的依赖、组件文件、页面等)

    我们命令中的-S的作用就是:它会把我们下载的依赖添加到package.json文件中,后面即使我们没有了node_modules文件夹,我们也可以根据我们的package.json依赖文件从而重新去进行下载。

    这里有两种方式:

    • 全部引入
    • 按需引入

    全部引入

    在 main.js 中写入以下内容:

    import Vue from 'vue';
    import ElementUI from 'element-ui';
    import 'element-ui/lib/theme-chalk/index.css';
    import App from './App.vue';
    
    Vue.use(ElementUI);
    
    new Vue({
      el: '#app',
      render: h => h(App)
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    以上代码便完成了 Element 的引入。需要注意的是,样式文件需要单独引入。

    Vue.use(ElementUI)是将ElementUI里面的组件全局注入到Vue中。

    按需引入

    直接查看官方文档即可,这里不多赘述

    按需引入

    按需引入可以在代码打包的时候减小我们代码的体积。

    Vue-router的安装和配置

    安装依赖:

    npm i vue-router@3.6.5
    
    • 1

    在package.json文件中看一下是不是安装好了:
    在这里插入图片描述

    然后我们创建router文件夹,在此文件夹中创建index.js。

    因为我们是模块化工程,所以我们要在index.js文件中首先添加:

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    
    • 1
    • 2
    • 3
    • 4

    然后开始一系列的基本操作:

    • 创建路由器实例
    • 注册路由 (将路由与组件进行映射)
    • 将路由器挂载到Vue实例对象上
    • 最后使用router-view标签设置路由出口(也就是将路由匹配到的组件进行渲染)

    路由组件:
    Home.vue:
    在这里插入图片描述

    User.vue:
    在这里插入图片描述

    注意这里爆红是因为我们的name值不符合eslint的规范,我们可以在vue.config.js文件中将他关闭:
    在这里插入图片描述

    注意这里的name属性是与

    router/index.js:

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import Home from "../pages/Home"
    import User from "../pages/User"
    
    
    Vue.use(VueRouter)
    
    const router = new VueRouter({
        routes:[
            {
                path:"/home",
                component:Home
            },
            {
                path: "/user",
                component: User
            }
        ]
    })
    
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    挂载:
    在这里插入图片描述
    路由出口:
    App.vue:

    在这里插入图片描述

    然后我们通过访问http://localhost:8080/#/userhttp://localhost:8080/#/home就可以看到我们路由对应的组件了。

    首页框架搭建

    我们这里直接借助Element-UI快速布局我们的首页框架,我们的成体如下:
    在这里插入图片描述

    所以我们选择这种布局:
    在这里插入图片描述

    直接粘贴代码:

    Main.vue:

    <template>
        <div>
            <el-container>
                <el-aside width="200px">
                    Aside
                el-aside>
                <el-container>
                    <el-header>
                        Header
                    el-header>
                    <el-main>
                        <router-view>router-view>
                    el-main>
                el-container>
            el-container>
    
        div>
    
    template>
    
    <script>
        export default {
            name: "Main"
        }
    script>
    
    <style scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    左侧菜单栏的引入

    我们直接在Elemet-UI中找到对应的样式。

    我们在NavMenu 导航菜单一栏找到如下的样式:

    在这里插入图片描述
    考虑到菜单栏是一个功能比较单一的部分,所以我们把它独立封装成一个组件命名为CommonAside,并将其放在component包下:
    在这里插入图片描述

    <template>
        <div>
            <el-radio-group v-model="isCollapse" style="margin-bottom: 20px;">
                <el-radio-button :label="false">展开el-radio-button>
                <el-radio-button :label="true">收起el-radio-button>
            el-radio-group>
            <el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" :collapse="isCollapse">
                <el-submenu index="1">
                    <template slot="title">
                        <i class="el-icon-location">i>
                        <span slot="title">导航一span>
                    template>
                    <el-menu-item-group>
                        <span slot="title">分组一span>
                        <el-menu-item index="1-1">选项1el-menu-item>
                        <el-menu-item index="1-2">选项2el-menu-item>
                    el-menu-item-group>
                    <el-menu-item-group title="分组2">
                        <el-menu-item index="1-3">选项3el-menu-item>
                    el-menu-item-group>
                    <el-submenu index="1-4">
                        <span slot="title">选项4span>
                        <el-menu-item index="1-4-1">选项1el-menu-item>
                    el-submenu>
                el-submenu>
                <el-menu-item index="2">
                    <i class="el-icon-menu">i>
                    <span slot="title">导航二span>
                el-menu-item>
                <el-menu-item index="3" disabled>
                    <i class="el-icon-document">i>
                    <span slot="title">导航三span>
                el-menu-item>
                <el-menu-item index="4">
                    <i class="el-icon-setting">i>
                    <span slot="title">导航四span>
                el-menu-item>
            el-menu>
        div>
    
    template>
    
    <style>
        .el-menu-vertical-demo:not(.el-menu--collapse) {
            width: 200px;
            min-height: 400px;
        }
    style>
    
    <script>
        export default {
            name:"CommonAside",
            data() {
                return {
                    isCollapse: true
                };
            },
            methods: {
                handleOpen(key, keyPath) {
                    console.log(key, keyPath);
                },
                handleClose(key, keyPath) {
                    console.log(key, keyPath);
                }
            }
        }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    然后我们在Main组件中进行引入:
    在这里插入图片描述
    然后放到我们的侧边导航栏区域
    在这里插入图片描述

    这里引入的组件标签最好是使用小驼峰+中划线的标准形式:

    左侧菜单栏的基本实现

    一级菜单实现

    我们拿到下图这种样式之后,先跟我们目标导航栏做个对比。我们可以发现我们要做的导航栏有两种选项,一种是带子项的,另一种是不带子项的。
    在这里插入图片描述

    在这里插入图片描述

    于是我们保留导航一、导航二,将导航三、四删掉。

    然后来看看我们的菜单栏数据:

    	[
            {
              path: '/',
              name: 'home',
              label: '首页',
              icon: 's-home',
              url: 'Home/Home'
            },
            {
              path: '/mall',
              name: 'mall',
              label: '商品管理',
              icon: 'video-play',
              url: 'MallManage/MallManage'
            },
            {
              path: '/user',
              name: 'user',
              label: '用户管理',
              icon: 'user',
              url: 'UserManage/UserManage'
            },
            {
              label: '其他',
              icon: 'location',
              children: [
                {
                  path: '/page1',
                  name: 'page1',
                  label: '页面1',
                  icon: 'setting',
                  url: 'Other/PageOne'
                },
                {
                  path: '/page2',
                  name: 'page2',
                  label: '页面2',
                  icon: 'setting',
                  url: 'Other/PageTwo'
                }
              ]
            }
          ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    我们可以根据是否有children将我们的导航栏分为有孩子和无孩子的。这里我们可以使用计算属性分类:

    		 computed: {
                //筛选没孩子的
                noChildren() {
                    return this.menuData.filter(item => !item.children)
                },
                //筛选有孩子的
                hasChildren() {
                    return this.menuData.filter(item => item.children)
                }
            },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    然后将有孩子的放到导航二中去用for循环进行遍历,将没有孩子的放到导航一中去用for循环进行遍历:

    <template>
        <div>
            <el-radio-group v-model="isCollapse" style="margin-bottom: 20px;">
                <el-radio-button :label="false">展开el-radio-button>
                <el-radio-button :label="true">收起el-radio-button>
            el-radio-group>
    
            <el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
                     :collapse="isCollapse">
                <el-menu-item :index="item.name" v-for="item in noChildren" :key="item.name">
                    <i :class="`el-icon-${item.icon}`">i>
                    <span slot="title">{{item.label}}span>
                el-menu-item>
    
            el-menu>
        div>
    
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这里有几个注意点:

    我们打开页面的时候,整个导航列表应该还是展开的(不包括子栏),这个怎么去控制呢?

    我们可以查看Element-UI的官方文档:
    在这里插入图片描述
    可以发现是通过collapse属性进行控制的,那么我们将它设为false即可

    我们在遍历的时候需要一个索引key,我们可以去用name属性当作这个key

    然后就是图标问题:

    我们使用的是Element-UI里面提供的Icon图标集合,我们发现他们都有共同的前缀el-icon
    在这里插入图片描述

    然后我们的菜单数据中提供了图表的后缀,我们将前缀与后缀相结合给class赋值,即可得到对应的图标:
    在这里插入图片描述

    这里我们使用的是js字符串的模板语法

    最后一点我们在for循环的时候需要将el-menu-item中的index属性也赋值称为一个独一无二的值:
    在这里插入图片描述

    如果不设置的话点击一个选项栏,其他的选项栏也会产生高亮

    二级菜单实现

    方法和注意点与一级菜单相似,我们这里直接上代码:

    			<el-submenu index="1" v-for="item in hasChildren" :key="item.name">
                    <template slot="title" >
                        <i :class="`el-icon-${item.icon}`"></i>
                        <span slot="title">{{item.label}}</span>
                    </template>
                    <el-menu-item-group v-for="child in item.children" :key="child.name">
                        <el-menu-item :index="child.name">{{child.label}}</el-menu-item>
                    </el-menu-item-group>
                </el-submenu>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    一级二级导航栏代码整合:

    <template>
        <div>
            <el-radio-group v-model="isCollapse" style="margin-bottom: 20px;">
                <el-radio-button :label="false">展开</el-radio-button>
                <el-radio-button :label="true">收起</el-radio-button>
            </el-radio-group>
    
            <el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
                     :collapse="isCollapse">
                <el-menu-item :index="item.name" v-for="item in noChildren" :key="item.name">
                    <i :class="`el-icon-${item.icon}`"></i>
                    <span slot="title">{{item.label}}</span>
                </el-menu-item>
                <el-submenu index="1" v-for="item in hasChildren" :key="item.name">
                    <template slot="title" >
                        <i :class="`el-icon-${item.icon}`"></i>
                        <span slot="title">{{item.label}}</span>
                    </template>
                    <el-menu-item-group v-for="child in item.children" :key="child.name">
                        <el-menu-item :index="child.name">{{child.label}}</el-menu-item>
                    </el-menu-item-group>
                </el-submenu>
    
            </el-menu>
        </div>
    
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    实现效果:
    在这里插入图片描述

    菜单样式优化与less引入

    我们现在的菜单和目标相比还有很多差距:
    在这里插入图片描述

    经过对比我们要对以下的几点进行优化:

    • 背景颜色以及字体颜色、被选择时的颜色优化
    • 浏览器默认margin的优化
    • 菜单栏长度的优化
    • 菜单栏上方标题的优化
    • 去掉展开收起按钮
    • 去掉滚动条

    接下来我们一个个的说一下解决思路与代码:

    1)背景颜色以及字体颜色、被选择时的颜色优化
    我们这一块的配置都是沿用Element-UI的示例:
    在这里插入图片描述
    我们找到它的代码:
    在这里插入图片描述
    我们可以看到我们上述的几个属性都在这里设置好了,官方文档里面也有介绍:
    在这里插入图片描述
    我们直接cv过来,然后我们还有一个注意点,初始化的时候默认就选择了首页项,也就是说我们直接把首页项设为默认高亮,这个需求可以借助default-active属性来完成。完整代码如下:

            <el-menu default-active="home" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
                     :collapse="isCollapse"
                     background-color="#545c64"
                     text-color="#fff"
                     active-text-color="#ffd04b"
            >
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2)去掉展开收起按钮

    直接删除掉对应部分的代码即可:
    在这里插入图片描述

    3)浏览器默认margin,padding的优化

    我们直接在App组建的Style中对样式进行修改。

    因为最后编译的时候那些网页结构样式什么的实际都会汇总到App组件中来。

    注意:style标签不要使用scoped,否则就会只因为作用在当前组件样式,而无法改变我们规定的样式

    在这里插入图片描述

    4)去掉滚动条

    首先我们要明白为什么会出现滚动条?大多数情况是因为容器的内容大过了容器的体积,我们分析页面可以发现这个滚动条是因为el-menu的右边界有1px突出来了:
    在这里插入图片描述
    我们把这个值设为0就可以发现滚动条消失:
    在这里插入图片描述
    接下来我们进行修改:

    在CommonAside组件中:
    在这里插入图片描述

    5)菜单栏上方标题的优化

    这个地方我们选择使用less样式来解决这个问题

    我们主要使用的是less的嵌套特性,与css变化不是很大。
    我们要使用less少不了两个东西:

    • less的依赖
    • less的解析器

    安装代码(适用于本项目的版本):

    • npm i less@4.1.2
    • npm i less-loader@6.0.0

    首先我们在菜单栏使用h3标签加上我们的文字:
    在这里插入图片描述

    然后使用less语法进行修改:

    <style lang="less" scoped>
        .el-menu-vertical-demo:not(.el-menu--collapse) {
            width: 200px;
            min-height: 400px;
        }
        .el-menu {
            border-right:solid 0px #e6e6e6;
            h3 {
                text-align: center;
                font-size: 16px;
                color: #ffffff;
                font-weight: 400;
            }
        }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6)菜单栏长度的优化

    我们直接使用height=100vh即可,这里的100vh代表占满页面的高度

    在这里插入图片描述

    整体优化完毕,效果如下;
    在这里插入图片描述

    菜单点击跳转功能实现

    菜单点击跳转功能有两种方法:

    • 第一种:利用Element-UI框架提供的组件中自带的router属性(简单)
    • 第二种:利用Vue路由器身上的push方法(稍麻烦)
      • 第二种方法有几个注意点 :
        • home页重定向问题
        • 点击相同路由时会爆红(但是不影响功能):
          在这里插入图片描述

    第一种实现方法

    第一种实现方法我们只需要一行代码就可以解决!

    我们从Element-UI官方文档注意到Menu Attribute下有一个router属性:
    在这里插入图片描述

    它以index作为路由进行跳转,恰好我们是使用数据中的name属性作为index,而我们配置路由的时候正好与name属性相契合:
    在这里插入图片描述
    在这里插入图片描述

    所以我们只需要把router属性设置为true即可:
    在这里插入图片描述

    第二种实现方法

    我们在菜单上绑定点击事件并向回调函数传入数据对象,再利用这些数据对象完成路由的跳转。

    在这里插入图片描述

    在这里插入图片描述

    jumpto方法:

    			jumpTo(item){
                    if (this.$route.path !== item.path && !(this.$route.path === "/home" && item.path === "/")){
                        this.$router.push(item.path)
                    }
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这个jumpto方法就解决了点击相同路由时会爆红的问题,其中的逻辑主要有如下两条:

    • 如果要跳转的路由和当前路由一致则不跳转
    • 如果要跳转的路由为/,而当前的路由为/home则不跳转(也就是下面要说的路由重定向的情况)

    最后就是路由的重定向问题,我们发现在点击首页栏的时候地址栏显示的是:

    http://localhost:8080/#/
    
    • 1

    而我们点击主页的时候想要显示home组件,所以我们要重定向路由,我们借助redirect来实现:
    在这里插入图片描述

    如果这里路由的多级关系正不清楚,可以看几个嵌套路由的案例马上就能明白。

    header组件的实现

    我们的目标header是长这样的:
    在这里插入图片描述

    我们完成这个只需要如下三步:

    • 引入左边的按钮、文字
    • 引入右边的下拉框
    • 更改背景颜色,并完成布局

    步骤一:引入左边的按钮、文字

    我们直接在Element-UI中找到对应的按钮:
    在这里插入图片描述

    我们发现最后一排的按钮符合我们的基本预想,中间是可以有一个图片的。

    我们把代码粘过来,然后做一些修改:

    <el-button icon="el-icon-menu" size="mini">el-button>
    
    • 1

    三处修改:

    • icon的值换为菜单图标
    • 将circle属性取消,将图标变为矩形
    • 新添加一个属性size用来定义按钮的大小,并将值设为mini

    步骤二:引入右边的下拉框
    在Element-UI中找到下拉菜单栏:
    在这里插入图片描述
    这个下拉菜单就符合我们的要求,我们只需要把他的展开项换成我们的头像即可:

    修改之前:

    <el-dropdown>
      <span class="el-dropdown-link">
        下拉菜单<i class="el-icon-arrow-down el-icon--right">i>
      span>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item>黄金糕el-dropdown-item>
        <el-dropdown-item>狮子头el-dropdown-item>
        <el-dropdown-item>螺蛳粉el-dropdown-item>
        <el-dropdown-item disabled>双皮奶el-dropdown-item>
        <el-dropdown-item divided>蚵仔煎el-dropdown-item>
      el-dropdown-menu>
    el-dropdown>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    修改之后:

    		<el-dropdown class="dropdown r-part">
                <span class="el-dropdown-link">
                    <img src="../assets/user.png" alt="">
                span>
                    <el-dropdown-menu slot="dropdown">
                        <el-dropdown-item>个人中心el-dropdown-item>
                        <el-dropdown-item>退出el-dropdown-item>
                    el-dropdown-menu>
            el-dropdown>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    步骤三:更改背景颜色,并完成布局

    这里我们使用弹性布局

    如果你还不熟悉弹性布局,点击复习:
    Flex 布局语法教程

    我们使用如下的主轴对齐方式:
    在这里插入图片描述

    space-between:两端对齐,项目之间的间隔都相等。

    但是要注意:我们如果直接使用的话,我们的首页两个字会跑到中间去,所以我们可以选择用一个盒子将首页和我们的按钮装到一块,这样就可以解决这个问题。

    整体代码如下:‘

    CommenHeader.vue:

    <template>
        <div class="header-container">
            <div class="l-part">
                <el-button icon="el-icon-menu" size="mini">el-button>
                <span>首页span>
            div>
    
    
            <el-dropdown class="dropdown r-part">
                <span class="el-dropdown-link">
                    <img src="../assets/user.png" alt="">
                span>
                    <el-dropdown-menu slot="dropdown">
                        <el-dropdown-item>个人中心el-dropdown-item>
                        <el-dropdown-item>退出el-dropdown-item>
                    el-dropdown-menu>
            el-dropdown>
        div>
    template>
    
    <script>
        export default {
            name: "CommonHeader"
        }
    script>
    
    <style lang="less" scoped>
        .header-container {
            .l-part {
                font-size: 14px;
                span {
                    color: #ffffff;
                    margin-left: 10px;
                }
            }
    
            background-color: #333;
            height: 60px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 0px 20px;
    
    
    
            .dropdown {
                img {
                   height: 40px;
                    width: 40px;
                    border-radius: 50%;
                }
            }
    
    
        }
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    附:yarn和npm安装对比

    Yarn是什么?

    “Yarn是由Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具 ,正如官方文档中写的,Yarn 是为了弥补 npm 的一些缺陷而出现的。”这句话让我想起了使用npm时的坑了:

    • npm install的时候巨慢。特别是新的项目拉下来要等半天,删除node_modules,重新install的时候依旧如此。
    • 同一个项目,安装的时候无法保持一致性。由于package.json文件中版本号的特点,下面三个版本号在安装的时候代表不同的含义。
    "5.0.3",
    "~5.0.3",
    "^5.0.3"
    
    • 1
    • 2
    • 3

    “5.0.3”表示安装指定的5.0.3版本,“~5.0.3”表示安装5.0.X中最新的版本,“^5.0.3”表示安装5.X.X中最新的版本。这就麻烦了,常常会出现同一个项目,有的同事是OK的,有的同事会由于安装的版本不一致出现bug。

    • 安装的时候,包会在同一时间下载和安装,中途某个时候,一个包抛出了一个错误,但是npm会继续下载和安装包。因为npm会把所有的日志输出到终端,有关错误包的错误信息就会在一大堆npm打印的警告中丢失掉,并且你甚至永远不会注意到实际发生的错误。

    带着这些坑,我开始了解Yarn的优势及其解决的问题。

    Yarn的优点?

    • 速度快 。速度快主要来自以下两个方面:
      • 并行安装:无论 npm 还是 Yarn 在执行包的安装时,都会执行一系列任务。npm 是按照队列执行每个 package,也就是说必须要等到当前 package 安装完成之后,才能继续后面的安装。而 Yarn 是同步执行所有任务,提高了性能。
      • 离线模式:如果之前已经安装过一个软件包,用Yarn再次安装时之间从缓存中获取,就不用像npm那样再从网络下载了。
    • 安装版本统一:为了防止拉取到不同的版本,Yarn 有一个锁定文件 (lock file) 记录了被确切安装上的模块的版本号。每次只要新增了一个模块,Yarn 就会创建(或更新)yarn.lock 这个文件。这么做就保证了,每一次拉取同一个项目依赖时,使用的都是一样的模块版本。npm 其实也有办法实现处处使用相同版本的 packages,但需要开发者执行 npm shrinkwrap 命令。这个命令将会生成一个锁定文件,在执行 npm install 的时候,该锁定文件会先被读取,和 Yarn 读取 yarn.lock 文件一个道理。npm 和 Yarn 两者的不同之处在于,Yarn 默认会生成这样的锁定文件,而 npm 要通过 shrinkwrap 命令生成 npm-shrinkwrap.json 文件,只有当这个文件存在的时候,packages 版本信息才会被记录和更新。
    • 更简洁的输出:npm 的输出信息比较冗长。在执行 npm install 的时候,命令行里会不断地打印出所有被安装上的依赖。相比之下,Yarn 简洁太多:默认情况下,结合了 emoji直观且直接地打印出必要的信息,也提供了一些命令供开发者查询额外的安装信息。
    • 多注册来源处理:所有的依赖包,不管他被不同的库间接关联引用多少次,安装这个包时,只会从一个注册来源去装,要么是 npm 要么是 bower, 防止出现混乱不一致。
    • 更好的语义化: yarn改变了一些npm命令的名称,比如 yarn add/remove,感觉上比 npm 原本的 install/uninstall 要更清晰。

    在这里插入图片描述

    附:项目中的一些调试技巧

    技巧一:

    我们可以直接在控制台中进行样式的调试,等满意之后我们再去项目中进行修改:
    在这里插入图片描述

    技巧二:

    我们想要获取网页上的元素信息的时候,可以直接在样式或者计算样式中找到:
    在这里插入图片描述
    技巧三:

    我们在对结构附加样式的时候,不需要去分析自己的结构然后思考加在哪里,我们可以直接借助开发者工具,点击元素根据显示的class或者id来进行添加。

    如果你使用了Element-UI框架也可以使用,你通过工具得到的class可能在编译器中显示没有或未使用,但是当网页编译完成之后,这些框架中的组件提供的样式也会变成原生的html元素,所以最终你的样式还是会奏效。

    如果要这样的话,样式标签最好不要加scoped,否则会失效

  • 相关阅读:
    json-c 理解记录
    银行基于云原生架构下的 DevOps 建设实践经验
    windows系统docker中将vue项目网站部署在nginx上
    三天快速搭建一个属于自己的管理系统,包括前端、后端、部署上线,超级详细的介绍。
    企业运维实践-Nginx使用geoip2模块并利用MaxMind的GeoIP2数据库实现处理不同国家或城市的访问最佳...
    外卖项目05---套餐管理业务开发
    【Swift-Vapor服务器】0001、Swift-Vapor入门-环境搭建
    鸿蒙求职面试内容总结——6月3日ZR的FS项目
    java 字符串只保留数字、字母、中文
    分布式搜索引擎01
  • 原文地址:https://blog.csdn.net/zyb18507175502/article/details/127346499