Element-admin从入门到精通

1,234 阅读3分钟

1、官方文档

element-admin panjiachen.gitee.io/vue-element…

element-ui element.eleme.cn/#/zh-CN/com…

2、下载安装

集成版本(选择i8n分支,进入中文版)

git clone https://github.com.cnpmjs.org/PanJiaChen/vue-element-admin.git

基础版本

git clone https://github.com.cnpmjs.org/PanJiaChen/vue-admin-template.git

3、运行

安装依赖

npm install --registry=https://registry.npm.taobao.org

启动项目

npm run dev

 4、项目结构

20210622065743989.png  

5、重命名项目

修改项目文件夹名称 修改package.jsom的name、description、authorpackage-lock.jsom的name

6、ElementUI中文版

找到 src/main.js

// import locale from 'element-ui/lib/locale/lang/en' // lang i18n
 
----------------------------------------------------------------
 
// Vue.use(ElementUI, { locale }) 
// 如果想要中文版 element-ui,按如下方式声明
Vue.use(ElementUI)

7、取消 ESLint 校验

找到vue.config.js

lintOnSave: false, // process.env.NODE_ENV === 'development',

8、菜单设置

  • 找到src/settings.js 20210622072328701.png

  • 将自己的ico图标替换在 public/favicon.ico

  • 找到Logo组件 src/layout/components/Sidebar/Logo.vue

data() {
    return {
      title: '梦学谷博客管理系统',
      logo: require('@/assets/logo-new.png') // 注意不能直接写 '@/assets/logo-new.png'
    }
  }

20210622082423268.png

  • showSettings用来设置是否显示控制面板

image.png

  • tagsView用来设置是否显示页面标签

image.png

9、icon(svg)

  • 在阿里图标,把svg下载至src/icons/svg

image.png

  • 在项目中引用 <svg-icon icon-class="password" /> // icon-class 为 icon 的名字

10、富文本tiny

  • 去除默认菜单显示
<!-- 只需修改调用代码 -->
<tinymce :height="300" v-model="content"  menubar=""></tinymce>

image.png

  • 添加字体和字号
export default {
   name: 'tinymce',
  props: {
    id: {
      type: String
    },
    value: {
      type: String,
      default: ''
    },
    toolbar: {
      type: Array,
      required: false,
      default() {
          // 第一步
          // 修改前
        // return ['removeformat undo redo |  bullist numlist | outdent indent | forecolor | fullscreen code', 'bold italic blockquote | h2 p  media link | alignleft aligncenter alignright'] 
        // 修改后
          return ['removeformat undo redo |  bullist numlist | outdent indent | forecolor | fullscreen code', 'bold italic blockquote | h2 p  media link | alignleft aligncenter alignright | fontsizeselect | fontselect'] 
      }
    },
  },
  mounted() {
    this.initTinymce()
  },
  methods: {
    initTinymce() {
    window.tinymce.init({
      toolbar: this.toolbar,
      menubar: this.menubar,
      plugins: 'advlist,autolink,code,paste,textcolor,colorpicker,fullscreen,link,lists,media,wordcount,imagetools',
           // 第二步,添加字号选项
      fontsize_formats: "8pt 10pt 12pt 14pt 18pt 24pt 36pt", 
      end_container_on_empty_block: true,
      powerpaste_word_import: 'clean',
      code_dialog_height: 450,
      code_dialog_width: 1000,
      advlist_bullet_styles: 'square',
      advlist_number_styles: 'default',
    })
   }
  }
}
  • 图片上传
