Vue2企业级实战:电商后台管理系统开发全流程解析

2025-08-02 0 777

Vue2企业级实战:电商后台管理系统开发全流程解析

一、项目架构设计

电商后台管理系统技术栈:

  • Vue2:核心框架
  • Vue CLI:项目脚手架
  • Vuex:状态管理
  • Element UI:UI组件库
  • Axios:HTTP请求库

二、项目初始化与配置

1. 使用Vue CLI创建项目

npm install -g @vue/cli
vue create ecommerce-admin
cd ecommerce-admin
vue add element
npm install axios vuex vue-router --save

2. 目录结构优化

src/
├── api/               # 接口封装
├── assets/            # 静态资源
├── components/        # 公共组件
│   ├── common/        # 全局通用组件
│   └── business/      # 业务组件
├── directive/         # 自定义指令
├── filters/           # 全局过滤器
├── mixins/            # 混入
├── router/            # 路由配置
├── store/             # Vuex状态管理
├── styles/            # 全局样式
├── utils/             # 工具函数
├── views/             # 页面组件
├── App.vue            # 根组件
└── main.js            # 入口文件

三、核心功能实现

1. 权限控制方案

// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import store from '@/store'

Vue.use(Router)

const router = new Router({
  routes: [
    {
      path: '/login',
      component: () => import('@/views/Login'),
      meta: { requiresAuth: false }
    },
    {
      path: '/',
      component: () => import('@/layouts/MainLayout'),
      meta: { requiresAuth: true },
      children: [
        // 动态路由将通过addRoutes添加
      ]
    }
  ]
})

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !store.getters.token) {
    next('/login')
  } else if (to.path === '/login' && store.getters.token) {
    next('/')
  } else {
    // 动态添加路由
    if (store.getters.menus.length === 0 && store.getters.token) {
      store.dispatch('user/getUserInfo').then(() => {
        const menus = store.getters.menus
        const routes = generateRoutes(menus)
        router.addRoutes(routes)
        next({ ...to, replace: true })
      }).catch(() => {
        next('/login')
      })
    } else {
      next()
    }
  }
})

function generateRoutes(menus) {
  // 根据菜单数据生成路由配置
  // ...
}

export default router

2. Vuex状态管理

// store/modules/user.js
const state = {
  token: localStorage.getItem('token') || '',
  userInfo: null,
  menus: []
}

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token
    localStorage.setItem('token', token)
  },
  SET_USERINFO: (state, userInfo) => {
    state.userInfo = userInfo
  },
  SET_MENUS: (state, menus) => {
    state.menus = menus
  }
}

const actions = {
  login({ commit }, userInfo) {
    return new Promise((resolve, reject) => {
      login(userInfo).then(response => {
        commit('SET_TOKEN', response.token)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },
  getUserInfo({ commit }) {
    return new Promise((resolve, reject) => {
      getInfo().then(response => {
        commit('SET_USERINFO', response.user)
        commit('SET_MENUS', response.menus)
        resolve(response)
      }).catch(error => {
        reject(error)
      })
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

四、高级组件开发

1. 可编辑表格组件

<template>
  <el-table :data="tableData" border>
    <el-table-column
      v-for="col in columns"
      :key="col.prop"
      :prop="col.prop"
      :label="col.label"
      :width="col.width">
      <template slot-scope="scope">
        <template v-if="scope.row.isEdit">
          <el-input v-model="scope.row[col.prop]" />
        </template>
        <template v-else>
          {{ scope.row[col.prop] }}
        </template>
      </template>
    </el-table-column>
    <el-table-column label="操作" width="180">
      <template slot-scope="scope">
        <el-button
          v-if="!scope.row.isEdit"
          @click="handleEdit(scope.row)">
          编辑
        </el-button>
        <el-button
          v-else
          type="success"
          @click="handleSave(scope.row)">
          保存
        </el-button>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
export default {
  props: {
    data: Array,
    columns: Array
  },
  data() {
    return {
      tableData: JSON.parse(JSON.stringify(this.data))
    }
  },
  methods: {
    handleEdit(row) {
      this.$set(row, 'isEdit', true)
    },
    handleSave(row) {
      this.$set(row, 'isEdit', false)
      this.$emit('save', row)
    }
  }
}
</script>

2. 图片上传组件

<template>
  <div class="upload-container">
    <el-upload
      :action="uploadUrl"
      :headers="headers"
      :multiple="false"
      :limit="1"
      :file-list="fileList"
      :on-success="handleSuccess"
      :before-upload="beforeUpload">
      <el-button size="small" type="primary">点击上传</el-button>
      <div slot="tip" class="el-upload__tip">
        只能上传jpg/png文件,且不超过2MB
      </div>
    </el-upload>
    <img v-if="imageUrl" :src="imageUrl" class="preview" />
  </div>
</template>

<script>
export default {
  props: {
    value: String
  },
  data() {
    return {
      uploadUrl: process.env.VUE_APP_BASE_API + '/upload',
      headers: {
        Authorization: 'Bearer ' + this.$store.getters.token
      },
      fileList: [],
      imageUrl: this.value
    }
  },
  methods: {
    beforeUpload(file) {
      const isImage = file.type.includes('image/')
      const isLt2M = file.size / 1024 / 1024 < 2
      
      if (!isImage) {
        this.$message.error('只能上传图片格式!')
      }
      if (!isLt2M) {
        this.$message.error('图片大小不能超过2MB!')
      }
      
      return isImage && isLt2M
    },
    handleSuccess(response) {
      this.imageUrl = response.data.url
      this.$emit('input', this.imageUrl)
    }
  },
  watch: {
    value(val) {
      this.imageUrl = val
    }
  }
}
</script>

五、性能优化实践

1. 路由懒加载

// router/index.js
const UserManagement = () => import(/* webpackChunkName: "user" */ '@/views/system/UserManagement')
const RoleManagement = () => import(/* webpackChunkName: "role" */ '@/views/system/RoleManagement')

2. 组件按需加载

// 安装babel插件
npm install babel-plugin-component -D

// babel.config.js
module.exports = {
  plugins: [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

3. 长列表优化

<template>
  <virtual-list
    :size="60"
    :remain="8"
    :data="listData">
    <template v-slot:default="{ item }">
      <div class="list-item">
        {{ item.name }}
      </div>
    </template>
  </virtual-list>
</template>

<script>
import VirtualList from 'vue-virtual-scroll-list'

export default {
  components: { VirtualList },
  data() {
    return {
      listData: [] // 大数据列表
    }
  }
}
</script>
Vue2企业级实战:电商后台管理系统开发全流程解析
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 vue2 Vue2企业级实战:电商后台管理系统开发全流程解析 https://www.taomawang.com/web/vue2/734.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务