目录

1.电商业务概述

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

​3.项目初始化步骤

4.后台项目的环境安装配置

4.1. API V1 接口说明

4.2. 支持的请求方法

4.3. 通用返回状态说明

5.测试后台接口是否正常

6.登录/退出功能

1.登录概述

1.登录业务流程

2.登录业务的相关技术点

3.token原理

2.登录功能实现

1.终端执行git status:查看当前工作区是否干净

2.用分支开发登录功能

3.查看项目运行效果

4.删除不需要的组件

5.创建登录组件

6.设置背景颜色

7.组件头像布局

8.登录组件表单布局

9.表单小图标布局

10.表单的数据绑定

11.表单的数据验证

12.表单的重置

13.登录前的预验证

14.根据预验证是否发起请求

15.配置弹窗提示

16.登录成功后的行为

17.创建home组件

18.路由导航守卫控制访问权限

19.退出功能的实现

20.语法警告问题(无问题)

21.提交登录功能代码

7.主页部分

1.主页布局

1.主页Header布局

2.左侧菜单布局

3.通过接口获取菜单数据

4.发起请求获取左侧菜单数据

5.渲染UI结构

6.左侧菜单格式美化

7.左侧菜单的折叠和展开功能

8.首页的路由重定向

9.左侧菜单改为路由链接

10.用户列表开发

11.用户列表的基本UI结构

12.获取用户列表数据

13.渲染用户列表数据

13.用户列表添加索引列

14.状态列的按需展示

15.插槽形式自定义操作列的渲染

16.数据的分页形式

17.用户状态的修改

18.实现搜索的功能

19.实现添加用户的功能

20.添加用户对话框中渲染一个添加用户的表单

21.实现自定义校验规则

22.添加用户表单的重置功能

23.添加用户的预验证功能

24.发起请求添加一个新用户

25.添加用户修改的操作

26.根据id

查询到用户信息

27.绘制修改用户的表单

28.修改表单的关闭后的重置操作

29.修改用户信息的操作

30.实现删除用户的操作

31.提交用户列表功能


1.电商业务概述

根据不同的应用场景,电商系统一般都提供了 PC 端、移动 APP、移动 Web、微信小程序等多种终端访问方式。
  • 客户使用的业务服务:PC端,小程序,移动web,移动app
  • 管理员使用的业务服务:PC后台管理端。
  • PC后台管理端的功能:管理用户账号(登录,退出,用户管理,权限管理),商品管理(商品分类,分类参数,商品信息,订单),数据统计
  • 电商后台管理系统采用前后端分离(后端写接口,前端调接口)的开发模式
  • 前端项目是基于Vue的SPA(单页应用程序)项目
  • 前端技术栈:Vue,Vue-Router,Element-UI,Axios,Echarts
  • 后端技术栈:Node.js,Express,Jwt(模拟session(登录记录功能),状态保持工具),Mysql,Sequelize(操作数据库的框架)

一般电商系统是由不同终端组成,共用同一份数据库,同一份接口服务器,通过PC后台管理来管理不同终端访问的数据。

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

电商后台管理系统用于管理用户账号、商品分类、商品信息、订单、数据统计等业务功能。

3.项目初始化步骤

  • A.安装Vue脚手架
  • npm i -g @vue/cli
  • B.通过脚手架创建项目
  • //使用可视化的形式创建项目
    vue ui

    手动配置项目->Babel,Router,Linter/Formatter(代码格式校验,风格一致),使用配置文件

  • C.配置路由
  • D.配置Element-UI:在插件中安装,搜索vue-cli-plugin-element(根据自己需要,选择导入方式:按需导入)
  • E.配置Axios:在依赖中安装,搜索axios(运行依赖)
  • F.初始化git仓库
  • 创建仓库,用管理员运行终端,进行Git 全局设置(创建仓库成功后,会显示需要执行的命令)
  • G.将本地项目托管到github或者码云中
  • 打开项目实战的文件夹,打开powerShell终端,执行git status检查项目状态;在将所有文件放入暂存区git add .  ;在本地做一次提交 git commit -m "add files"
  • 检查状态,正处于主分支,工作区干净的git status

这只是本地仓库,选择需要跟gittee仓库连通

  • 执行gitee简易的命令行内容

    git remote add origin https://gitee.com...git
    git push -u origin "master"

4.后台项目的环境安装配置

A.使用Navicat导入mysql数据库数据

B.安装Node.js环境,配置后台项目,从终端打开后台项目vue_api_server 然后在终端中输入命令安装项目依赖包:npm install,在执行node .\app.js

C.使用postman测试api接口

4.1. API V1 接口说明

  • 接口基准地址:http://127.0.0.1:8888/api/private/v1/

  • 服务端已开启 CORS 跨域支持

  • API V1 认证统一使用 Token 认证

  • 需要授权的 API ,必须在请求头中使用 Authorization 字段提供 token 令牌

  • 使用 HTTP Status Code 标识状态

  • 数据返回格式统一使用 JSON

4.2. 支持的请求方法

  • GET(SELECT):从服务器取出资源(一项或多项)。

  • POST(CREATE):在服务器新建一个资源。

  • PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。

  • PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。

  • DELETE(DELETE):从服务器删除资源。

  • HEAD:获取资源的元数据。

  • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。

4.3. 通用返回状态说明