// 在初始化时配置上传地址
window.tinymce.init({
    //图片上传地址
    images_upload_url: '你的服务器图片上传地址',

后端需请求参数为file,响应location为图片地址

11、router

  • 路由白名单
// src/permission.js
const whiteList = ['/login'] // no redirect whitelist

12、面包屑 Dashboar 中文显示

src/components/Breadcrumb/index.vue 中修改为首页

微信图片_20210623134417.png

13、伸缩菜单栏

  • 去除伸缩菜单栏按钮 1、 src/layout/components/Navbar.vue 注释掉Hamburger组件

image.png 2、在/src/store/modules/app.js,把opened改成true

image.png 3、app.js中还有两处注释

image.png

14、跨域及接口

  • 设置vue.config.js,注释mock
devServer: {
    port: port,
    open: true,
    overlay: {
      warnings: false,
      errors: true
    },
    proxy: {
          [process.env.VUE_APP_BASE_API]: {
            target: process.env.VUE_APP_BASE_API,
            changeOrigin: true,  //配置跨域
            pathRewrite: {
              ['^' + process.env.VUE_APP_BASE_API]: ''
            }
          }
        }
    // before: require('./mock/mock-server.js')
  }
  • .env.development设置VUE_APP_BASE_API
VUE_APP_BASE_API = 'http://localhost:80/php/'
  • 接口请求格式
// api/article.js
import request from '../utils/request';
export function fetchList(query) {
  return request({
    url: '/article/list',
    method: 'get',
    params: query
  })
}


// views/example/list
import { fetchList } from '@/api/article'
export default {
  data() {
    list: null,
    listLoading: true
  },
  methods: {
    fetchData() {
      this.listLoading = true
      fetchList().then(response => {
        this.list = response.data.items
        this.listLoading = false
      })
    }
  }
}
  • header请求头设置
// src/utils/request.js

if (store.getters.token) {
  // 你可以自定义添加header头
  config.headers['X-Token'] = getToken()
}
  • php接口格式
<?php
	header('Content-Type: text/html;charset=utf-8');
        header('Access-Control-Allow-Origin:*'); // *代表允许任何网址请求
	header('Access-Control-Allow-Methods: HEAD, GET, OPTIONS, POST, PUT');
        // 设置接收的header头,可以自定义
	header('Access-Control-Allow-Headers: X-Token,Content-Type, Content-Range, Content-Disposition, Content-Description');
	header('Access-Control-Max-Age: 1728000');
	header('Access-Control-Allow-Credentials: true');

    $data = array(
        'token'=> "admin-token"
    );
    
    $result = (object)array(
              'code'=>20000,
              'message'=>'成功',
              'data'=>$data,
            );
    echo json_encode($result);
?>

15、请求状态码与错误提示

// src/utils/request.js
// code为成功的状态码
if (res.code !== 200) {
  Message({
    message: res.msg || 'Error', // msg为错误提示
    type: 'error',
    duration: 5 * 1000
  })

16、动态菜单

  • php接口格式
<?php
    header('Content-Type: text/html;charset=utf-8');
    header('Access-Control-Allow-Origin:*'); // *代表允许任何网址请求
    header('Access-Control-Allow-Methods: HEAD, GET, OPTIONS, POST, PUT');
    header('Access-Control-Allow-Headers: Content-Type, Content-Range, Content-Disposition, Content-Description');
    header('Access-Control-Max-Age: 1728000');
    header('Access-Control-Allow-Credentials', 'true');

    $data = array(
        (object)array(
            'path'=> '/goods',
            'component'=> 'Layout',
            'redirect'=> '/goods/index',
            'name'=> 'goods',
            'meta'=> (object)array(
                'title'=> '商品管理',
                'icon'=> 'goods'
            ),
            'children'=> array(
                (object)array(
                    'path'=> 'list',
                    'component'=> "goods_list",
                    'name'=> 'goods_list',
                    'meta'=> (object)array( 'title'=> '商品列表','icon'=> 'menu' ),
                ),
                (object)array(
                    'path'=> 'coop',
                    'component'=> "goods_coop",
                    'name'=> 'goods_coop',
                    'meta'=> (object)array( 
                        'title'=> '正在撮合商品',
                        'activeMenu'=> '/project', //指定菜单高亮
                        'icon'=> 'menu' 
                    )
                )
            )
        )
    );

    $result = (object)array(
        'code'=>200,
        'message'=>'成功',
        'data'=>$data,
    );
    echo json_encode($result);
?>
  • src/router/index.js
/**
 * 定义替换组件的map对象
 */
export const componentMap = {
  'Layout':require('@/layout').default,
  'redirect_index':() => import('@/views/redirect/index').then(m=>m.default),
  'login_index':() => import('@/views/login/index').then(m=>m.default),
  'login_auth_redirect':() => import('@/views/login/auth-redirect').then(m=>m.default),
  'error_page_404':() => import('@/views/error-page/404').then(m=>m.default),
  'error_page_401':() => import('@/views/error-page/401').then(m=>m.default),
  'dashboard_index':() => import('@/views/dashboard/index').then(m=>m.default),
  'guide_index':() => import('@/views/guide/index').then(m=>m.default),
  'icons_index':() => import('@/views/icons/index').then(m=>m.default),
  //新建页面根据name替换路由
  'goods_list':() => import('@/views/goods/list/index').then(m=>m.default),
  'goods_coop':() => import('@/views/goods/coop/index').then(m=>m.default),
}
  • src/store/modules/perssion.js
// 引入componentMap和后端菜单接口
import { asyncRoutes, constantRoutes , componentMap } from '@/router'
import { getRouter } from '@/api/user'

......

// 替换route对象中的component
function replaceComponent(comp){
  if(comp.component && typeof(comp.component) == 'string'){
    comp.component = componentMap[comp.component]
  }
  if(comp.children && comp.children.length>0){
    for(let i=0;i<comp.children.length;i++){
      comp.children[i] = replaceComponent(comp.children[i])
    }
  }
  return comp
}


const actions = {
  generateRoutes({ commit }, roles) {
    return new Promise(resolve => {
      // 新添加代码 start
      // 接受后端菜单数据并进行处理
      getRouter().then(response => {
        let MyRoutes = response.data.filter(curr => {
          if(curr.children == null || curr.children.length == 0){
            delete curr.children
          }
          return replaceComponent(curr)
        })
        // 新添加代码 end
        let accessedRoutes
        if (roles.includes('admin')) {
          accessedRoutes = MyRoutes || []
        } else {
          accessedRoutes = filterAsyncRoutes(MyRoutes, roles)
        }
        commit('SET_ROUTES', accessedRoutes)
        resolve(accessedRoutes)
      }) // 增加本行代码
    })
  }
}
  • 最后去除冗余的asyncRoutes代码

17、菜单样式

  • 设置每个字菜单的高度
src/styles/sidebar.scss
// menu hover
.submenu-title-noDropdown,
.el-submenu__title {
  height: 50px; // 设置每个字菜单的高度
  &:hover {
    background-color: $menuHover !important;
  }
}
  • 设置选中菜单的颜色
src/styles/sidebar.scss
// 设置选中菜单的颜色
.el-menu-item.is-active {
   background-color: #35B4B9 !important;
}
  • src/styles/variables.scss设置子菜单颜色