文章目录

  • 一、项目概述
    • 1.电商系统基本业务概述
    • 2.电商系统后台管理系统的功能划分
    • 3.项目的开发模式及技术选型
  • 二、项目初始化
    • 前端项目初始化
    • 安装element-ui
    • 安装axios
    • 码云
    • 后端项目的环境安装配置,p8
  • 三、登录、退出功能
    • 登录概述
      • 登录页面:
    • 语法格式化
      • 格式化语法:
      • 禁用部分语法规则,eg:
      • 全局样式:
      • `el-form`绑定数据:
    • 表单验证
      • 重置表单数据 和 提交前的校验(表单预验证):参考项目。
      • 请求数据
    • 路由守卫
    • 退出
      • import的格式化
  • 四、主页布局
    • header:
    • menu:
      • 用户列表:
      • 编辑用户
      • 删除用户
      • 分配角色
    • 用户、角色、权限
    • 商品分类,eg:
    • 商品管理-参数管理

b站: https://www.bilibili.com/video/BV1bE411p7As?p=2

项目地址:https://www.escook.cn/vue-shop/#/login
https://www.liulongbin.top/#/login

一、项目概述

1.电商系统基本业务概述

电商系统一般都提供了:pc端、移动app端、移动web端、微信小程序等多种终端访问方式。对应了不同角色的人使用的。

eg:京东:
1.pc端:https://www.jd.com/
2.移动web:https://m.jd.com/ (手机浏览器打开京东网站)
3.app:京东app
4.小程序:京东小程序
5.pc后台管理:后台管理员使用的,是我们准备学习的;其他的用户使用的。

对应新运力的:超管(pc),租赁和资产(pc)、承租人(App)、小程序(网点)

2.电商系统后台管理系统的功能划分

3.项目的开发模式及技术选型

电商后台管理系统整体采用前后端分离的开发模式,其中前端项目是基于Vue技术栈的SPA项目。

后端:主要操作数据库,并向前端暴露一些api接口。
前端:绘制页面,并通过ajax调用api接口。

技术选型:

  • 前端技术栈:
    Vue
    Vue-router
    Element-UI
    Axios
    Echarts

  • 后端技术栈
    Node.js
    Express
    Jwt:状态保持的一个工具,模拟session的一个登陆记录功能。
    Mysql:数据库
    Sequelize:操作数据库的一个框架。

二、项目初始化

前端项目初始化

1.安装vue-cli
2.通过cli创建项目
3.配置路由
4.配置Element-UI
5.配置Axios
6.初始化git远程仓库,托管项目到Github或者码云中

vue及cli的版本查看:

  • vue版本查看:
npm list vue // 进入项目中,使用这个命令

或者:进入项目中package.json文件直接查看

  • vue/cli版本查看:
vue -V  // 查看cli的版本,不是vue的版本  vue --versionnpm uninstall vue-cli -g  // 卸载cli-2.x
npm install @vue/cli -g // 安装cli-3.x

项目地址:https://github.com/ly1994lyy/Vue_Element_ShopManage

我是使用的版本:

@vue/cli 4.2.2
vue@2.6.11
// 创建项目:
vue ui

vue_shop即为项目名称。
init:第一次git的commit信息的内容,随意写。

进入到预设面板(presets):
1.自己保存过的。
2.默认的。
3.手动配置。手动配置如下展示。

进入到功能面板(features)
手动配置

1.babelLinter/Formatter 默认是选中的,那么必须安装的。
2.选择router使用配置文件(use config files),然后下一步(选的比较少)
其中的不选中,如果用到的话,再安装。
bable:
linter:格式化代码,语法检查
router:路由
配置文件:将插件的配置保存在各自的配置文件(eg:.babelrc)中。

进入到配置面板(configuration):
1.选择模式:hash还是history的,我们用hash的(兼容性更强,所以关闭状态),
2.linter/formatter使用standard的那个,即(ESLint+Standard config),
3.lint on save // 保存后,就格式化文件

是否保存为新的预设(save as a new preset):
名称为:vue_shop_preset,自己随意写的。

项目创建成功。

安装element-ui

  • 安装element-ui(在ui界面)- 插件中:

搜索:element,
结果:vue-cli-plugin-element 1.0.1 安装即可,安装完成后需要配置一下:


全局导入:fully import,默认的。
按需导入:import on demand,修改为按需导入的。

安装axios

  • 安装axios - UI界面- 在依赖中:
    安装依赖,

    启动项目:(运行成功后,启动app)
    访问:localhost:8080。

手动安装element-ui
element-ui官网:https://element.eleme.cn/#/zh-CN/component/installation

npm i element-ui -Snpm install babel-plugin-component -D // 按需导入的时候,需要babel,并配置一下

修改babel.config.js或者.babelrc文件。

参考:https://blog.csdn.net/li522021642/article/details/82851246
https://blog.csdn.net/weixin_44143279/article/details/110648868
新建element文件夹,并index.js:

