最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vue电商管理系统笔记

    正文概述 掘金(番茄一个)   2021-04-22   416

    一、准备工作

    0. 给el-container设置最小宽度,防止挤压变形
    0. 给目录配置别名
    // vue.config.js文件中
    
    const path = require('path')
    // 处理路径函数
    function resolve (dir) {
      console.log(__dirname)
      return path.join(__dirname, dir)
    }
    
    
    module.exports = {
      lintOnSave: true, // 启用eslint
      // 解决[WDS] Disconnected! 报错
      devServer: {
        headers: {
          'Access-Control-Allow-Origin': '*'
        },
        hotOnly: true,
        disableHostCheck: true
      },
      // 打包时去console插件
      configureWebpack: config => {
        if (process.env.NODE_ENV === 'production') {
          config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true
        }
      },
      // 配置别名
      chainWebpack (config) {
      config.resolve.alias.set('views',resolve('src/views')).set('@', resolve('src'))
      }
    }
    
    
    1. 登录逻辑以及token
    1. 前端输入用户名密码进行登录
    2. 后端服务器验证登录成功,会生成一个token字段,返回给前端
    3. 前端将token存储在sessionStorage中
    4. 以后的每次请求都要携带此token
    
    2. API接口授权
    // 利用axios请求拦截器
    axios.interceptors.request.use(config=>{
      //为请求头对象,添加token验证的Authorization字段
      config.headers.Authorization = window.sessionStorage.getItem("token")
      return config
    })
    
    3. 解决左侧菜单刷新后默认高亮
    • 方法一:

      sessionStorage保存每次点击子菜单选项绑定的唯一index , 刷新以后created里面同步到data中定义的activePath ,el-menu的default-active绑定此activePath
      
      注意:不能是mounted生命周期中同步,具体见各个生命周期会进行的事件
      
      https://zhuanlan.zhihu.com/p/71958016
      

      vue生命周期图解

    • 方法二:el-menu的default-active直接绑定 $route.path

    二、用户管理

    4. 栅格布局
    5. Table设置索引列
     <!-- 设置索引列 -->
            <el-table-column
              label="#"
              type="index"
              width="60"
              align="center"
            >
            </el-table-column>
    
    6. 作用域插槽实现switch开关状态
    7. trycatch用法
    8. 表单绑定以及验证
    1. 先data中定义表单数据formData ,表单校验规则formRules 。 对象里有多个属性
    2. 不光 el-input 要利用v-model绑定到formData的各个属性上
    3. el-form也要用 :model 绑定到表单数据formData上
    4. el-form-item 还要用 prop绑定formRules里的具体对应的校验规则,属性值可以是数组,里面包含多个规则(见9中的 addUserFormRules)
    
    9. 邮箱和手机号自定义校验规则
    1. 先在data中定义利用回调函数自定义校验规则,注意不是在return中
    2. 再在prop绑定的校验规则中用validator指向定义的该回调,trigger:blur失焦时候触发
    
    // 定义在data中的回调 
    // 验证邮箱的规则
        var checkEmail = (rule, value, cb) => {
          // 验证邮箱的正则表达式
          const regEmail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;
    
          if (regEmail.test(value)) {
            // 合法的邮箱
            return cb();
          }
    
          cb(new Error("请输入合法的邮箱"));
        };
    
        // 验证手机号的规则
        var checkMobile = (rule, value, cb) => {
          // 验证手机号的正则表达式
          const regMobile = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/;
    
          if (regMobile.test(value)) {
            return cb();
          }
    
          cb(new Error("请输入合法的手机号"));
        };
    
    // 定义在data中的校验规则 
    // 添加表单的验证规则对象
          addUserFormRules: {
            username: [
              { required: true, message: "请输入用户名", trigger: "blur" },
              {
                min: 3,
                max: 10,
                message: "用户名的长度在3~10个字符之间",
                trigger: "blur"
              }
            ],
            password: [
              { required: true, message: "请输入密码", trigger: "blur" },
              {
                min: 6,
                max: 15,
                message: "用户名的长度在6~15个字符之间",
                trigger: "blur"
              }
            ],
            email: [
              { required: true, message: "请输入邮箱", trigger: "blur" },
              { validator: checkEmail, trigger: "blur" }
            ],
            mobile: [
              { required: true, message: "请输入手机号", trigger: "blur" },
              { validator: checkMobile, trigger: "blur" }
            ]
          }
    
    10. 表单提交之前要做预校验
    // el-form-item 要绑定prop的验证规则字段,用v-model绑定到输入框的值 ,el-form还要用 :rule 绑定到验证规则 , 用 :model 绑定到表单数据
    
    11. 侧边el-aside底部出现滚动条
    将el-aside的宽度设置小于200px , 在点击aside内部的导航栏时,底部出现横向滚动条。
    经过简单测试,宽度>=200px的时候不会有
    
    解决办法:在el-aside的内部el-menu的外部套一个el-scrollbar组件,在style属性中设置width:100% 。 类似情形如果出现纵向滚动,就设为高度100%
    
    12. 列表分页的问题
    12-1. 刷新以后分页的当前页码和每页条数被重置
    思路:
    1. pagination组件的current-page和page-size 绑定data中定义的初始值pagenum和pagesize
    2. 点击更改页码或者容量时,回掉函数内部把当前的pagesize和pagenum同步到sessionStorage中 
    3. created生命周期里重新获取并赋值给初始值 , 再请求列表数据
    
    注意: current-page和page-size要绑定的是Number类型 , 要利用parseInt()转换类型
    
    created() {
        if (window.sessionStorage.getItem("currentPage")) {
          this.params.pagenum = parseInt(
            window.sessionStorage.getItem("currentPage")
          );
        }
        if (window.sessionStorage.getItem("currentPageSize")) {
          this.params.pagesize = parseInt(
            window.sessionStorage.getItem("currentPageSize")
          );
        }
        this.getUsers();
      }
    
    12-2. 分页中删除最后一页数据自动跳到上一页
     // 解决分页删除当前页不跳转,先判断当前应该处于的页数 , 再给pagenum重新赋值
    	//  因为usersTotal总数需要在重新请求后才能同步最新数据,所以这里计算需要手动减1
          let totalPage = Math.ceil((this.usersTotal - 1) / this.params.pagesize);
          let currentPage = this.params.pagenum > totalPage ? totalPage : this.params.pagenum;
          this.params.pagenum = currentPage < 1 ? 1 : currentPage;
     // 同步sessionStorage中的currentPage
     window.sessionStorage.setItem("currentPage", currentPage);
    
    // 分页器的代码如下:
          <el-pagination
            :background="true"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="params.pagenum"
            :page-sizes="[2, 3, 4, 5]"
            :page-size="params.pagesize"
            layout="total, sizes, prev, pager, next, jumper"
            :total="usersTotal"
          >
          </el-pagination>
    
    
    // usersTotal是data中定义的用户总数 , params是用户请求的参数
          params: {
            pagesize: 4,
            pagenum: 1,
            query: "" // 用户搜索关键字 , 绑定到搜索输入框
          },
    
    12-3. 删除最后一页数据再刷新显示列表数据为空
    因为删除最后一页时候,没有同步sessionStorage中的currentPage,所以再刷新请求利用的还是最后一页的currentPage值,故请求的仍是原尾页的数据,为空 
    
     window.sessionStorage.setItem("currentPage", currentPage);
    

    三、权限管理

    13. 作用域插槽显示不同等级的标签
    <el-table-column prop="level" label="权限等级" align="center">
              <template slot-scope="level">
                <el-tag v-if="level.row.level === '0'" type="success">等级一</el-tag>
                <el-tag v-else-if="level.row.level === '1'" type="warning">等级二</el-tag>
                <el-tag v-else type="danger">等级三</el-tag>
              </template>
    </el-table-column>
    
    另外思路: 可能还可以用过滤器filters配合switch实现(???)暂时没试过
    
    14. 删除权限标签视图刷新以后展开的权限列表又关闭了
    15. 利用递归获取当前角色的所有三级权限id , el-tree默认选中
     // 递归获取已有三级权限的id
        getDefaultKeys(data, arr) {
     /* 
    思路:1. 点击分配权限,传递当前role的数据,获取当前角色的所有已有三级权限id , 组成数组 , 赋值给defaultExpandedArray
         2. 遍历roleData, 判断当前数据是否有children , 没有就把当前对象的id push到数组 
         3. 有就遍历该children数组 , 然后对每一项元素继续调用this.getDefaultKeys() 进行判断
    */
          if (!data.children) {
            arr.push(data.id);
            return false;
          } else {
            data.children.forEach(i => this.getDefaultKeys(i, arr));
          }
        },
    
    16. 给上一个角色分配权限,再点下一个角色,默认选中了上一个角色有的权限
    // 在关闭对话框时候,要把默认选中的权限 defaultCheckedKeysArray数据清空,不然点击下一个角色的分配权限,会默认选中上一个角色的权限
    
     // 关闭el-tree分配权限对话框
        closeSetRightsDialog() {
          /* 在关闭对话框时候,要把默认选中的权限 defaultCheckedKeysArray数据清空 
          不然点击下一个角色的分配权限,会默认选中上一个角色的权限
          */
          this.defaultCheckedKeysArray = [];
        }
    
    17. vue-table-with-tree-grid实现树形table表格

    vue-table-with-tree-grid

    四、商品管理

    18. moment.js格式化时间
    • 先定义全局或者局部过滤器

      import moment from 'moment'
      
      // 定义全局的时间过滤器
      Vue.filter('dateFilter', (time) => {
        return moment(time).format('YYYY-MM-DD   HH:mm:ss') // 格式:1970-01-18 20:39:05
      })
      
      
    • 引用

        <el-table-column
                header-align="center"
                align="center"
                width="250"
                label="创建时间">
                <template slot-scope="{row}">
                  {{ row.add_time | dateFilter }}
                </template>
        </el-table-column>
      
    19. el-tab标签栏和el-steps步骤条联动
    https://i.postimg.cc/xTxK7ZMy/Screenshot-2.png
    
    20. el-tab和el-form的层级关系
    21. 利用before-leave在切换tab标签之前做判断
    1. 要判断当前步骤是不是由 1 到 2
    2. this.queryInfo.goods_cat.length !== 3 时 返回 false
    
    22. upload图片上传,发请求显示无效token
    // 说明upload上传没用的axios发请求 
    // 利用headers属性,设置请求头
    
      uploadUrl: 'http://127.0.0.1:8888/api/private/v1/upload', // 图片上传服务器地址
          headerObj: {
            // upload设置请求头
            Authorization: window.sessionStorage.getItem('token')
          }
    
    23. 图片上传成功,但是缩略图不能正常显示,是白色方块
    // 因为el-upload中:file-list绑定了提交的表单信息里的pics , 导致每次pics数组里push的对象如下:
    [{"pic":"tmp_uploads\\6dc05d2211b648cefe5d4e593c952f8e.jpeg","uid":1618827444464,"status":"success"}]
    
    // 正常应该是只有pic属性
    
    
    24. vue-quill-editor富文本编辑器使用
    25. lodash的_.cloneDeep深拷贝

    五. 数据统计

    1. e-charts的使用
    • 在mounted生命周期中初始化

    六. 项目优化上线

    blog.csdn.net/weixin_4438…

    1. 顶部进度条效果 nprogress.js
    • 在main.js中利用axios拦截器实现
    import Nprogress from 'nprogress'
    import 'nprogress/nprogress.css'
    
    
    // 请求拦截器中显示进度条效果
    axios.interceptors.request.use(config => {
      Nprogress.start()
      // 为请求头对象,添加token验证的Authorization字段
      config.headers.Authorization = window.sessionStorage.getItem('token')
      return config
    })
    // 响应拦截器中停止进度条效果
    axios.interceptors.response.use(config => {
      Nprogress.done()
      return config
    })
    
    • 利用路有守卫实现
    router.beforeEach((to, from, next) => {
    if (to.path == '/login') {
        sessionStorage.removeItem('username');
      }
    let user = sessionStorage.getItem('username');
    if (!user && to.path != '/login') {
        next({path: '/login'})
      } else {
        NProgress.start();
        next()
      }
    });
    
    router.afterEach(transition => {
      NProgress.done();
    });
    
    2. build期间去掉所有的console
    babel-plugin-transform-remove-console 插件
    
    // 注意需要只在生产阶段去console 要先做环境的判断 process.env.NODE_ENV === 'production'
    
    3. 生成打包报告

    Vue电商管理系统笔记

    4. 为开发模式和发布模式指定不同的打包入口

    Vue电商管理系统笔记

    Vue电商管理系统笔记

    // main.js复制两份分别命名main-dev.js / main.prod.js
    // vue.config.js中使用chainWebpack
    module.exports = {
        // 利用when判断环境,指定不同的打包入口文件
        // 发布模式
        config.when(process.env.NODE_ENV === 'production', config => {
          // entry找到默认的打包入口,调用clear则是删除默认的打包入口
          // add添加新的打包入口
          config.entry('app').clear().add('./src/main-prod.js')
        })
        // 开发模式
        config.when(process.env.NODE_ENV === 'development', config => {
          config.entry('app').clear().add('./src/main-dev.js')
        })
    }
    
    
    5. 通过externals加载外部的CDN资源

    Vue电商管理系统笔记

    • 配置如下 :

    Vue电商管理系统笔记

    6. 优化打包element-ui

    Vue电商管理系统笔记

    7. 自定义首页标题内容

    Vue电商管理系统笔记

    Vue电商管理系统笔记

    8. 路由懒加载
    • 使用babel的话,先安装@babel/plugin-syntax-dynamic-import

    • babel.config.js中声明一下插件

    Vue电商管理系统笔记

    • 路由中改造组件导入方式

    Vue电商管理系统笔记

    9. 开启gzip压缩

    一般是后端的范围 , 需要服务器是node写的,可能需要前端做


    起源地下载网 » Vue电商管理系统笔记

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元