电商后台管理系统 项目源码:码云 微信号:RanY_Luck
npm install -g @vue/cli
vue ui
启动服务并启动app
你会看到这样的一个画面
测试一下:
node app.js
通过Element-UI组件实现布局
删除views
<template>
<div id="app">
</div>
</template>
<script>
// 导入helloword
export default {
name: 'app'
}
</script>
<!-- style样式 -->
<style>
</style>
<template>
<div class="login_container">
<!-- 登录主体边框 -->
<div class="login_box">
<!-- 头像区域 -->
<div class="avater_box">
<img src="../assets/logo.png" alt="头像logo" />
</div>
<!-- 登录表单区域 -->
<el-form :model="loginForm" :rules="rules" ref="loginFormRef" label-width="0px" class="login_form">
<!-- 用户名 -->
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
placeholder="请输入账号"
prefix-icon="iconfont icon-RectangleCopy"
></el-input>
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
placeholder="请输入密码"
prefix-icon="iconfont icon-RectangleCopy1"
type="password"
></el-input>
</el-form-item>
<!-- 按钮区域 -->
<el-form-item class="btns">
<el-button type="primary" @click="login">登录</el-button>
<el-button type="info" @click="resetLoginForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
export default {
data () {
return {
// 这是登录表单的数据绑定对象
loginForm: {
username: 'admin',
password: '123456'
},
// 这是表单的验证规则对象
rules: {
// 验证用户名是否合法
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' }
]
}
}
},
methods: {
// 点击重置按钮,重置登录表单
resetLoginForm () {
// 前提是先获取ref节点
this.$refs.loginFormRef.resetFields()
},
login () {
// 表单之前的预验证
this.$refs.loginFormRef.validate(async valid => {
if (!valid) return;
const { data: res } = await this.$http.post('login', this.loginForm);
if (res.meta.status !== 200) return this.$message.error('登录失败! ');
this.$message.success('登录成功');
// 1. 将登陆成功之后拿到后端返回的token值,保存到客服端也就是临时浏览器sessionStorage中
// 1.1 项目中出了登录之外的其他api接口,必须在登录之后才能访问
// 1.2 token只应在当前网站打开期间生效,所以将token保存在sessionStorage中
const data = res.data.token;
window.sessionStorage.setItem('token', data);
// 2. 通过编程式导航跳转到后台主页,路由地址是 /home
this.$router.push('/home');
})
}
}
}
</script>
<style lang="less" scoped>
.login_container {
background: #2b4b6b;
height: 100%;
}
.login_box {
width: 450px;
height: 300px;
background-color: #fff;
border-radius: 3px;
position: absolute; // 绝对定位
left: 50%;
top: 50%;
transform: translate(-50%, -50%); // 在横轴上进行位移-50%,纵轴上位移-50%
// 语法嵌套
.avater_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%); // 在横轴上进行位移-50%,纵轴上位移-50%
background-color: #fff;
img {
width: 100%;
height: 100%;
border-radius: 50%; // 添加圆角边框
background-color: #eee;
}
}
}
.btns {
display: flex; // 弹性布局
justify-content: flex-end; // 位于容器的结尾
}
.login_form {
position: absolute; // 绝对定位
bottom: 0; // 底部对齐
width: 100%;
padding: 0 20px;
box-sizing: border-box; // 将元素限制到宽度里面
}
</style
// App.vue
<template>
<div id="app">
<!-- 路由占位符 -->
<router-view></router-view>
</div>
</template>
<script>
// 导入helloword
export default {
name: 'app'
}
</script>
<!-- style样式 -->
<style>
</style>
访问页面
现在需要让用户访问根目录就自动跳转到login页面
post返回值是一个Promise 对象,为了简化Promise操作,我们可以用async await 来优化
await 只能用在async的方法中,所以需要把vaild修饰成异步,这样就能直接拿到服务器返回的数据{ data: res }中的data 才是服务器的真实数据,然后重命名为res对象,然后在根据res的meta属性来判断是否为200,为200就登录成功并打印,不为200就失败并打印。
第一步:你需要进行组件导入
进行全局导入后,以后用到message就可以直接用this.$message.xxx()
第二步:代码使用
// 为路由对象,添加 beforeEach 导航守卫
router.beforeEach((to, form, next) =>{
// 如果用户访问的登录页,直接放行
if(to.path === '/login') return next()
// 从 sessionStorage 中获取保存的token值
const tokenStr = window.sessionStorage.getItem('token')
// 没有token,强制跳转到登录页
if(!tokenStr) return next('/login')
next()
})
判断用户在没有token了自动跳转到登录界面
需要进行router.js改写
退出功能实现原理 基于token的方式实现退出比较简单,只需要销毁本地的token即可。这样,后续的请求就不会携带token,必须重新登录生成一个新的token之后才可以访问
// 清空token
window.sessionStorage.clear();
// 跳转到登录页
this.$router.push('/login')
<el-container>
// 头部区域
<el-header></el-header>
<el-container>
// 侧边栏区域
<el-asider></el-asider>
// 右侧主体区域
<el-main></el-main>
</el-container>
</el-container>
<el-menus>
<el-submenu>
// 这个template 是一级菜单的内容模版
<i class="el-icon-menu"></i>
<span>一级菜单</span>
// 在一级菜单中,可以嵌套二级菜单
<el-menu-item>
<i class="el-icon-menu"></i>
<span slot="title">二级菜单</span>
</el-menu-item>
</el-submenu>
</el-menus>
<!-- 侧边栏 -->
<el-aside width="200px">
<!-- 侧边栏菜单区 -->
<el-menu
background-color="#333744"
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 index="1-4-1">
<!-- 图标 -->
<i class="el-icon-location"></i>
<!-- 文本 -->
<span>二级菜单</span>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
需要element.js进行注册
通过axios请求拦截器添加token,保证拥有获取数据的权限
// axios请求拦截(预处理)
axios.interceptors.request.use(config =>{
// 为请求头对象添加Token验证的Authorization字段
config.headers.Authorization = window.sessionStorage.getItem('token')
return config
})
对接口请求,获取详细信息:
就可以看到已经获取到数据,所有的一级菜单都放在了data数据中,二级菜单就嵌到了children中
拿到了数据 我们就需要渲染到页面中
第一步:需要在一级菜单进行v-for循环
第二步:需要在一级菜单的基础上对二级菜单再进行v-for循环
代码:
不过可以看到一级菜单的图标都为统一不是很好看,我们需要整改下
第一步:先自定义iconsObj
第二步:在一级菜单的图标中进行v-bind双向绑定
效果:
fix展开后对不齐的问题,先看效果:
经过分析:
于是可以在css选择器中添加个border-right: none;就可以了
fix可以将一级菜单全部展开,先看效果:
经过分析:element-ui是默认展开的,不过也提供了只保持一个子菜单展开的api
水平折叠收起菜单
经过分析:element-ui是默认不折叠的,不过也提供了只保持一个子菜单展开的api
第一步:在el-menu新增
第二步:自定义一个div,并赋予click事件
第三步:在data()定义初始值
第四步:动态赋值侧边栏宽度
第一步:创建个Welcome.vue文件
第二步:在router里面导入Welcome.vue
第三步:在Home.vue中渲染出Welcome.vue的内容
步骤一:
步骤二:
效果:
第一步:在comments里新建一个user的文件夹,创一个Users.vue的文件
第二步:在router里面引用
效果:
步骤一:在侧边栏增加default-active语法
第二步:我们需要动态渲染路径
组件创建了需要执行created生命周期函数
在点击不同连接的时候,我们需要给activePath重新赋值
这样就不会点了其他高亮然后再点回来不高亮啦(可能有点绕)
步骤一:element-ui给出了面包屑的方案
我们只需要复制过来
步骤二:需要在element.js中进行按需引入
效果:
步骤一:element-ui给出了卡片的方案
我们只需要复制过来删除不必要的东西
步骤一:element-ui给出了卡片的方案
我们只需要复制过来删除不必要的东西
效果:
tips:
需要对card做样式修改。可以在global.css中做全局设定,当然也可以自建class进行修改样式
第一步:查看接口文档
第二步:将接口请求参数定义到data中
第三步:进行axios请求
第四步:定义空列表
第五步:赋值数据到空列表中
快速入门Table表格(element-ui提供了方法)
第一步:
第二步:copy代码
第三步:重置样式
效果:
发现序号id,值非常大,不便于查看,我们需要自己创建一个索引,特别简单
效果:
快速入手Switch开关(element-ui提供了方法)
步骤一:作用域插槽
步骤二:将v-model绑定到作用域的mg_state
效果:
fix更改后刷新重置,没有更改数据库值
步骤一:element-ui给了一个解决方法api
步骤二:修改用户状态接口(put)方法
步骤三:监听switch开关状态的改变
接口地址分析:
效果:
快速入手Tooltip 文字提示(element-ui提供了方法)
步骤一:
步骤二:在element.js按需导入
效果:
快速入手Pagination分页(element-ui提供了方法)
步骤一:
事件名称 | 说明 |
---|---|
size-change | pageSize 改变时会触发 |
current-change | currentPage 改变时会触发 |
current-page | 当前页数 |
page-sizes | 每页显示个数选择器的下拉 |
page-size | 每页显示条目个数 |
layout | 组件布局,子组件名需要用逗号隔开 |
total | 总条目数 |
步骤二:传参
第三步:在element.js按需导入
第四步:重置样式(global.css)
效果:
效果:
快速入手Dialog对话框(element-ui提供了方法)
第二步:进入element.js按需引入
第三步:初始化对话框为隐藏
第四步:在添加用户这个按钮上给一个click事件,并赋值为true
效果:
步骤一:
model数据绑定对象 rules验证规则对象 ref引用对象 label-width确定了文本所占宽度
步骤二:添加表单用户的表单数据
步骤三:添加表单的验证规则对象
效果:
新增邮箱、手机校验规则
快速入手Form表单自定义校验规则(element-ui提供了方法)
步骤一:查看官方文档示例
因为邮箱/手机这种校验规则比较复杂,这里推荐大家下个插件
步骤二:增加校验规则
效果:
fix填写完表单后重新打开未重置效果
第一步:element-ui给出了Form表单重置方案
第二步:写一个close的关闭事件
第三步:
效果:
步骤一:当点击确定时,我们需要预加载数据看是否符合规则
效果:
第一步:查看接口文档
第二步:发起axios请求
效果:
第一步:使用Dialog对话框(element-ui给出了例子)
第二步:在编辑按钮上增加click事件
第三步:增加编辑对话框
第四步:methods增加显示为true
第五步:控制修改用户对话框显示与隐藏
效果:
第一步:使用scope.row.id获取到用户id
第二步:查看接口文档
第三步:进行接口文档的调用
第四步:在data中创建editForm
第五步:res的数据保存到第四步中
效果:点击编辑按钮后将id传入到api接口中
第一步:制作表单
第二步:定义验证规则
效果:
第一步:添加一个click事件
第二步:监听修改用户关闭对话框
第一步:在提交按钮上增加一个click事件
第二步:进行预校验
效果:
步骤一:看后端接口
步骤二:在确定按钮上添加click事件
效果:
第一步:导入MessageBox 弹框(element-ui给出了方案)
第二步:在删除按钮上增加一个click(id)事件
第三步:根据id删除对应用户信息(参考elementui给出的方案)
效果:
第四步:使用接口文档进行删除用户信息
第五步:调用接口
效果:
第一步:导入Dialog对话框 弹框(element-ui给出了方案)
第二步:在分配角色按钮新增click事件
第三步:在data中定义对话框初始化为隐藏
第四步:点击角色分配按钮就进行展示为true
效果:
第一步:在data创建接收对象
第二步:查看接口文档
第三步:接口请求
第四步:导入Select选择器(element-ui给出了方案)
第五步:赋予一个接收选中对象的值
第六步:进行组件注册
效果:
第一步:在确定按钮增加click事件
第二步:查看接口文档
第三步:接口调用
效果:
第一步:给分配角色一个close事件
第二步:重置列表
效果:
第一步:写Rights.vue
第二步:在路由引入步骤一
注意:因为在home里面继续跳转,所以权限列表为home的子路由
效果:
第一步:使用面包屑
第二步:使用card卡片
效果:
第一步:创建一个权限列表的接收对象
第二步:创建生命周期
第三步:查看接口文档
第四步:创建方法并声明
效果:
第一步:使用el-card
第二步:使用el-table表格
第三步:使用el-table-column 填入数据 label 定义列名 width定义列宽
第四步:使用el-tag标签
效果:
第一步:写Rights.vue
第二步:在路由引入步骤一
注意:因为在home里面继续跳转,所以权限列表为home的子路由
效果:
第一步:使用面包屑
第二步:使用card卡片
第一步:创建一个权限列表的接收对象
第二步:创建生命周期
第三步:查看接口文档
第四步:创建方法并声明
效果:
第一步:使用el-card
第二步:使用el-row Layout布局
第三步:使用el-table/el-table-column 表格
效果:
第一步:使用插槽进行数据展示/v-for进行循环取出值
效果:
第一步:增加样式
第二步:
效果:
第一步:
效果:
第一步:
效果:
总体效果:
第一步:创建一个样式
第二步:将样式放到需要的位置
效果:
第一步:使用可移除标签(element ui给出了方案)
第二步:点击移除标签是触发的事件
第三步:写二次弹框(element ui 给出了方案)
效果:
第一步:查看接口文档
第二步:接口请求
效果:
第一步:新增一个click事件
第二步:点击分配权限弹框(element ui 给出了方案)
第三步:默认分配权限对话框为隐藏
第四步:点击对话框就显示
效果:
第五步:查看接口文档
第六步:接口调用
效果:
快速入门Tree树形控件(element-ui提供了方法)
第一步:
第二步:将控件树形树形控件属性绑定对象
第三步:进行组件注册
效果:
第一步:在el-tree增加属性(element-ui给了方案)
效果:
第一步:默认勾选节点key的数组(element ui给出了方案)
第二步:在data中定义一个接收对象
第三步:进行递归函数遍历权限接口
第四步:在分配权限增加click事件并拿到所有数据
第五步:将role进行传参,将获取到的id传入第三步defkeys中
效果:
第一步:新增close事件
第二步:监听分配权限对话框关闭事件,没关闭一次,就像defkeys赋值一个空数组
第一步:新增一个click事件在确定按钮上
第二步:定义一个dom元素
第三步:选中权限点击确定
el-tree给了2个函数,getCheckedKeys 节点选择后返回节点的key所组成的数组
getHalfCheckedKeys 节点被选择,返回目前半选节点的key所组成的数组
tips:...为JS中展开运算符
let a={x:1,y:2};
let b={z:3};
let ab={...a,...b};
ab //{x:1,y:2,z:3}
效果:
第一步:查看接口文档
第二步:进行接口请求
效果:
第一步:需要重新创建一个分支取名为:goods_cate
第二步:在comments创建一个goods目录,创建Cate.vue
第三步:写基础骨架
// Cate.vue
<template>
<div>
商品分类组件
</div>
</template>
<script>
export default {
data() {
return {}
},
// 生命周期函数
created() {
},
// 所有的事件处理函数
methods: {
}
}
</script>
<style lang="less">
</style>
第四步:在路由引入
效果:
第一步:引入面包屑
第二步:引入卡片视图
第三步:引入button按钮
效果:
第一步:查看接口文档
第二步:创建data数据
第三步:创建生命周期
第四步:接口请求
效果:
第一步:安装插件
进入到vue ui中依赖--安装依赖---vue-table-with-tree-grid
第二步:在main.js引入插件
第三步:运用插件
data:指定绑定数据;columns:表格各列的配置;selection-type:关闭复选框
expand-type:关闭展开项;show-index:增加索引;index-text:索引名称;border:显示纵向边框;show-row-hover:鼠标悬停是否高亮
第四步:录入数据
效果:
第一步:增加自定义模版列渲染,表格数据,定义插槽
第二步:添加对应样式
效果:
第一步:增加自定义模版列渲染,表格数据,定义插槽
第二步:添加对应样式
效果:
第一步:引入Pagination分页(element ui给出了方案)
size-change:监听pagesize事件;current-change:监听pagenum事件;current-page:当前页;page-sizes:显示下拉条数;page-size:默认显示条数;
total:总条数
第二步:在methods创建对应事件
效果:
第一步:引入Dialog对话框(element ui给出了方案)
第二步:在data中初始化该对话框为隐藏
第三步:在添加分类button上增加一个click事件
第四步:在methods中处理事件
效果;
第一步:引入Form表单(element ui给出了方案)
第二步:查看接口文档
第三步:添加分类相关数据
效果:
第一步:查看接口文档
第二步:接口请求
第三步:在data中定义一个接收对象
第四步:在点击添加分类按钮时进行触发
效果:
第一步:引入Cascader级联选择器(element ui给出了方案)
步骤二:进行数据绑定
第三步:在勾选选项的时候触发日志打印
效果:
第四步:进行组注册
fix下拉数据过多导致显示不全
效果:
第一步:进行数组length判断
第二步:给确定按钮增加一个click事件
第三步:日志打印
效果:
第一步:新增一个close事件
第二步:进行数据重置
效果:
第一步:查看接口文档
第二步:调用接口
效果:
第一步:需要重新创建一个分支取名为:goods_params
第二步:在goods目录创建Params.vue
第三步:写基础骨架
<template>
<div>
分类参数
</div>
</template>
<script>
export default {
data() {
},
created() {
},
methods: {
}
}
</script>
<style lang="less" scoped>
</style>
第四步:在路由引入
效果:
第一步:引入面包屑
第二步:引入卡片视图
第三步:引入alert组件(element ui给出了方案)
第四步:进行组件注册
第五步:增加商品分类
效果:
第一步:查看接口文档
第二步:调用接口
效果:
第一步:引入Cascader级联选择器(element ui给出了方案)
第二步:在data中定义数据
第三步:
效果:
在样式上添加属性:
效果:
第一步:获取selectedCateKeys的长度后进行判断
效果:
第一步:引入Tabs标签页(element ui给出了方案)
第二步:在data中加入activeName参数
第三步:进行tabs页签点击事件处理函数
第五步:注册组件
效果:
第一步:新增button按钮
第二步:新增一个计算属性(computed)
效果:
第一步:查看接口文档
第二步:在computed创建一个函数获取到三级分类的id
第三步:接口调用
第四步:更改tabs标签页中的name
第五步:更改被激活的页签名称
效果:
第一步:将handleChange中的数据抽离出来,创建一个getParamsData函数
第二步:单独添加该函数
效果:
第一步:在data中定义空数组
第二步:进行判断数据属于哪个标签
第三步:进行表格渲染
效果:
在添加参数按钮新增一个click事件
第一步:引入Dialog对话框(element ui给出了方案)
第二步:在data中定义对话框默认隐藏
第三步:在computed中新增titleText达到对话框titile赋值
第四步:引入Form表单(element ui给出了方案)
第五步:在data中新增属性
第六:监听添加对话框的关闭事件
效果:
第一步:查看接口文档
第二步:在确定按钮上新增click事件
第三步:接口请求
效果:
在编辑按钮增加一个click事件
第二步:在data中定义对话框默认隐藏
第三步:引入Form表单(element ui给出了方案)
第四步:在data中新增属性
第五步:关闭对话框进行重置
效果:
采用作用域插槽进行attr_id获取
第一步:查看接口文档
第二步:调用接口
效果:
第一步:查看接口文档
第二步:调用接口
效果:
在删除按钮新增一个click事件
第一步:查看接口文档
第二步:接口调用
引入MessageBox弹框(element ui给出了方案)
效果:
第一步:将数据进行分割重组
第二步:在展开行新增tag标签页,for循环
效果:
第一步:引入New Tags(element ui给出了方案)
第二步:在data中定义相关初始值
第三步:在methods中定义方法
第四步:修改下宽度
效果:
第一步:找到获取参数列表的方法
每一行数据都有自己的bool和value
第二步:使用作用域插槽指定数据
第三步:删除data中定义相关初始值
第四步:在click事件中传入scope.row
第五步:在函数的形参中传入row
效果:
第一步:引入New Tags获取焦点(element ui给出了方案)
效果:
第一步:在属性框增加scope.row
第二步:失去焦点后,从input过度到tags
效果:
第一步:进行输入值长度判断
效果:
第一步:查看接口文档
第二步:调用接口
效果:
第一步:在tags中增加close事件
第二步:将添加tags到数据库的方法单独封装一下
第三步:删除对应参数可选项
效果:
第一步:
效果:
第一步:需要重新创建一个分支取名为:goods_list
第二步:在goods目录创建List.vue
第三步:写基础骨架
<template>
<div>
商品列表
</div>
</template>
<script>
export default {
data() {
return {}
},
created() {
},
methods: {}
}
</script>
<style lang="less" scoped>
</style>
第四步:在路由引入
效果:
第一步:引入面包屑
第二步:引入卡片视图
第三步:引入输入框/按钮
效果:
第一步:查看接口文档
第二步:定义参数
第三步:接口调用
效果:
第一步:
效果:
第一步:全局定义格式化时间的过滤器
第二步:进行调用
第一步:引入Pagination分页(element-ui提供了方法)
第二步:创建方法
效果:
第一步:在input输入框增加数据绑定,清空,清空触发功能
效果:
第一步:在删除按钮上新增click事件
第二步:查看接口文档
第三步:调用接口文档
引入MessageBox弹框(element-ui提供了方法)
效果:
第一步:在添加商品新增一个click事件
第二步:在methods写一个路由跳转的方法
第三步:新增一个Add.vue
第四步:编写Add.vue骨架
第五步:在index.js注册该路由
效果:
第一步:引入面包屑
第二步:引入卡片
第三步:引入Alert警告(element ui给出了方案)
第三步:引入Steps步骤条(elementui给出了方案)
效果:
第一步:引入Tabs标签页(element ui给了方案)
效果:
第一步:新增name索引值、v-model数据绑定
第二步:长得像数字的字符串
第三步:
效果:
第一步:引入Form表单、表格校验
第二步:加入校验规则
效果:
第一步:查看接口文档
第二步:创建声明周期函数
第三步:调用接口函数
效果:
第一步:引入级联选择器
第二步:在addForm新增一个goods_cat接收数据和校验
第三步:级联选择器数据
效果:
第一步:使用element ui 提供函数
第二步:判断是不是选中第一个tabs标签或是否选择了3级选择
效果:
第一步:新增tab被选中时触发(element ui给出了方案)
第二步:查看接口文档
第三步:判断激活面板是否等于1、接口调用
第四步:请求成功后保存到manyTableData
效果:
第一步:在tab被选中时触发
第二步:引入复选框(element ui给出了方案)
第三步:进行组件注册
效果:
第一步:
效果:
第一步:
第二步:将获取到的数据保存到onlyTableData
效果:
第一步:进行表单循环(和商品参数一致)
效果:
第一步:引入Upload上传组件(element ui 给出了方案)
第二步:将Url写在data中,注意这个url是baseURL的根路径
第三步:写方法
第四步:组件注册
效果:
第一步:点击上传图片后在网络请求中可以看到是无效token,就证明发起这个请求并没有携带
第二步:Upload上传给了一个设置上传请求头部的事件
第三步:在el-upload中添加这个事件
第四步:在data中写入请求头
效果:
第一步:Upload图片上传给出了文件上传成功时的钩子(element ui给出了方案)
第二步:将图片信息对象push到pisc中,先创建一个接收对象
第三步:写方法
效果:
第一步:Upload图片上传给出了文件移除时的钩子(element ui给出了方案)
第二步:处理移动图片的操作
效果:
第一步:Upload图片上传给出了文件上传时的钩子(element ui给出了方案)
第二步:引入Dialog对话框
第三步:获取图片预览地址
第四步:控制dialog对话框的显示与隐藏
当点击图片名称就触发
第五步:修改样式
效果:
第一步:安装vue-quil-editor
第二步:man.js进行全局引用富文本编辑器
第三步:在Add.vue引入富文本
第四步:在addForm创建一个goods_introduce接收富文本内容
第五步:修饰样式
效果:
第一步:新增添加商品按钮、click事件
第二步:写click事件方法
知识点:validate是校验表单项prop值,校验是否通过
效果:
第一步:
第二步:引入深拷贝依赖库
第三步:在代码中导入深拷贝库官方地址
为什么需要进行深拷贝呢?因为在此之前级联选择器希望是数组,而另外个希望是字符串产生了分歧,所以同时满足就采用深拷贝。
效果:
第一步:
第二步:新增attrs数组
第三步:
效果:
第一步:查看接文档
第二步:接口请求
效果:
第一步:需要重新创建一个分支取名为:order
第二步:在order目录创建Order.vue
第三步:写基础骨架
<template>
<div>
订单管理
</div>
</template>
<script>
export default {
// 初始化基础数据节点
data(){
return {}
},
// 声明周期函数
created() {},
// 事件处理函数
methods: {}
}
</script>
<style lang="less" scoped>
</style>
第四步:在路由引入
效果:
第一步:引入面包屑
第二步:引入卡片
第三步:引入input搜索框
效果:
第一步:查看接口文档
第二步:增加查询信息
第三步:接口请求
效果:
第一步:引入el-tab表格
第二步:
效果:
第一步:引入Pagination分页
第二步:写对应方法
效果:
第一步:给编辑按钮新增clikc事件
第二步:引入Dialog对话框
第三步:控制默认对话框为隐藏
第四步:点击编辑按钮控制对话框显示
第五步:引入表单校验
第六步:表单校验规则
第七步:引入城市列表(citydata.js)
第八步:引入级联选择器,并将城市数据绑定到opthions
第九步:新增dialog对话框close事件
第十步:关闭对话框后触发清空表单事件
效果:
第一步:在定位图标新增click 事件
第二步:引入Dialog对话框
第三步:设置对话框为隐藏状态
第四步:查看接口文档
第五步:接口请求
效果:
第一步:引入时间线(element ui)给出了方案
第二步:注册组建
效果:
第一步:需要重新创建一个分支取名为:report
第二步:在report目录创建Report.vue
第三步:写基础骨架
<template>
<div>
报表组件
</div>
</template>
<script>
export default {
data() {},
created() {},
methods: {}
}
</script>
<style lang="less" scoped>
</style>
第四步:在路由引入
效果:
第一步:引入面包屑
第二步:引入卡片
效果:
第一步:安装Echars插件
第二步:在项目中引入Echarts
1.导入Echarts
2.创建一个Dom节点
3.创建一个mounted钩子 该钩子的作用是Dom创建完成之后才会执行,此时,页面上的元素已经渲染完毕了
4.准备Echarts展示数据和配置项
5.在页面上展示Echarts
效果:
第一步:查看接口文档
第二步:请求接口
第三步:进行数据合并
效果:
第一步:下载nprogress插件
第二步:在main.js导入nprogress
第三步:在发起axios请求前调用Nprogress.start()
第四步:在发起axios请求后调用Nprogress.done()
效果:
第一步:在开发依赖下载对应插件
第二步:在build过程中,新增该插件
第一步:下载插件【babel-plugin-transform-remove-console】
第二步:在根目录可以看到babel.config.js这个文件
第三步:进行判断为什么环境,如果为生产环境,则使用这个插件,非正式环境则不使用这个插件
效果:现在在开发环境,所以可以正常打印console.log
// 通过 vue-cli 的命令选项可以生成打包报告
// --report 选项可以生成 report.html 以帮助分析包内容
vue-cli-service build --report
在可视化UI面板中,通过控制台和分析面板,可以方便看到项目中所存在的问题
第一步:在根目录创建vue.config.js这个配置文件
第二步:固定写法
// vue.config.js
// 这个文件中,应该导出一个包含了自定义配置选项的对象
module.exports = {
// 选项...
}
第一步:将原来main.js修改成dev和prod模式
第二步:定义打包入口
默认情况下,通过import语法导入第三方依赖包,最终会被打包合并到同一个文件中,从而导致打包成功后,单个文件体积过大的问题。
第一步:配置externals
第二步:删除在main.js引入的资源,进行
第三步:在public文件夹下找到index.html
效果:编译后体积明显变小
效果:编译后体积明显变小
在public/index.html首页中,可以根据isProd的值,来决定如何渲染页面结构
第一步:在vue.config.js中增加一个自定义属性
chainWebpack: config => {
// 发布模式默认打包入口
config.when(process.env.NODE_ENV === 'production', config => {
// html插件新增一个自定义属性
config.plugin('html').tap(args =>{
args[0].isProd = true
return args
})
})
// 开发模式默认打包入口
config.when(process.env.NODE_ENV === 'production', config => {
config.plugin('html').tap(args =>{
args[0].isProd = false
return args
})
})
}
第二步:在index.html中进行判断
效果:编译后体积明显变小
不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件
效果:
第一步:首先去网站进行注册并选好需要的图标下载到本地
第二步:将这个目录放在src/assets里
第三步:去main.js进行引入
第四步:使用图标
git checkout -b 分支名字
git branch
git add .
git status
git commit -m "备注"
git checkout master
git merge 分支
git push -u origin 仓库名(-u 是没有将分支推送到仓库的操作) git push
├─README ├─babel.config.js ├─package-lock.json ├─package.json ├─src ├─vue.config.js └─电商管理后台 API 接口文档
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。