import {Pagination,Dialog,// ...
} from 'element-ui'const element = {install: function (Vue) {Vue.use(Pagination)Vue.use(Dialog)// ....Vue.prototype.$loading = Loading.serviceVue.prototype.$msgbox = MessageBoxVue.prototype.$alert = MessageBox.alertVue.prototype.$confirm = MessageBox.confirmVue.prototype.$prompt = MessageBox.promptVue.prototype.$notify = NotificationVue.prototype.$message = Message}
}
export default element

main.js:

import 'element-ui/lib/theme-chalk/index.css' //element-ui样式引入
import element from './element-ui/index' //element-ui文件夹下Vue.use(element) // 这种方式叫:按需引入的代码单独分割一下

手动安装axios
axios官网:http://www.axios-js.com/zh-cn/docs/

npm install axios

码云

github服务器在国外;码云服务器在国内,快一些。

https://gitee.com/

第一次登录后是不可以创建项目的,需要配置下。

注册登录后,是要配置公钥的。
设置>SSH公钥:

公钥教程地址:https://gitee.com/help/articles/4181#article-header0

生成公钥:在cmd中,输入:ssh-keygen -t rsa -C "xxxxx@xxxxx.com",替换为自己码云的邮箱(自己去设置中找去:基本设置-多邮箱管理),生成公钥后,会提示文件路径在哪里的(文件:id_rsa.pub)。
路径:/Users/likaipeng/.ssh/id_rsa
查看文件内容:cat ~/.ssh/id_rsa.pub // cat就有权限查看了,根sodu很像。

复制内容到公钥中即可(码云后面的描述不正确)。

测试公钥是否ok了:

ssh -T git@gitee.com  // 添加信任  添加信任后(yes),再次执行

若返回 Hi XXX! You've successfully authenticated, but Gitee.com does not provide shell access. 内容,则证明添加成功。

mac使用:
查找文件路径:
拖拽文件到terminal中,会显示文件路径。
command+shift+g:跳转到地址的快捷键。

创建仓库:

注:使用readme文件初始化这个仓库 ,一定不要选中。

// Git 全局设置:git config --global user.name "神zhi殇"
git config --global user.email "tomorrow_123@163.com"// 本地没有项目的时候:创建 git 仓库:
mkdir vue_admin
cd vue_admin
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/lkp_ksbk/vue_admin.git
git push -u origin master// 本地已经通过cli生成项目的:已有仓库
cd existing_git_repo
git remote add origin https://gitee.com/lkp_ksbk/vue_admin.git
git push -u origin master

后端项目的环境安装配置,p8

1.安装MySQL数据库,使用phpStudy.exe,启动即可(包括apache和MySQL),并初始化数据库脚本。
2.安装Node.js环境
3.配置项目相关信息(关闭apache,并初始化数据库脚本)
4.启动项目
5.使用Postman测试后端项目接口是否正常

1.初始化mySql脚本。脚本路径:vue_api_server>db>mydb.sql。
phpStudy>mysql管理器>mysql导入导出>
密码root;还原文件:mydb.sql路径;还原到数据库名:mydb;

验证:其它选项菜单>mysql工具>打开数据库目录>能看到一个mydb文件且里面很多文件,那就是ok了。

2.启动node。 vue_api_sever文件件就是node项目。先装包,再node app.js
3.使用postman验证接口是否成功。

停止apache:其他选项菜单>服务管理器>apache>停止。

phpStudy没有mac版本的。

// node项目:
npm install  // 装包 node app.js // 启动后端服务

三、登录、退出功能

测试登录接口:
在这里插入图片描述

登录概述

登录业务流程
1.登录,2.调接口验证,3.根据响应状态跳转到页面,

登录业务的技术点:
1.http是无状态的。登录成功后,需要记录登录的状态。可以使用cookie、session方式,token方式。
2.通过cookie在客户端记录状态。
3.通过session在服务端记录状态。
4.通过token方式维持状态。

什么情况下用cookie和session,什么情况下用token???

  • 前后端不存在跨域问题的时候,用cookie和session。
  • 前后端存在跨域问题,使用token方式。

登录页面element-ui组件:
el-formel-form-itemel-inputel-buttonel-icon

main.js入口:
render App.vue,
引入路由,
引入element,

清空了项目:app.Vue清空,路由配置删除,views删除,components删除。
components/Login.vue:

<template><div>登录组件</div>
</template><script>
export default {};
</script><style lang="less" scoped>
</style>

配置路由:

// @ is an alias to /src
import Login from '@/components/Login' // @开头的。{ path: "/", redirect: "/login" },
{ path: "/login", component: Login }

路由占位符:

<router-view></router-view>
登录页面:

语法格式化

格式化语法:

根目录下新建.prettierrc文件,这是一个json格式的配置文件,不能有注释:

{"semi": false, // 末尾不加分号"singleQuote": true, // 使用单引号"trailingComma": "none", // //对象后面默认添加逗号去除掉
}
Unexpected trailing comma =>  comma-dangle  // 后面多了一个逗号

vscode中,Prettier: Trailing Comma,设置为无。

禁用部分语法规则,eg:
logout() {} // logout与括号之间没有空格,但是也会报错,eg:Missing space before function parentheses  space-before-function-paren

我们认为这不是语法错误,手动关闭掉这个错误校验:
复制:space-before-function-paren,在.eslintrc.js中,rules:

'space-before-function-paren':0

重新编译后,就ok了。

 Expected indentation of 0 spaces but found 2   // indentA space is required after '{'    //   object-curly-spacing

参考:https://blog.csdn.net/u011350541/article/details/81049761

直接关闭eslint的把,费劲:

// vue.config.js:
module.exports = {lintOnSave: false
}
  • 语法错误vscode报一堆错误:

在vscode-设置中搜索下面的设置:

error  Trailing spaces not allowed   ==>  no-trailing-spaces // 空对象,不用有空行
Too many blank lines at the end of file. Max of 0 allowed ==> no-multiple-empty-lines // 文件结尾不能太多空行,只能有一个Strings must use singlequote ==> quotes // 都是用单引号(vscode,搜索singlequote,修改为单引号,格式化后就ok了)error  Extra semicolon ==> semi  // 结尾有分号,那么报错;vscode,搜索semi,修改为结尾不用分号,格式化后就ok了)
  • 路由报错:
vue-router.esm.js?8c4f:16 [vue-router] Non-nested routes must include a leading slash character. Fix the following routes:
- login

注:非嵌套路由必须包含前导斜杠字符

  • css解析错误

在使用less写css的时候,发现报错:

Error: Can't resolve 'less-loader' // 写less语法的是报错,没有配置less-loader。

UI视图中:开发依赖中安装less和less-loader(都需要安装一下),然后重启项目。


这个错误是因为less-loader版本太高了。

  • 修改package.json文件:
    修改less和less-loader的版本为^3.11.3^6.1.1, 然后删除node_modules文件夹后重新npm install
  • 卸载,并安装指定版本
npm uninstall less less-loadernpm install less@3.11.3 less-loader@6.1.1 --save-dev
全局样式:

src/assets/css/global.css,在main.js中import后,可以生效。

水平垂直居中:

.login_box{width: 450px;height: 300px;background: #FFF;border-radius: 3px;position: absolute;left:50%;top:50%;/*margin-left:-225px;*//*margin-top:-150px;*/transform: translate(-50%,-50%);
}
  • element-ui 报错
[Vue warn]: Unknown custom element: <el-form> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

按需导入的,所以要自己加组件。

imported multiple times  import/no-duplicates // 重复导入的话,错误// error, eg:
import { Button } from 'element-ui'
import { Form, FormItem } from 'element-ui'
import { Input } from 'element-ui'// ok
import { Button, Form, FormItem, Input } from 'element-ui'

默认form表单是box-sizing:content-box,改为box-sizing: border-box;即可。

给input增加icon:

// 属性方式:
<el-inputplaceholder="请输入内容"prefix-icon="el-icon-search"v-model="input2">
</el-input>// slot方式:
<el-inputplaceholder="请选择日期"v-model="input3"><i slot="suffix" class="el-input__icon el-icon-date"></i>
</el-input>

iconfont的使用:
src/assets/fonts/iconfont.css,直接在main.js中引用即可。

// fonts文件直接全部复制粘贴在assets下面。
import './assets/fonts/iconfont.css'

使用:

// 具体的参考demo中的使用(自定义了fontFamily或者prefix等)
<el-input prefix-icon="iconfont iconuser"></el-input><i slot="prefix" class="iconfont iconmima"></i>
data() {} // data后面没有空格,语法报错。// 错误信息
Missing space before function parentheses  space-before-function-paren// 解决:
// 1.id方式,js的:
javascript.format.insertSpaceBeforeFunctionParenthesis// 2.json方式,ts的:
"typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false
el-form绑定数据:

form上:model="loginForm" ,表单元素增加:v-model="loginForm.username"

// <el-form label-width="0px" :model="loginForm"></el-form> // :model
<el-form label-width="0px" class="login_form" :model="loginForm"><el-form-item><el-inputv-model="loginForm.username"placeholder="请输入账号"prefix-icon="iconfont icon-user"></el-input></el-form-item><el-form-item><el-inputtype="password"v-model="loginForm.password"placeholder="请输入密码"prefix-icon="iconfont icon-3702mima"></el-input></el-form-item><el-form-item class="btns"><el-button type="primary">登录</el-button><el-button type="info">重置</el-button></el-form-item></el-form>

增加切换是否显示密码的功能:

<el-input v-model="loginForm.password" v-bind:type="isShowPassword?'text':'password'"><i slot="prefix" class="iconfont iconmima"></i><i v-if="!isShowPassword" slot="suffix" class="el-icon-soccer" @click="changeEye"></i><i v-if="isShowPassword" slot="suffix" class="el-icon-baseball" @click="changeEye"></i>
</el-input>

表单验证

form上:rules="loginRules"el-form-item增加:prop="username"

  • 表单验证:参考项目。
    1.表单绑定rules。:rules="loginRules"
    2.编写rules规则。
    3.给el-form-item增加prop属性。prop="username"
重置表单数据 和 提交前的校验(表单预验证):参考项目。

form增加:ref="loginFormRef"

重置:
1.el-form添加一个ref引用(eg:loginFormRef)。获取表单实例对象
2.使用:this.$refs.loginFormRef.resetFields()。resetFields是 form中的methods。
对整个表单进行重置,将所有字段值重置为初始值移除校验结果

校验:

this.$refs.loginFormRef.validate((valid) => {console.log(valid) // boolean:是否校验成功
})

validate也是 form中的methods。

请求数据

axios安装包了,但是还没配置。

// main.js中:
import axios from 'axios' // 引入包
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/' // 设置根路径
Vue.prototype.$http = axios // 挂载到原型对象上,使用:this.$http
  • 启动mySQL:
    其它选项菜单>服务管理器>MySQL>启动。
    node启动:node app.js

  • 接口的处理

const result = this.$http.post('login', this.loginForm)
console.log(result) // result返回是Promise。

如果方法返回值是promise,可以使用async和await方法来简化这次promise操作。
await只能用在被async修饰的方法中。


解决办法:npm i core-js

// 箭头函数修饰为异步函数,返回值为await。
this.$refs.loginFormRef.validate(async valid => {console.log(valid) // 返回false,验证不通过;返回true,调用登录接口if (!valid) return falseconst result = await this.$http.post('login', this.loginForm)console.log(result) // {data:{},config:{},headers:{},request:{},status:200,statusText:'OK'}
})

返回的result是一个axios修饰过的对象,我们只要data就好了(data是接口返回的数据)。所以,结构赋值:

const { data: res } = await this.$http.post('login', this.loginForm) // 取data属性,重命名为res。
console.log(res) // res就是data(我们想要的数据)

注:async和await
解构赋值

账号密码:admin/123456

if (res.meta.status !== 200) return this.$message.error('登录失败')
this.$message.success('登录成功')

message的使用:

// element.js
import { Message } from 'element-ui' // message特殊,需要挂在Vue上
Vue.prototype.$message = Message// 使用:
this.$message.error('登录了要')

登录后,把token存储在客户端,存在session中,然后跳转到home页面。
1.其他接口必须在登录后才可以访问。
2.token在网站打开期间有效,所以存在session中。
3.跳转到home页面。路由地址: /home

sessionStorage.setItem('token', '123abc')
window.sessionStorage.setItem('token', '123abc')
this.$router.push('/home')

文件最后一行是newLine:

"files.insertFinalNewline": true

路由守卫

如果用户没有登录,那么通过url访问特定页面,需要重新导航到登录页面。

全局前置守卫:

router.beforeEach((to, from, next) => {// 三个参数console.log(to) // 要访问的路径console.log(from) // 从哪个路径来的额next() // next()放行,可以到to页面;next('/login')强制跳转到login页面。
})

router.js:

router.beforeEach((to, from, next) => {// 如果访问login,那么可以放行if (to.path === '/login') return next()// 获取tokenconst tokenStr = sessionStorage.getItem('token')// 没有token,强制跳转到loginif (!tokenStr) return next('/login')// 有token,可以跳转路由next()
})

退出

清除掉本地的token,然后跳转到login页面。

// 清除token
sessionStorage.removeItem('token')
// 跳转到登录页面
this.$router.push('/login')
import的格式化

element-ui,按需导入的时候,import语句合并。

四、主页布局

element-ui:组件名称就是类名。

分析:

  • el-container,

    • el-header,el-container

      • el-aside,el-main

header:

Container布局容器,参考项目。
左侧:logo+文字;
右侧:退出按钮;

menu:

  • el-menu

    • el-submenu

      • el-menu-item
    • el-menu-item
<el-menubackground-color="#333744"text-color="#fff"active-text-color="#ffd04b"><!--包含自己菜单--><el-submenu index="2"><!--一级菜单内容--><template slot="title"><i class="el-icon-location"></i><span>一级菜单</span></template><!--二级菜单内容--><el-menu-item index="2-1"><i class="el-icon-setting"></i><span slot="title">二级菜单1</span></el-menu-item><!--二级菜单内容--><el-menu-item index="2-2"><template slot="title"><i class="el-icon-search"></i><span>二级菜单2</span></template></el-menu-item></el-submenu><!--只有一级菜单--><el-menu-item index="4"><i class="el-icon-setting"></i><span slot="title">导航四</span></el-menu-item></el-menu>
  • 布局和样式:菜单树,NavMenu导航菜单,参考项目。
  • 请求数据
    请求菜单数据,通过axios请求拦截器添加token。
// axios请求拦截
axios.interceptors.request.use(config => {console.log(config) // {baseURL:'xxx',data:{},headers:{},method:'post',// ....}// 为请求头对象,添加Token验证的Authorizationconfig.headers.Authorization = window.sessionStorage.getItem('token')return config // 最后必须return config
})

baseURL:是自己配置的。
data:接口的body。
header:头部信息。

注:
1.路由守卫:token
2.拦截器:token

调用菜单接口(异步及结构赋值):

methods: {async getMenuList () {const { data: res } = await this.$http.get('menus')if (res.meta.status !== 200) return this.$message.error(res.meta.msg)this.menuList = res.dataconsole.log(res)}
},

问题:
1.vscode:console.log的快捷键
2.复制了一个菜单list在vue中,但是语法报错,且太多报错,不能挨个解决,怎么办?
3.

设置代码片段:
首选项->用户代码判断->javascript,设置(有一个默认注释的example):

"Print to console": {"prefix": ".log","body": ["console.log('$1')$2"],"description": "Log output to console"
}// .log是快捷键,迅速调到$1,且有引号,tab后,调到$2,没加引号。

如果太多错误,不想解决了的话:

不校验某个模块的语法,eg:

You may use special comments to disable some warnings.
1.Use // eslint-disable-next-line to ignore the next line.
2.Use /* eslint-disable */ to ignore all warnings in a file.

渲染菜单:

v-for="item in menuList" :key="item.id"

菜单的index属性,只接受字符串,错误提示如下:

Invalid prop: type check failed for prop "index". Expected String with value "125", got Number with value 125.

修改菜单选中高亮颜色.

修改菜单的icon:
接口没有返回,怎么改icon呢?
1.可以直接使用iconfont的图标。
2.使用一个对象,根据id匹配icon。

<i :class="icnosObj[item.id]"></i>icnosObj: {125: 'iconfont icon-users',103: 'iconfont icon-tijikongjian',101: 'iconfont icon-danju',102: 'iconfont icon-shangpin',145: 'iconfont icon-baobiao',
}

菜单默认只能展开一个,其他的关闭:

// el-menu加一条属性:
:unique-opened='true' // boolean值,前面要加冒号的。

菜单默认右多1px:

.el-menu {border-right: solid 1px #e6e6e6; // 去掉border即可。
}

折叠和展开菜单的问题:
el-menucollapse属性可以控制.:collapse="isCollapsed"
折叠动画可以关闭掉:collapse-transition:collapse-transition="false"

菜单栏随着折叠w变化:

<el-aside :width="isCollapsed?'64px':'200px'">

路由重定向:重定向到一个welcome页面(子路由):

  {path: '/home',component: Home,redirect: '/welcome', // 显示路由:/welcome;显示/home重定向到了/welcomechildren: [{ path: '/welcome', component: Welcome }// { path: '/', redirect: 'welcome' } // 如果诶呦redirect,有本行,那么显示路由:/home/welcome]}

菜单开启路由模式:
router:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转

       <el-menuunique-opened="true"background-color="#333744"text-color="#fff"active-text-color="#409eff":collapse="isCollapse":collapse-transition="false"router>
// router:相当于:`:router="true"`,index就是跳转地址。所以index才不能为number类型。

所以index由id修改为path字段;且路由是/开头的,需要补充一下。

  • 菜单高亮:default-active 当前激活菜单的 index
default-active="/roles" // 写死的情况:default-active="activePath" // 点击菜单的时候,给activePath赋值,并记录到session中;created的时候,获取session中的值。
用户列表:

用户列表:component/user/users,并配置路由。

  • 面包屑:el-breadcrumb

  • card的使用(带box-shadow的):

<el-card class="box-card">123
</el-card>
  • search模块
    使用了栅格布局。
<el-row :gutter="20"><el-col :span="6"><div class="grid-content bg-purple">1</div></el-col><el-col :span="6"><div class="grid-content bg-purple">2</div></el-col><el-col :span="6"><div class="grid-content bg-purple">3</div></el-col><el-col :span="6"><div class="grid-content bg-purple">4</div></el-col>
</el-row>
  • 获取列表接口
    接口:users,get,
    参数:{query,pagenum,pagesize}
this.$http.get('users', { params: this.queryInfo}) // get第二个参数:{params:{}}
// 返回结构:pagenum: 1,total: 4,users:[]
  • table的使用
<!--data:渲染的list;border:边框线;stripe:斑马线;prop:渲染的key;-->
<el-table :data="userList" border stripe style="width: 100%"><!--索引列: type="index"--><el-table-column type="index"></el-table-column><el-table-column prop="username" label="姓名" width="120"></el-table-column><el-table-column prop="email" label="邮箱" width="180"></el-table-column><el-table-column prop="mobile" label="电话"></el-table-column><el-table-column prop="role_name" label="角色"></el-table-column><!--需要特殊处理的列--><el-table-column prop="mg_state" label="状态"><template slot-scope="scope"><!--当前行的数据-->{{scope.row}}--><!--是否显示-->{{scope.row.mg_state ? '是' : '否'}}==><!--switch显示,双向绑定--><el-switch v-model="scope.row.mg_state"></el-switch></template></el-table-column><!--操作列:不需要prop属性--><el-table-column label="操作" width="180"><template slot-scope="scope"><!--{{scope.row}}--><el-button type="primary" icon="el-icon-edit" size="mini" @click="edit(scope.row)"></el-button><el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteUser(scope.row)"></el-button><el-button type="warning" icon="el-icon-setting" size="mini" @click="assign(scope.row)"></el-button></template></el-table-column></el-table>

propslot-scope同时存在的时候,slot-scope优先级高。

特殊需要操作的:

<el-table-column label="状态">// 作用域插槽,scope.row:当前行数据的所有内容<template slot-scope="scope">{{scope.row}}</template>
</el-table-column>
<el-table-column label="状态">// 作用域插槽<template slot-scope="scope"><el-switch v-model="scope.row.status"></el-switch></template>
</el-table-column>

序号列:

<el-table-column type="index"></el-table-column>

iconBtn没有文字,所以用tooltip,hover到tooltip上,tooptip不消失(不消失的话会遮盖别的按钮):

<el-tooltip content="分配角色" :enterable="false">   // 鼠标是否可进入到 tooltip 中
  • 分页
//
<el-pagination@size-change="handleSizeChange" // size改变@current-change="handleCurrentChange" // page改变:current-page="queryInfo.pagenum" // page:page-sizes="[1, 2, 3, 4]" // 页码切换:page-size="queryInfo.pagesize" // sizelayout="total, sizes, prev, pager, next, jumper":total="total"> // total
</el-pagination>
  • 修改用户状态
async changeStatus (item) {console.log('changeStatus:', item)// users/:id/state/:mg_stateconst { data: res } = await this.$http.put(`users/${item.id}/state/${item.mg_state}`)console.log('修改用户状态-res:', res)if (res.meta.status !== 200) {// 失败的话,前端页面也要更改回去。item.mg_state = !item.mg_statereturn this.$message.error(res.meta.msg || '失败')}this.$message.success(res.meta.msg || '成功')}

vscode快捷键:
ctr+b:折叠目录栏

  • 搜索功能
    输入内容,点击搜索,查询;想在查询全部,增加一个清空按钮,点击清空,就查询全部;

input的事件:

Input Events
事件名称    说明                      回调参数
blur    在 Input 失去焦点时触发 (event: Event)
focus   在 Input 获得焦点时触发 (event: Event)
change  仅在输入框失去焦点或用户按下回车时触发 (value: string | number)
input   在 Input 值改变时触发  (value: string | number)
clear   在点击由 `clearable` 属性生成的清空按钮时触发

使用clear事件。

添加用户:

  • 弹框dialog =>打开弹框,并输入form表单
  • 自定义校验器 =>校验邮箱和手机号的正确性
  • 弹框(事件) =>重新打开弹框的时候,清空表单和校验错误提示。
  • 接口
  data () {// 校验邮箱var checkEmail = (rule, value, cb) => {var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/if (reg.test(value)) {return cb()}cb(new Error('请输入合法的邮箱'))}// 校验手机号var checkMobile = (rule, value, cb) => {var reg = /^1[34578]\d{9}$/if (reg.test(value)) {return cb()}cb(new Error('请输入合法的手机号'))}return {userList: [],total: 10}},
// 校验规则使用:email: [{ required: true, message: '请输入邮箱', trigger: 'blur' },{ validator: checkEmail, trigger: 'blur' }],
Events
事件名称    说明     回调参数
open    Dialog 打开的回调    —
opened  Dialog 打开动画结束时的回调   —
close   Dialog 关闭的回调    —
closed  Dialog 关闭动画结束时的回调   —
// 新增用户接口:post users
// 参数:username password email mobile
const { data: res } = await this.$http.post('users', this.userForm)
编辑用户

查询用户信息:get,users/:id
编辑:

// 编辑用户接口:put users/:id
// 参数 email mobile
const { data: res } = await this.$http.put(`users/${this.editForm.id}`, {email: this.editForm.email || '',mobile: this.editForm.mobile || ''
})
删除用户

this.$confirm的使用:
confirm返回是一个promise,可以使用async-await的方法。
确认的时候,返回:confirm(一个字符串)
但是cancel的时候,报错,所以需要一个catch方法,返回错误信息。

async removeUserById (id) {const confirmResult = await this.$confirm('此操作将永久删除该用户,是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).catch(err => {return err})// .catch(err => err) // 去除{},然后省略return。// catch捕获错误。console.log(confirmResult) // confirm || cancel}
分配角色

弹框,接口

提交新分支:

git push -u origin user

用户、角色、权限

权限:components/power/Rights.vue
角色:components/power/Roles.vue
1.面包屑,card,table,list接口
2.面包屑,card,table,新增,编辑,删除,分配权限

// 获取权限列表接口:get rights/:type   type:list||tree
const { data: res } = await this.$http.get('rights/list')// 角色列表接口:get roles
const { data: res } = await this.$http.get('roles')

v-if,v-else-if,v-else。

<el-tag v-if="scope.row.level == 0">一级</el-tag>
<el-tag type="success" v-else-if="scope.row.level == 1">二级</el-tag>
<el-tag type="warning" v-else>三级</el-tag>


用户:登录的每一个账号
权限:账号拥有的能力,eg:列表的增、删、改、查的某个权限。
没有把权限直接绑定在用户上,而是通过角色。
权限分配给角色,然后角色分配给用户。

表格展开用:

 // 展开列
<el-table-column type="expand"><template slot-scope="scope">// 自己渲染所有的页面内容{{scope.row}}</template>
</el-table-co<el-table-column type="index" label="序号"></el-table-column> // 索引列

角色列表:
新增、编辑和删除功能跟用户列表一样,自己去做。

权限折叠显示:
1.先渲染一级菜单,然后修改样式(tag,border,右箭头icon)
2.渲染二级菜单,修改样式(tag,border,右箭头icon)
3.渲染三级
4.样式优化
4.1:页面加min-width
4.2:垂直居中对齐(el-row加flex布局样式)
5.删除后,刷新列表,但是会折叠住,体验不好;
删除后返回是最新权限的内容,直接替换是不是就可以了。

==>没有新增,只有删除;删除的时候,如果一级,那么后面的都没有了,所以不存在联动;删除一级的时候,二三级接口自动全部删除了,直接替换数据就行。

class类:

// 125: 'iconfont icon-users',
<i :class="icnosObj[item.id]"></i>
:class="['bdbottom',index1===0?'bdtop':'']"

分配权限->弹框->tree的实现:==>是不是antd中也是同样的问题。
1.树渲染
2.改变label字段 (props配置children和label字段)
3.增加checkbox
4.配置选中是id值
5.默认折叠全部是展开的
6.默认选中的(回写)
7.关闭弹框的时候,清空数据。
8.接口调用(选中和半选的都要提交)

// 代码
<!-- 树结构 -->
<el-tree:data="rightsList":props="treeProps"show-checkboxnode-key="id"default-expand-alldefault-checked-keys="defKeys"
></el-tree>
>
>
// 变量:默认选中的节点id值
defKeys: [105, 116]// 错误信息
Invalid prop: type check failed for prop "defaultCheckedKeys". Expected Array, got String with value "defKeys".

当前每次打开弹框,都会重新调用一次接口请求tree-list,如果树结构的数据使用一个,那么会有问题的:
树结构都是一样的(整个tree),所以准备请求一次,放在data中,那么每次关闭弹框后,重新打开弹框显示的还是之前的数据(checkbox选中状态的),哪怕我checked的list为空,都不行了。
解决方法:
1.每次弹框打开都重新赋值一次。
2.使用重新赋值checked的方法。

// 使用setCheckedKeys方法(element官网有使用方法)
this.$refs.rightsTree.setCheckedKeys(this.defKeys) // 获取节点:
this.$refs.tree.getCheckedNodes() // 有参数,是否只获取leaf节点
this.$refs.tree.getCheckedKeys() // 有参数,是否只获取leaf节点// 获取半选状态的节点的id:
getHalfCheckedKeys

商品分类,eg:

1.一级分类:家用电器
2.二级分类:电视、空调、洗衣机、等
3.三级分类:

  • 曲面电视,超薄电视,OLED电视,55英寸,65英寸
  • 中央空调,悬挂式空调,柜式空调
  • 洗衣机一体机,滚筒洗衣机,烘干机

git push -u origin goods_cate // 提交到远程,且没有该分支git push --set-upstream origin goods_params // 默认提示的

文件路径:goods/Cate.vue
页面基本布局:面包屑,card,search,row,table,
接口获取数据:categories

路由没有跳转成功的问题:

// com=>快捷生成的居然是 comments...
{ path: '/categories', comments: Cate }

刚发现该用人家接口地址的,不一定用本地的…好蠢。

产品分类中,使用了树状的table,需要用第三方的:
github中,examples就是示例,eg:
https://github.com/MisterTaki/vue-table-with-tree-grid/blob/master/example/Example.vue
参考示例和使用文档挨个对比什么作用,然后放在自己的项目中。

data,columns,selection-type(是否有checkbox),expand-type(是否有展开列),show-index(是否显示索引列),border,

columns中的type和template来指定作用域的插槽的。

columns而不是column

总是把函数写在了data中,这样总是报错!!!!

商品管理-参数管理

动态参数:颜色,版本(可以选择的)
静态属性:重量,长宽,上市年份,(用户不可选择的,只读的)

参数列表:
1.切换tab的时候,如果是当前tab,那么不用调用函数了,不做处理就是了。

编辑器快捷键:
选中某个字段,ctr+d,快速选中下一个这个字段(多选,可以用来多个替换)

添加tag的时候,每一行的input显示和值需要都有一个:
给list的每一项绑定一个flag和value,自己维护自己的,就可以啦。

// input自动获取焦点:点击btn后,更改了flag,但是input还没渲染,等渲染后在执行focus事件。
// $nextTick:当页面上的元素被重新渲染之后,才会执行回调函数中的代码
this.$nextTick(_ => {this.$refs.saveTagInput.$refs.input.focus();
});

vue电商实战-黑马-01相关推荐

  1. 7006.vue电商实战项目2-登录退出功能

    学习笔记记录,如有侵权请联系我 文章目录 1 登录概述 1.1 登录流程 1.2 登录的业务技术点 2 登录退出功能 2.1 登录token的原理分析 2.2 登录功能 2.2.1 登录页面布局 2. ...

  2. 微信小程序电商实战项目

    项目地址:https://github.com/sirfuao/wx-shop 如果觉得对您有用,不忘记了给个 star 顺便附上 vue电商实战项目的地址:https://blog.csdn.net ...

  3. 前端03.vue电商管理平台项目实战

    VUE电商管理平台 前部分内容见网站 ​ https://share.mubu.com/doc/7vPChNBEZl 附typora自动标号 https://zhuanlan.zhihu.com/p/ ...

  4. 08 获取器 withAttr、多连缀、whereRaw、事务、数据集《ThinkPHP6 入门到电商实战》

    知识点:获取器 withAttr.多连缀.whereRaw.事务.数据集 文章目录(更新中-) 01 thinkphp6的前期开发准备<ThinkPHP6 入门到电商实战> 02 控制器& ...

  5. 大型电商实战项目,助力2021年高薪

    文章目录 序言 推荐背景 项目介绍 整体架构图形 热点技术栈 项目特点 适合人群 对比番外类似的项目 痛点和选择 序言 2021 新的一年开始,祝愿大家工作顺利,事事顺心.如果你有幸看到这一篇文章,请 ...

  6. Mall电商实战项目专属学习路线,主流技术一网打尽!

    之前经常有朋友问我,mall项目该如何学习,按照什么顺序学习?我一般都会把<mall学习教程>的目录发给他,希望他按照教程顺序学习.我一直认为基于项目实战的学习,可以更好的掌握技术.mal ...

  7. 微信小程序电商实战-商品列表流式布局

    微信小程序电商实战-商品列表流式布局 流式布局概念 流式布局也叫百分比布局 把元素的宽,高,margin,padding不再用固定数值,改用百分比, 这样元素的宽,高,margin,padding会根 ...

  8. 12-Flutter移动电商实战-首页导航区域编写

    12-Flutter移动电商实战-首页导航区域编写 1.导航单元素的编写 从外部看,导航是一个GridView部件,但是每一个导航又是一个上下关系的Column.小伙伴们都知道Flutter有多层嵌套 ...

  9. 11-Flutter移动电商实战-首页_屏幕适配方案和制作

    11-Flutter移动电商实战-首页_屏幕适配方案和制作 1.flutter_ScreenUtil插件简介 flutter_ScreenUtil屏幕适配方案,让你的UI在不同尺寸的屏幕上都能显示合理 ...

最新文章

  1. 总结ISO各层协议都有哪些
  2. ncnn源码编译安装
  3. ZOJ 3633 rmq 重点在于转化
  4. matlabrvctools主要功能及实际应用_【从业必备 | 收藏】ISO26262功能安全标准白皮书:关键组成、软硬件认证、测试过程、合规认证工具...
  5. python编程狮电脑版_w3cschool编程狮PC版-编程狮电脑版下载 v3.3.10--PC6电脑版
  6. Express框架的安装通信测试 - 讲解篇
  7. typescript和coffeescript简介
  8. Matlab使用过程中内存不足问题的总结(修改)
  9. avast! 5 简体中文正式版 官方直接下载链接
  10. DEAP 框架(遗传算法)模块笔记
  11. 记账管家绿色版 V1.0
  12. 山东省枣庄高新区益洋花园地块场地环境初步调查信息公示
  13. 示例正则表达式验证6位数字密码
  14. 中学计算机课小课题,【信息技术课题研究方案】 信息技术小课题研究题目大全_信息技术课题研究题目_信息技术课题研究_东城教研...
  15. java发布geoserver样式(sld样式)
  16. Android封装支付宝支付
  17. 基于51单片机的简易数字电压表proteus仿真原理图程序设计
  18. HTML嵌套注释、多行注释、多级注释,提高生产力
  19. tar.gzh和zip的区别
  20. 微信发照片怎么在服务器上删除,我们发现微信发送原图,确实会暴露位置信息!但你可以这么解决...

热门文章

  1. Kafka拉取某一个时间段內的消息
  2. 怎么计算一个月有多少天
  3. If-else与三目运算符的区别
  4. FPS能重塑英雄联盟的辉煌吗?Valorant公测半年有什么优势和不足?
  5. linux系统单网卡绑定双IP的方法
  6. 带你了解ICCV、ECCV、CVPR三大国际会议
  7. 7-13 寻找大富翁 (25 分)
  8. android中涉及的字体修改
  9. c语言数组判断不及格人数,C语言编程 运用数组求不及格人数
  10. TokenSky DeFi高峰论坛区块链经济学者朱幼平:DeFi究竟有没有前途?