状态码 含义 说明
200 OK 请求成功
201 CREATED 创建成功
204 DELETED 删除成功
400 BAD REQUEST 请求的地址不存在或者包含不支持的参数
401 UNAUTHORIZED 未授权
403 FORBIDDEN 被禁止访问
404 NOT FOUND 请求的资源不存在
422 Unprocesable entity [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误
500 INTERNAL SERVER ERROR 内部错误

5.测试后台接口是否正常

修改mysql数据库密码为自己电脑数据库的密码

在default.json中有后端的数据库配置文件,本机中的数据库名称,账号,密码与数据库配置文件中的保持一致,后台服务器才能访问到该数据库。

6.登录/退出功能

1.登录概述

1.登录业务流程

  • 在登录页面输入用户名和密码
  • 调用后台接口进行验证
  • 通过验证之后,根据后台的响应状态跳转到项目主页

2.登录业务的相关技术点

  • http是无状态的
  • 通过cookie在客户端记录状态
  • 通过session在服务器端记录状态
  • 通过token方式维持状态

存在跨域问题,推荐使用token;不存在跨域问题,推荐使用cookie,session。

  • A.登录状态保持 如果服务器和客户端同源,建议可以使用cookie或者session来保持登录状态 如果客户端和服务器跨域了,建议使用token进行维持登录状态。
  • B.登录逻辑: 在登录页面输入账号和密码进行登录,将数据发送给服务器 服务器返回登录的结果,登录成功则返回数据中带有token 客户端得到token并进行保存,后续的请求都需要将此token发送给服务器,服务器会验证token以保证用户身份。
  • C.添加新分支login,在login分支中开发当前项目vue_shop: 打开vue_shop终端,使用git status确定当前项目状态。 确定当前工作目录是干净的之后,创建一个分支进行开发,开发完毕之后将其合并到master git checkout -b login 然后查看新创建的分支:git branch 确定我们正在使用login分支进行开发

3.token原理

2.登录功能实现

登录页面的布局,通过——Element-UI组件实现布局

  • el-form
  • el-form-item
  • el-input
  • el-button
  • 字体图标

1.终端执行git status:查看当前工作区是否干净

2.用分支开发登录功能

创建分支

git checkout -b login

查看分支

git branch

3.查看项目运行效果

点击任务->serve运行->启动app

4.删除不需要的组件

index.js

import Vue from 'vue'
import VueRouter from 'vue-router'Vue.use(VueRouter)const routes = [
]const router = new VueRouter({routes
})export default router

App.vue

<template><div id="app">App根组件</div>
</template><script>
export default {name: 'app'
}
</script><style>
</style>

5.创建登录组件

components/Login.vue

<template><div>登录组件</div>
</template>

src/router/index.js

import Login from '@/components/Login.vue'const routes = [{ path: '/login', component: Login }
]

App.vue

<template><div id="app">App根组件<!-- 放路由占位符 --><router-view></router-view></div>
</template>

component name  XXX should always be multi-word  报错

.eslintrc.js

// 在rules中添加自定义规则
rules: { // 关闭组件命名规则// 'vue/multi-word-component-names': 'off'// 关闭命名规则,不会校验组件名;最好设置:根据组件名进行忽略// 忽略部分组件名// 添加组件命名忽略规则"vue/multi-word-component-names": ["error", {"ignores": ["Login"]//需要忽略的组件名}]}

重定向规则,让它默认为login页面

const routes = [{ path: '/', redirect: '/login' },{ path: '/login', component: Login }
]

6.设置背景颜色

<template><div class="login_container">登录组件</div>
</template><style lang="less" scoped>
.login_container {background-color: pink;height: 100%;
}
.login_box {width: 450px;height: 300px;background-color: #fff;border-radius: 3px;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);
}
</style>

报错Can't resolve 'less-loader' in,需要添加依赖

终端下载依赖(开发依赖)---版本出错

npm i less@3.9.0 less-loader@4.1.0 --save-dev

vue ui下载开发依赖less和less-loader ---正常使用

src/assets/css/global.css

/* 全局样式表 */
html,
body,
#app{height: 100%;margin: 0;padding:0;
}

main.js

// 导入全局样式表
import './assets/css/global.css'

7.组件头像布局

 <div class="login_container"><div class="login_box"><div class="avatar_box"><img src="../assets/logo.png" alt="" /></div></div></div>.avatar_box {height: 130px;width: 130px;border: 1px solid #eee;border-radius: 50%;padding: 10px;box-shadow: 0 0 10px #ddd;position: absolute;left: 50%;transform: translate(-50%, -50%);background-color: #fff;img {width: 100%;height: 100%;border-radius: 50%;background-color: #eee;}}

8.登录组件表单布局

<!-- 登录表单区域 --><el-form label-width="0" class="login_form"><!-- 用户名 --><el-form-item><el-input prefix-icon="el-icon-search"></el-input></el-form-item><!-- 密码 --><el-form-item><el-input prefix-icon="el-icon-search"></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>.login_form {position: absolute;bottom: 0;// 只占左边一半,需要设置宽度width: 100%;padding: 0 20px;// 超出区域了,需要设置border-boxbox-sizing: border-box;
}
.btns {// 居右对齐display: flex;justify-content: flex-end;
}

src/plugins/element.js

import { Button, Form, FormItem, Input } from 'element-ui'//Vue.use(Button, Form, FormItem, Input)错误,要分别使用Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)

Element

9.表单小图标布局

 prefix-icon="el-icon-search"

Element

elment图标不完整,使用iconfont图标下载图标形式,使用图标,

  • 将图标文件夹fonts放入assets文件夹
  • 在main.js中导入字体图标
  • // 导入字体图标
    import './assets/fonts/iconfont.css'
  • 在Login.vue进行使用
  • <el-form-item><el-input prefix-icon="iconfont icon-user"></el-input>
    </el-form-item>
    <el-form-item><el-input prefix-icon="iconfont icon-3702mima"></el-input>
    </el-form-item>

10.表单的数据绑定

  • 1.el-form添加:model属性绑定,指向一个数据对象
  • 2.为每一个表单项通过v-model绑定到数据对象上对应的属性中
  <el-form :model="loginForm">data () {return {// 这是登录表单的数据绑定对象loginForm:{username: '',password: ''}}},<el-input v-model="loginForm.username"></el-input>
<el-input v-model="loginForm.password"type="password"></el-input>

11.表单的数据验证

  • 1.为el-form通过属性绑定,指定一个:rules校验对象
  • 2.在data数据中定义这个校验对象,每一个属性都是一个验证规则
  • 3.为不同的表单item项el-form-item,通过props指定不同的验证规则,来进行表单的验证
  <el-form :rules="loginFormRules">// 这是表单的验证规则对象loginFormRules: {// 验证用户名是否合法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' }]}<el-form-item prop="username">
<el-form-item prop="password">

12.表单的重置

  1. 为表单添加ref引用,ref的值就是组件的实例对象(拿到表单的实例对象,使用ref绑定组件(ref相当于给当前标签取名字,用这个名字可以直接获取到这个元素并且操作它里面的数据))
  • 重置按钮绑定事件,通过this访问到$refs,点出表单的引用对象loginFormRef,直接调用resetFields( )方法
  • 即可重置表单
 <el-form ref="loginFormRef"><el-button type="info" @click="resetLoginForm">重置</el-button>methods: {// 点击重置按钮,重置登录表单resetLoginForm () {console.log(this)// 通过this,可以直接获取引用对象(就是这个组件的实例)this.$refs.loginFormRef.resetFields()}}

13.登录前的预验证

当点击登录按钮,要进行一下验证,验证通过才能进行登录。

  1. 为登录按钮绑定点击事件login
  2. 调用表单的引用对象loginFormRef,调用validate函数进行验证,接收一个回调函数,从而拿到验证结果
  3. 符合要求则输出true,不符合要求则输出false(布尔值)
<el-button type="primary" @click="login">登录</el-button>login () {this.$refs.loginFormRef.validate((valid) => {console.log(valid)})
}

14.根据预验证是否发起请求

  login () {this.$refs.loginFormRef.validate(valid => {// console.log(valid)// valid为false则return,不发起请求if (!valid) return})}

添加到vue.prototype.$http后,可以在每一个组件上通过this.$http获取axios,不必在每个页面都import axios,$http是自定义属性名,可以随便起名。

main.js

// 对axios进行全局配置
import axios from 'axios'
// 配置请求根路径
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
Vue.prototype.$http = axios

返回结果是promise,可以用async await来简化promise操作。

只有data才是服务器返回的数据,可以直接解构data

 login () {this.$refs.loginFormRef.validate(async valid => {// console.log(valid)// valid为false则return,不发起请求if (!valid) return// loginForm当成请求参数,因为用户填写的数据会同步到loginForm// const result = await this.$http.post('login', this.loginForm)// console.log(result)const { data: res } = await this.$http.post('login', this.loginForm)console.log(res)if (res.meta.status !== 200) return console.log('登录失败')console.log('登录成功')})}

15.配置弹窗提示

src/plugins/element.js

// 导入弹框提示组件
import {  Message } from 'element-ui'// 在Message挂载到Vue原型上,每个组件都可以直接通过this,访问到Message
Vue.prototype.$message = Message
 if (res.meta.status !== 200) return this.$message.error('登录失败')this.$message.success('登录成功')

Element

16.登录成功后的行为

  1. 将登录后的token,保存到客户端的sessionStorage中
  2. 项目中除了登录之外的其他API接口,必须在登录之后才能访问
  3. token只应在当前网站打开期间生效,所以将token保存在sessionStorage中
  4. 通过编程式导航跳转到后台主页,路由地址是  /home
// 1.将登录后的token,保存到客户端的sessionStorage中// 1.1项目中除了登录之外的其他API接口,必须在登录之后才能访问console.log(res)// 1.2token只应在当前网站打开期间生效,所以将token保存在sessionStorage中window.sessionStorage.setItem('token', res.data.token)
// 2.通过编程式导航跳转到后台主页,路由地址是/homethis.$router.push('/home')

17.创建home组件

18.路由导航守卫控制访问权限

只允许在登录成功后才能看见home组件。

如果用户没有登录,但是直接通过URL访问特定页面,需要重新导航到登录页面。

  • to:将要访问的那个页面路径
  • from:从哪个页面路径跳转而来的
  • next:放行函数
//为路由对象,添加beforeEach导航守卫
router.beforeEach((to,from,next)=>{//如果用户访问的登录页,直接放行if(to.path === '/login') return next()//从sessionStorage中获取到保存的token值const tokenStr = window.sessionStorage.getItem('token')//没有token,强制跳转到登录页if(!tokenStr) return next('/login')next()
})

src/router/index.js

// 挂载路由导航守卫
router.beforeEach((to, from, next) => {// to 将要访问的路径// from 代表从哪个路径跳转而来// next 是一个函数,表示放行// next() 放行   next('/login') 强制跳转if (to.path === '/login') return next()// 获取tokenconst tokenStr = window.sessionStorage.getItem('token')if (!tokenStr) return next('/login')next()
})

19.退出功能的实现

基于token的方式实现退出比较简单,只需要摧毁本地的token即可。这样,后续的请求就不会携带token,必须重新登录生成一个新的token之后才可以访问。

//清空token
window.sessionStorage.clear()
//跳转到登录页,重定向到登录页
this.$router.push('/login')

Home.vue

<template><div><el-button type="info" @click="logout">退出</el-button></div>
</template>logout () {window.sessionStorage.clear()this.$router.push('/login')}

20.语法警告问题(无问题)

shift+alt+f格式化文件

创建格式化配置文件.prettierrc

{// 末尾不加分号"semi": false,// 启用单引号的格式化方式"singleQuote": true
}

.eslintrrc.js关闭某语法规则

    'space-before-function-paren': 0

我在setting json中已经全局设置了

21.提交登录功能代码

1.git status 检查当前代码

2.git add . 添加代码到暂存区

3.git status

4.git commit -m "完成了登录功能"  把暂存区的代码提交到本地仓库中

5.git branch 检查所处分支

6.把login分支代码合并到master主分支中

  • 1.切换到master主分支
  • git checkout master
  • 检查发现处于master分支
  • 2.再从主分支合并login分支
  • git merge login

7.远程推送,把本地的master分支推送到远程的码云中 git push

8.把本地的login分支推送到远程码云中(远程码云只有master分支)

  1. git checkout login 切换到login子分支
  2. 检查分支状态 git branch
  3. 推送到码云中,需要使用 git push -u origin login(将本地的login分支推送到远程的origin仓储里面,并且叫做login子分支,进行保存)

7.主页部分

1.主页布局

Home.vue

  <el-container><!-- 头部区域 --><el-header><el-button type="info" @click="logout">退出</el-button></el-header><!-- 页面主体区域 --><el-container><!-- 侧边栏 --><el-aside width="200px">Aside</el-aside><!-- 右侧内容主体 --><el-main>Main</el-main></el-container></el-container><style lang="less" scoped>
// 没有撑满全屏,需要添加home-container
.home-container {height: 100%;
}
.el-header {background-color: rgb(69, 14, 65);
}
.el-aside {background-color: rgb(165, 59, 154);
}
.el-main {background-color: rgb(241, 192, 241);
}
</style>

element.js注册组件

import { Container,Header,Aside,Main } from 'element-ui'Vue.use(Container)
Vue.use(Header)
Vue.use(Aside)
Vue.use(Main)

Element

1.主页Header布局

左右布局,flex布局。

<el-header><div><img src="../assets/logo.png" alt="" /><span>电商后台管理系统</span></div><el-button type="info" @click="logout">退出</el-button>
</el-header>.el-header {background-color: rgb(69, 14, 65);display: flex;justify-content: space-between;padding-left: 0;align-items: center;color: #fff;font-size: 20px;// 嵌套div> div {display: flex;align-items: center;span {margin-left: 15px;}}img {height: 50px;}
}

2.左侧菜单布局

 <el-aside width="200px"><!-- 侧边栏菜单区 --><el-menubackground-color="#545c64"text-color="#fff"active-text-color="#ffd04b"><el-submenu index="1"><template slot="title"><i class="el-icon-location"></i><span>导航一</span></template><el-menu-item-group><template slot="title">分组一</template><el-menu-item index="1-1">选项1</el-menu-item><el-menu-item index="1-2">选项2</el-menu-item></el-menu-item-group><el-menu-item-group title="分组2"><el-menu-item index="1-3">选项3</el-menu-item></el-menu-item-group><el-submenu index="1-4"><template slot="title">选项4</template><el-menu-item index="1-4-1">选项1</el-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></el-aside>

按需导入element.js

import { Menu, Submenu, MenuItem } from 'element-ui'Vue.use(Menu)
Vue.use(Submenu)
Vue.use(MenuItem)

梳理结构

 <!-- 侧边栏 --><el-aside width="200px"><!-- 侧边栏菜单区 --><el-menubackground-color="rgb(165, 59, 154)"text-color="#fff"active-text-color="rgb(69, 14, 65)"><!-- 一级菜单 --><el-submenu index="1"><!-- 一级菜单的模板区域 --><template slot="title"><!-- 图标 --><i class="el-icon-location"></i><!-- 文本 --><span>导航一</span></template><!-- 二级菜单 --><el-menu-item index="1-4-1"><template slot="title"><!-- 图标 --><i class="el-icon-location"></i><!-- 文本 --><span>导航一</span></template></el-menu-item></el-submenu></el-menu></el-aside>

Element

3.通过接口获取菜单数据

接口说明:需要授权的API,必须在请求头中使用Authorization字段提供token令牌。

所以需要:通过axios请求拦截器添加token,保证拥有获取数据的权限。

后台除了登录接口之外,都需要token权限验证,我们可以通过添加axios请求拦截器来添加token,以保证拥有获取数据的权限

//axios请求拦截
//请求在到达服务器之前,先会调用use中的这个回调函数来添加请求头信息
axios.interceptors.request.use(config => {//为请求头对象,添加Token验证的Authorization字段config.headers.Authorization = window.sessionStorage.getItem('token')return config
})

在重新登录或会获取到此数据

发起login的登录请求,request请求头Headers中包括Authorization:null(登录期间是null,服务器没有颁发令牌;如果登录之后,再用其他接口,此时这个值就不是null)(符合要求才会执行请求 ,不符合要求或者请求不存在,则服务器驳回请求)

main.js

// 配置请求根路径
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
// 在挂载到原型对象之前,先设置一个拦截器
axios.interceptors.request.use(config => {config.headers.Authorization = window.sessionStorage.getItem('token')console.log(config)// 获取headers数据// 在最后必须要return configreturn config
})
Vue.prototype.$http = axios

这时,有权限的API就能调用成功了。

4.发起请求获取左侧菜单数据

左侧菜单权限- 请求路径:menus
- 请求方法:get
- 响应数据{"data":{"id": 101,"authName": "商品管理","path": null,"children": [{"id": 104,"authName": "商品列表","path": null,"children": []}]}"meta": {"msg": "获取菜单列表成功","status": 200}
}

请求左侧菜单:在刚一加载时就应该获取左侧菜单(所以在created时要进行调用)。

 data () {return {// 左侧菜单数据menulist: []}},created () {this.getMenuList()},methods: {// 获取所有的菜单async getMenuList () {const { data: res } = await this.$http.get('menus')// 获取到的数据立即挂载到自己的data中,赋值if (res.meta.status !== 200) return this.$message.error(res.meta.msg)this.menulist = res.dataconsole.log(res)}}

5.渲染UI结构

  <!-- 一级菜单 --><!-- index相同的话,点开其中一个,所有都会展开,每一个都应该有一个独属于自己的index值:报错,index只接收字符串不接收数值,所有需要转成字符串 +'' --><el-submenu:index="item.id + ''"v-for="item in menulist":key="item.id"><!-- 一级菜单的模板区域 --><template slot="title"><!-- 图标 --><i class="el-icon-location"></i><!-- 文本 --><span>{{ item.authName }}</span></template><!-- 二级菜单 --><el-menu-item:index="subItem.id + ''"v-for="subItem in item.children":key="subItem.id"><template slot="title"><!-- 图标 --><i class="el-icon-location"></i><!-- 文本 --><span>{{ subItem.authName }}</span></template></el-menu-item></el-submenu>

6.左侧菜单格式美化

二级菜单小图标修改;一级菜单图标,每一个一级菜单图标都不一样,element不能满足需求,使用iconfont,将字体图标按照顺序更改到一级菜单图标上。在自动生成期间,加上图标,使用data初始化图标,以id为key,id对应图标为它的值。

<i :class="iconObj[item.id]"></i>data () {return {// 左侧菜单数据menulist: [],iconObj: {125: 'iconfont icon-user',103: 'iconfont icon-tijikongjian',101: 'iconfont icon-shangpin',102: 'iconfont icon-shangpin',145: 'iconfont icon-baobiao'}}},.iconfont {margin-right: 10px;
}

如果想要实现,点击一个一级菜单,再点击第二个一级菜单,之前点击的一级菜单收回情况(每次只展开一个),可以通过修改下面属性

   <el-menubackground-color="rgb(165, 59, 154)"text-color="#fff"active-text-color="rgb(69, 14, 65)"unique-opened>

Element

解决细微的对齐问题

.el-aside {background-color: rgb(165, 59, 154);.el-menu {border-right: none;}
}

7.左侧菜单的折叠和展开功能

//侧边栏不能跟着宽度变化,需要动态绑定在isCollapse。折叠,则为64px;不折叠,则为200px
<el-aside :width="isCollapse ? '64px' : '200px'"><div class="toggle-button" @click="toggleCollaapse">|||</div><el-menu:collapse="isCollapse":collapse-transition="false">// 是否折叠
isCollapse: false// 点击按钮,切换菜单的折叠和展开
toggleCollaapse () {this.isCollapse = !this.isCollapse
}.toggle-button {background-color: rgb(217, 119, 225);font-size: 10px;line-height: 24px;color: #fff;text-align: center;letter-spacing: 0.2em;cursor: pointer;
}

8.首页的路由重定向

登录成功后,在main区域显示欢迎页面;home路由中嵌套显示了main子路由组件。

只要访问了home这个地址,就显示Welcome子路由规则。

router/index.js

 {path: '/home',component: Home,redirect: '/welcome',children: [{ path: '/welcome', component: Welcome }]}

Home.vue

<!-- 右侧内容主体 -->
<el-main><!-- 路由占位符 --><router-view></router-view>
</el-main>

9.左侧菜单改为路由链接

把每一个设置为router-link(麻烦),通过element router属性完成,为整个侧边栏开启路由模式。(简单)

  <!-- 侧边栏菜单区 -->
<el-menurouter
>

path作为唯一的跳转路径合适,比id好;path不是以‘/’开头的,需要我们对齐补充

 <!-- 二级菜单 --><el-menu-item:index="'/' + subItem.path">

点击二级菜单可以进行跳转

Element

10.用户列表开发

router.js

import Users from '@/components/user/Users.vue'{path: '/home',component: Home,redirect: '/welcome',children: [{ path: '/welcome', component: Welcome },{ path: '/users', component: Users }]}

此时点击用户列表,右侧会显示用户列表的组件内容

解决无高亮现象(高亮效果的动态切换)

点击链接时把对应的地址保存到sessionStorage中,在刷新时(home杠创建的时候)就立即把值取出来,赋值到左边菜单即可。

default-active="/users"//写死
  1. 给二级菜单绑定单击事件
  2. 定义点击事件函数,保存链接的激活状态(把对应的index值保存到sessionStorage中)
  3. 把值重新取出来,在data中定义数据activePath,保存激活的链接
  4. 把activePath地址动态保存到el-menu上(:default-active="activePath")
  5. 给它动态赋值,在整个home组件一被创建时,就把sessionStorage中的值取出来,给它赋值上去
  6. 在点击不同链接时,应该为activePath重新赋值
<!-- 侧边栏菜单区 -->
<el-menu:default-active="activePath"
><!-- 二级菜单 -->
<el-menu-item@click="saveNavState('/' + subItem.path)"
>// 被激活的链接地址activePath: ''created () {this.activePath = window.sessionStorage.getItem('activePath')}// 保存链接的激活状态
saveNavState (activePath) {window.sessionStorage.setItem('activePath', activePath)this.activePath = activePath
}

点击用户列表,就会多一个键

保存记录你所选择的path(提留的界面),然后储存在sessionStorage中,重新加载时就从sessionStorage中查看你的历史记录,你浏览了其他的path则需要通过sessionStorage更新一下。

11.用户列表的基本UI结构

import { Breadcrumb, BreadcrumbItem, Card, Row, Col } from 'element-ui'Vue.use(BreadcrumbItem)
Vue.use(Breadcrumb)
Vue.use(Card)
Vue.use(Row)
Vue.use(Col)
  <div><!-- 面包屑导航区域 --><el-breadcrumb separator-class="el-icon-arrow-right"><el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item><el-breadcrumb-item>用户管理</el-breadcrumb-item><el-breadcrumb-item>用户列表</el-breadcrumb-item></el-breadcrumb><!-- 卡片视图区域 --><el-card class="box-card"><!-- 搜索与添加区域 --><el-row :gutter="20"><el-col :span="8"><el-input placeholder="请输入内容"><el-button slot="append" icon="el-icon-search"></el-button></el-input></el-col><el-col :span="4"><el-button type="primary">添加用户</el-button></el-col></el-row></el-card></div>

Element

Element

Element

Element

src/assets/css/global.css

.el-breadcrumb {margin-bottom: 15px;font-size: 12px;
}
.el-card {box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15) !important;
}

12.获取用户列表数据

// 获取用户列表的参数对象queryInfo: {query: '',pagenum: 1,pagesize: 2},userlist: [],total: 0created () {this.getUserList()},async getUserList () {const { data: res } = await this.$http.get('users', { params: this.queryInfo })if (res.meta.status !== 200) {return this.$message.error('获取用户列表失败!')}this.userlist = res.data.usersthis.total = res.data.totalconsole.log(res)}

13.渲染用户列表数据

import {Table,TableColumn } from 'element-ui'Vue.use(Table)
Vue.use(TableColumn)
<!-- 用户列表区域 -->
<el-table :data="userlist" border stripe>
//label:当前页的标题;prop:指向这一列的数据<el-table-column label="姓名" prop="username"></el-table-column><el-table-column label="邮箱" prop="email"></el-table-column><el-table-column label="电话" prop="mobile"></el-table-column><el-table-column label="角色" prop="role_name"></el-table-column><el-table-column label="状态" prop="mg_state"></el-table-column><el-table-column label="操作"></el-table-column>
</el-table>

src/assets/css/global.css

.el-table {margin-top: 15px;font-size: 12px;
}

Element

13.用户列表添加索引列

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

14.状态列的按需展示

通过作用域插槽来渲染当前状态列。

  1. 先在状态列中定义一个作用域插槽,通过slot-scope接收当前作用域的数据
  2. 通过scope.row拿到对应这一行的数据
  3. 需要把整个开关的状态绑定到哪个属性身上,v-model上绑定具体地方属性值即可
  4. 此时,prop="mg_state"可以删除,作用域插槽会覆盖prop
import { Switch } from 'element-ui'Vue.use(Switch)
<el-table-column label="状态"><template slot-scope="scope"><!-- {{ scope.row }} --><!-- 通过作用域插槽接收了scope,scope.row就等于这一行对应的数据 --><el-switch v-model="scope.row.mg_state"> </el-switch></template>
</el-table-column>

Element

15.插槽形式自定义操作列的渲染

import { Tooltip } from 'element-ui'Vue.use(Tooltip)
<el-table-column label="操作" width="180"><template slot-scope=""><!-- 修改按钮 --><el-buttontype="primary"icon="el-icon-edit"size="mini"></el-button><!-- 删除按钮 --><el-buttontype="danger"icon="el-icon-delete"size="mini"></el-button><!-- 分配角色按钮 --><el-tooltipeffect="dark"content="分配角色"placement="top-start":enterable="false"><el-buttontype="warning"icon="el-icon-setting"size="mini"></el-button></el-tooltip></template>
</el-table-column>

Element

Element

16.数据的分页形式

使用element ui分页组件。

  1. 按需导入这个分页组件
  2. 定义 size-change的handleSizeChange事件( 监听最新的pagesize),定义current-change的handleCurrentChange事件(监听最新的页码值pagenum)
  3. 只要页码值pagenum或者pagesize发生改变,就立即发起一次新的数据请求
  4. 通过不同的属性配置页码条
import { Pagination } from 'element-ui'Vue.use(Pagination)
<!-- 分页区域 -->
<el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="queryInfo.pagenum":page-sizes="[1, 2, 5, 10]":page-size="queryInfo.pagesize"layout="total, sizes, prev, pager, next, jumper":total="total">
</el-pagination>// 获取用户列表的参数对象queryInfo: {query: '',// 当前的页数pagenum: 1,// 当前每页显示多少条数据pagesize: 2},userlist: [],total: 0// 监听pagesize改变的事件handleSizeChange (newsize) {// console.log(newsize)this.queryInfo.pagesize = newsizethis.getUserList()},// 监听页码值改变的事件,可以拿到最新的页码值handleCurrentChange (newPage) {// console.log(newPage)this.queryInfo.pagenum = newPagethis.getUserList()}

assets/css/global.css

.el-pagination {margin-top: 15px;
}

Element

17.用户状态的修改

把用户状态同步到数据库中进行保存。

  1. 监听switch开关状态的改变,从而拿到状态

  2. 调用对应的API接口,把最新的状态保存到数据库中

 <!-- 只要调用了这个函数,就可以把当前用户的信息传过去,因为当前switch是通过v-model双向绑定到了scope.row.mg_state上,只要状态改变了,mg_state也会改变,所以直接把这一行的数据scope.row传到函数userStateChanged中 -->
<el-switch v-model="scope.row.mg_state" @change="userStateChanged(scope.row)">
</el-switch>// 监听switch开关状态的改变async userStateChanged (userinfo) {console.log(userinfo)const { data: res } = await this.$http.put(`users/${userinfo.id}/state/${userinfo.mg_state}`)// 如果获取用户状态失败了,应该把状态重置回去if (res.meta.status !== 200) {userinfo.mg_state = !userinfo.mg_statereturn this.$message.error('更新用户状态失败!')}this.$message.success('更新用户状态成功')}

 修改用户状态的API

  • 请求路径:users/:uId/state/:type

  • 请求方法:put

  • 请求参数

参数名 参数说明 备注
uId 用户 ID 不能为空携带在url中
type 用户状态 不能为空携带在url中,值为 true 或者 false
  • 响应数据

{"data": {"id": 566,"rid": 30,"username": "admin","mobile": "123456","email": "bb@itcast.com","mg_state": 0},"meta": {"msg": "设置状态成功","status": 200}
}

18.实现搜索的功能

  1. 在input上使用v-model双向绑定queryInfo
  2. 为搜索按钮绑定点击事件getUserList,点击了一次这个按钮,就会发起一次查询用户的请求
<el-input placeholder="请输入内容" v-model="queryInfo.query"  clearable @clear="getUserList"><el-button @click="getUserList"></el-button>
</el-input>

19.实现添加用户的功能

  1. 按需导入对话框组件
  2. 复制粘贴对话框结构
  3. 点击按钮可以隐藏对话框和显示对话框
import { Dialog } from 'element-ui'Vue.use(Dialog)
<el-button type="primary" @click="addDialogVisible = true"<!-- 添加用户的对话框 --><el-dialogtitle="提示":visible.sync="addDialogVisible"width="50%"><!-- 内容主体区域 --><span>这是一段信息</span><!-- 底部区域 --><span slot="footer" class="dialog-footer"><el-button @click="addDialogVisible = false">取 消</el-button><el-button type="primary" @click="addDialogVisible = false">确 定</el-button></span></el-dialog>// 控制添加用户对话框的显示和隐藏addDialogVisible: false

Element

20.添加用户对话框中渲染一个添加用户的表单

<!-- 内容主体区域 -->
<el-form:model="addForm":rules="addFormRules"ref="addFormRef"label-width="70px"
><el-form-item label="用户名" prop="username"><el-input v-model="addForm.username"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-input v-model="addForm.password"></el-input></el-form-item><el-form-item label="邮箱" prop="email"><el-input v-model="addForm.email"></el-input></el-form-item><el-form-item label="手机" prop="mobile"><el-input v-model="addForm.mobile"></el-input></el-form-item></el-form>// 添加用户的表单数据addForm: {username: '',password: '',email: '',mobile: ''},// 添加表单的验证规则对象addFormRules: {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'}],mobile: [{required: true, message: '请输入手机号', trigger: 'blur'}]}

21.实现自定义校验规则

  1. 定义一个箭头函数,写自定义校验规则
  2. 在具体的校验规则中,通过validator来使用上面自定义校验规则
  data () {// 验证邮箱的规则// rule:规则;value:待检验的value值;cb:回调函数const 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('请输入合法的邮箱'))}// 验证手机号的规则const checkMobile = (rule, value, cb) => {// 验证手机号的正则表达式const regMobile = /^(0|86|17951)?(13[0-9]|15[0123456789]|17[678]|18[0-9]|14[57])[0-9]{8}$/// 如果时合法的手机号,则直接return cb()if (regMobile.test(value)) {return cb()}// 不合法,调用cb,传递错误对象cb(new Error('请输入合法的手机号'))}email: [{ required: true, message: '请输入邮箱', trigger: 'blur'},{validator: checkEmail, trigger: 'blur'}],
mobile: [{required: true, message: '请输入手机号', trigger: 'blur'},{ validator: checkMobile, trigger: 'blur'}]
}

Element

22.添加用户表单的重置功能

监听对话框的关闭事件以及对话框的重置事件。

<el-dialog @close="addDialogClosed">// 监听添加用户对话框的关闭事件addDialogClosed () {this.$refs.addFormRef.resetFields()}
  1. 要监听对话框的close事件
  2. 在close事件的处理函数中,拿到表单的引用$refs
  3. 调用resetFields( )方法

23.添加用户的预验证功能

在点击确认按钮后,不应该直接关闭对话框,应该在点击这个按钮的时候调用函数,在函数中对整个表单进行预验证。

 <el-button @click="addUser">确 定</el-button>
// 点击按钮添加新用户addUser () {this.$refs.addFormRef.validate(valid => {// 接收校验结果console.log(valid)// 布尔值if (!valid) return// 可以发起添加用户的网络请求})}

24.发起请求添加一个新用户

  • 请求路径:users

  • 请求方法:post

  • 请求参数(跟addForm相同)

参数名 参数说明 备注
username 用户名称 不能为空
password 用户密码 不能为空
email 邮箱 可以为空
mobile 手机号 可以为空
  • 响应参数

参数名 参数说明 备注
id 用户 ID
rid 用户角色 ID
username 用户名
mobile 手机号
email 邮箱
  • 响应数据
{"data": {"id": 28,"username": "tige1200","mobile": "test","type": 1,"openid": "","email": "test@test.com","create_time": "2017-11-10T03:47:13.533Z","modify_time": null,"is_delete": false,"is_active": false},"meta": {"msg": "用户创建成功","status": 201}
}
// 点击按钮添加新用户addUser () {this.$refs.addFormRef.validate(async valid => {// 接收校验结果console.log(valid)// 布尔值if (!valid) return// 可以发起添加用户的网络请求const { data: res } = await this.$http.post('users', this.addForm)if (res.meta.status !== 201) {this.$message.error('添加用户失败!')}this.$message.success('添加用户成功!')// 隐藏添加用户的对话框this.addDialogVisible = false// 刷新列表,重新获取用户列表数据this.getUserList()})}

25.添加用户修改的操作

为修改按钮绑定点击事件,点击按钮就会弹出修改的对话框。

 <!-- 修改按钮 -->
<el-button @click="showEditDialog()"></el-button><!-- 修改用户的对话框 --><el-dialog title="修改用户" :visible.sync="editDialogVisible" width="50%"><span>这是一段信息</span><span slot="footer" class="dialog-footer"><el-button @click="editDialogVisible = false">取 消</el-button><el-button type="primary" @click="editDialogVisible = false">确 定</el-button></span></el-dialog>// 控制修改用户对话框的显示与隐藏
editDialogVisible: false// 展示编辑用户的对话框
showEditDialog () {this.editDialogVisible = true
}

Element

26.根据id查询到用户信息

根据用户的id查询到用户的旧数据,并且保存起来。

  1. 先在调用方法的时候,把用户的id通过scope.row.id将其传进去
  2. 接收到id后,调用API 接口查询用户信息
  3. 把查询到的用户信息存到editForm表单数据对象上
 <template slot-scope="scope"><!-- 修改按钮 --><el-buttontype="primary"icon="el-icon-edit"size="mini"@click="showEditDialog(scope.row.id)"></el-button>// 查询到的用户信息对象
editForm: {}// 展示编辑用户的对话框async showEditDialog (id) {console.log(id)const { data: res } = await this.$http.get('users/' + id)if (res.meta.status !== 200) {return this.$message.error('查询用户信息失败!')}// 给它进行赋值this.editForm = res.datathis.editDialogVisible = true}
  • 请求路径:users/:id

  • 请求方法:get

  • 请求参数

参数名 参数说明 备注
id 用户 ID 不能为空携带在url中
  • 响应参数

参数名 参数说明 备注
id 用户 ID
role_id 角色 ID
mobile 手机号
email 邮箱
  • 响应数据

{"data": {"id": 503,"username": "admin3","role_id": 0,"mobile": "00000","email": "new@new.com"},"meta": {"msg": "查询成功","status": 200}
}

27.绘制修改用户的表单

  1. 通过element ui把表单项粘贴过来
  2. 提供:model="editForm"; :rules="editFormRules";ref="editFormRef"
  3. 提供修改表单的验证规则对象editFormRules

 <el-form:model="editForm":rules="editFormRules"ref="editFormRef"label-width="70px"><el-form-item label="用户名"><el-input v-model="editForm.username" disabled></el-input></el-form-item><el-form-item label="邮箱" prop="email"><el-input v-model="editForm.email"></el-input></el-form-item><el-form-item label="手机号" prop="mobile"><el-input v-model="editForm.mobile"></el-input></el-form-item>
</el-form>// 修改表单的验证规则对象editFormRules: {email: [{required: true,message: '请输入用户邮箱',trigger: 'blur'},{ validator: checkEmail, trigger: 'blur' }],mobile: [{required: true,message: '请输入用户手机',trigger: 'blur'},{ validator: checkMobile, trigger: 'blur' }]}

Element

28.修改表单的关闭后的重置操作

  1. 监听对话框的close事件
  2. 在close事件中应该重置表单
<el-dialog @close="editDialogClosed">// 监听修改用户对话框的关闭事件editDialogClosed () {this.$refs.editFormRef.resetFields()}

29.修改用户信息的操作

  1. 提交修改之前表单预验证操作

  2. 然后再修改用户信息的操作

 <el-button type="primary" @click="editUserInfo">确 定</el-button>// 修改用户信息并提交editUserInfo () {this.$refs.editFormRef.validate(async valid => {// console.log(valid)if (!valid) return// 发起修改用户信息的数据请求const { data: res } = await this.$http.put('users/' + this.editForm.id, {email: this.editForm.email,mobile: this.editForm.mobile})if (res.meta.status !== 200) {return this.$message.error('更新用户信息失败!')}// 关闭对话框this.editDialogVisible = false// 刷新数据列表this.getUserList()// 提示修改成功this.$message.success('更新用户信息成功!')})}
  • 请求路径:users/:id

  • 请求方法:put

  • 请求参数(editForm修改的数据)

参数名 参数说明 备注
id 用户 id 不能为空 参数是url参数:id
email 邮箱 可以为空
mobile 手机号 可以为空
  • 响应参数

参数名 参数说明 备注
id 用户 ID
role_id 角色 ID
mobile 手机号
email 邮箱
  • 响应数据

/* 200表示成功,500表示失败 */
{"data": {"id": 503,"username": "admin3","role_id": 0,"mobile": "111","email": "123@123.com"},"meta": {"msg": "更新成功","status": 200}
}

30.实现删除用户的操作

plugins/element.js

import { MessageBox } from 'element-ui'//在每一个组件中都可以通过this.$confirm来弹出确认弹出的提示框
Vue.prototype.$confirm = MessageBox.confirm
<!-- 删除按钮 -->
<el-button @click="removeUserById(scope.row.id)"></el-button>// 根据Id删除对应的用户信息async removeUserById (id) {console.log(id)// 弹框询问用户是否需要删除数据const confirmResult = await this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).catch(err => err)// (err => err)为(err => {return err})的简写形式// 如果用户确认删除,则返回值为字符串confirm// 如果用户取消删除,则返回值为字符串cancelconsole.log(confirmResult)if (confirmResult !== 'confirm') {return this.$message.info('已取消删除')}// 在终端里显示了确认删除//console.log('确认了删除')const { data: res } = await this.$http.delete('users/' + id)if (res.meta.status !== 200) {return this.$message.error('删除用户失败!')}this.$message.success('删除用户成功!')// 删除成功之后,需要刷新用户列表,直接调用getUserList()this.getUserList()}

Element

31.提交用户列表功能

提交代码到git仓库。

  1. 检查当前所处的分支 git branch
  2. 创建新分支并切换checkout到新分支上 git checkout -b user
  3. 再所有修改操作添加到暂存区  git status检查当前user分支文件的状态  git add .
  4. 检查状态git status  所有文件都被添加到了暂存区
  5. 将user提交到仓库中 git commit -m "完成用户列表功能的开发"
  6. 检查状态      git status 
  7. 本地user的代码就是最新的了
  8. 码云中还没有记录user分支,检查当前所处的分支  git branch
  9. 把本地分支推送到云端(第一次推送新分支user)git push -u origin user (把本地的user分支推送到云端的origin仓库中,同时以user分支来进行保存)
  10. 此时master主分支还是旧的
  11. 检查当前所处分支 git branch
  12. 切换到master主分支 git checkout master
  13. 检查是否处于master主分支 git branch
  14. 从主分支上把user代码合并过来 git merge user
  15. 把本地的master分支代码推送到云端 git push (有master分支,不是第一次了)

Vue+JS+Element UI实战(电商项目1)相关推荐

  1. JS任务机制 - springboot实战电商项目mall4j

    springboot实战电商项目mall4j (https://gitee.com/gz-yami/mall4j) java商城系统源码 1.介绍 工作一段时间了,今天在这总结一下浏览器执行JS任务机 ...

  2. 关于vue.js element ui 表单验证 this.$refs[formName].validate()的问题

      方法使用前需了解: 来自"和"小编的小提示: 首先打印一下this.$refs[formName],检查是否拿到了正确的需要验证的form. 其次在拿到了正确的form后,检查 ...

  3. [Vue.js]实战 -- 电商项目(一)

    项目目录 项目概述 项目初始化 登录/退出功能 主页布局 用户管理模块 权限管理模块 分类管理模块 参数管理模块 商品管理模块 订单管理模块 数据统计模块 项目概述 电商项目基本业务概述 电商后台管理 ...

  4. [Vue]实战---电商项目(项目的概述及初始化)【一】

    项目实战 项目目录 项目概述 项目初始化 登录/退出功能 主页布局 用户管理模块 权限管理模块 分类管理模块 参数管理模块 商品管理模块 订单管理模块 数据统计模块 项目概述 电商项目基本业务概述 电 ...

  5. Node mysql mvc vue_net MVC +Vue.js+Element UI 笔记

    最近项目需求,要在MVC里用Vue 与 Element UI,故而做个笔记来记录一些遇到的问题和处理思路 (方式比较麻瓜,如果不是临时用的话,建议还是学一下Vue-cli,新项目还是老老实实前后端分离 ...

  6. Web实战——电商项目

    文章目录 电商项目实践 1 准备数据 模块说明 实践过程 相关技术 2 搭建 maven 私服(nexus) 模块说明 实践过程 相关技术 3 Dubbo 服务 模块说明 实践过程 相关技术 4 后台 ...

  7. [Vue.js]实战 -- 电商项目(二)

    主页布局 整体布局 主页布局开始 引入官网的框架时,首先要在element.js中添加 import { Container,Header,Aside,Main } from 'element-ui' ...

  8. [Vue.js]实战 -- 电商项目(四)

    分类管理 商品分类概述 商品分类用于在购物时,快速找到所要购买的商品,可以通过电商平台主页直观的看到 商品分类列表 基本布局与数据获取 基本布局 面包屑导航区域 <!-- 面包屑导航区域 --& ...

  9. [Vue.js]实战 -- 电商项目(六)

    商品管理 商品管理概述 用于维护电商平台的商品信息 包括商品的类型.参数.图片.详情等信息.通过商品管理模块可以实现商品的添加.修改.展示和删除等功能 商品列表 实现商品列表布局效果 调用后台接口获取 ...

最新文章

  1. SourceTree的安装
  2. matlab拟合双自变量双指数函数曲线,怎样用MATLAB拟合两个自变量的函数系数和指数?...
  3. Leetcode 166. Fraction to Recurring Decimal
  4. 使用jQuery实现图片懒加载原理
  5. 开放下载!《iOS开发者必读资讯》
  6. P2756,ssl2601-飞行员配对问题【网络流24题,最大匹配,dinic】
  7. Hive数据如何同步到MaxCompute之实践讲解
  8. 企业实战(Jenkins+GitLab+SonarQube)_07_Jenkins 安全设置
  9. orcl导入dmp语句_oracle中导入dmp数据注意事项
  10. pythontk界面显示函数中的变量值_简单易学,西门子触摸屏3种修改变量值的方法!博图Wincc V14组态...
  11. bottle模板中的替换
  12. 从2个命令简单聊聊CentOS账户锁定原理
  13. tidb 企业_TiDB,日均千万级数据存储方案选型
  14. mysql 索引失效情况总结
  15. ecshop模板支持php,ecshop模板支持php数据运算的代码实例
  16. 范蠡传(司马迁-史记)
  17. android随手记毕业论文,关于毕业论文的思考
  18. C语言 打印5阶魔方阵
  19. Ameya360代理 | 兆易创新发布GD32A503系列首款车规级MCU
  20. 编程从键盘输入一个字符串,统计该字符串中从‘a‘到‘z‘共26个小写字母各自出现的次数, 将结果存入数组中,并输出

热门文章

  1. C语言教程Day01
  2. FPGA — Vivado下ILA(逻辑分析仪)详细使用方法
  3. python中的生成器和迭代器
  4. 【图像识别】基于二维条形码识别matlab 源码含GUI
  5. VS2017下AI工具的安装
  6. 简单实现京东订单功能
  7. Vue集成Bmap离线地图
  8. 微信小程序控制三轮全向排爆小车
  9. 在Ubuntu 20.04 LTS Focal Fossa上安装Cockpit
  10. 分享一个下载免费电子书的好站