项目知识点

1.项目简介

2.项目使用到的技术

3.功能实现

3.1登录功能

初始化Login.vue

<template>
    <div class="login_container">
        
    </div>
</template>

<script>
export default {
  
}
</script>

<style lang="less" scoped>
.login_container {
  background-color: #2b5b6b;
  height: 100%;
}

</style>

style标签中的scoped可以防止组件之间的样式冲突,没有scoped则样式是全局的

在router.js中导入组件并设置规则

const router = new Router({
  routes: [
    { path: '/', redirect: '/login' },
    { path: '/login', component: Login }
  ]
})

在App.vue中添加路由占位符   

 

 当我们给Login.vue中的内容添加样式的时候,会报错“缺少less-loader”,需要配置less加载器(开发依赖),安装less(开发依赖)

在asset中设置全局样式global.css,并在main.js中引入

使用Element_UI组件实现布局

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

 通过 :model = "loginForm"为el-form表单动态绑定一个数据对象,并在data中定义数据对象

loginForm: {
        username: 'admin',
        password: '123456'
      },

 为每一项 el-input 框绑定数据对象的属性

登录组件表单的数据验证

首先要给el-form绑定一个rules属性,值是一个表单的验证规则对象

在data中定义验证规则对象,定义需要的验证规则,这里验证规则一般都是数组,数组中的每个对象都是验证规则

required:true  表示这一项为必填项 

message:'xxxxxxxx' 表示不符合规则时会弹出这个消息

trigger:‘blur’ 表示鼠标 失去焦点的时候触发这个验证

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属性可以绑定具体的验证规则

点击重置按钮,重置整个表单的数据校验结果

需要为表单加一个 ref 引用 ref="LoginFormRef",这样就可以在登录组件中获取到表单的dom对象,为重置按钮绑定一个点击事件,触发resetLoginForm()方法通过ref重置表单

resetLoginForm() {
      this.$refs.LoginFormRef.resetFields()
    },

 登录组件的预验证

点击登录按钮时,通过表单的引用对象调用validate函数进行预验证

为登录按钮绑定点击事件,触发login()方法,在该方法中,首先对数据进行预验证,如果验证失败则直接返回。

验证通过,则向服务器发送post请求,通过await简化Promise,await只能用在被async修饰的方法中,所以我们要将紧挨着await的那个方法修饰成异步的async方法

然后将服务器返回的data数据解构赋值给res,判断res的中的meta中的status状态码,如果是200,则弹出登录成功的$message信息,并且将服务器发送过来的res.data.token保存到浏览器的sessionStorage中,并通过push跳转到 /home

关于token:

项目中出了登录之外的其他API接口,必须在登录之后才能访问;token只应在当前网站打开期间生效,所以将token 保存在sessionStorage 中

如果状态码不是200,则弹出失败的信息。

login() {
      //点击登录的时候先调用validate方法验证表单内容是否有误
      this.$refs.LoginFormRef.validate(async valid => {
        console.log(this.loginFormRules)
        //如果valid参数为true则验证通过
        if (!valid) {
          return
        }

        //发送请求进行登录
        const { data: res } = await this.$http.post('login', this.loginForm)
        //   console.log(res);
        if (res.meta.status !== 200) {
          return this.$message.error('登录失败:' + res.meta.msg) //console.log("登录失败:"+res.meta.msg)
        }

        this.$message.success('登录成功')
        console.log(res)
        //保存token
        window.sessionStorage.setItem('token', res.data.token)
        // 导航至/home
        this.$router.push('/home')
      })
    }

为了向服务器发起请求,需要引入axios包,并将改包挂载到Vue的原型对象上,这样所有组件都可以通过this直接访问$http,从而发起请求

打开main.js,

import axios from 'axios'; 

设置请求的根路径:

​axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'

 挂载

Vue.prototype.$http = axios;

其中$Message也需要进行element-ui 的按需引入并进行全局挂载

如果用户没有登录,但是直接通过URL访问特定网页,需要重新导航到登录页面,在router/index.js中添加下面代码

挂载路由导航守卫,to表示将要访问的路径,from表示从哪里来,next是下一个要做的操作 ,只有将要访问的路径为login或者token不为空时才放行。访问任何一个路由都会经过该路由守卫。

router.beforeEach((to,from,next)=>{ 
  if(to.path === '/login')
    return next();
  
  //获取token
  const tokenStr = window.sessionStorage.getItem('token');

  if(!tokenStr)
    return next('/login');

  next();

})

退出功能

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

在/home中为退出按钮绑定点击事件loginout,触发后清空sessionStorage,并使用push回到/login

logout(){
            window.sessionStorage.clear();
            this.$router.push('/login');
        }

处理ESLint警告

默认情况下,ESLint和vscode格式化工具有冲突,需要添加配置文件解决冲突。 在项目根目录添加 .prettierrc 文件

{
    "semi":false,
    "singleQuote":true
}

打开.eslintrc.js文件,禁用对 space-before-function-paren 的检查:

rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'space-before-function-paren' : 0
  },

3.2 后台主页布局

首页是一个包含头部header,侧边Aside ,主内容区Main的结构布局,首先需要按需引入el-container,el-header,el-aside,el-main,并进行页面布局,在header中设置display:flex,并使其中的子元素中间填充 justify-content: space-between,使他们靠在两边,为子元素设置diaplay:flex 和 align-items:center,使登录按钮不贴边。

左边菜单栏分为两级,并且可以折叠,需要引入Menu,Submenu,MenuItem,

Submenu表示一级选项,MenuItem表示二级选项

axios请求拦截器

在进入主页时,就应该向服务器发送axios请求,但是向服务器发送请求时,需要带上token,获取访问数据的权限,否则服务器会拒绝访问,因此在每次向服务器发送请求时,需要一个请求拦截器

axios中有一个interceptors属性,里面有一个request成员,这个成员就是我们的请求拦截器

使用use函数给request挂载一个回调函数

我们向服务器端通过axios发送请求,在发送请求期间必然会先调用use这个回调函数进行预处理

config表示我们对这个请求头进行了预处理,经过预处理后,我们的请求才会真正发送到服务器,也就是在请求头中添加了Authorization字段,存储用户的token,这样请求头中就会带有token,服务器验证以后就会向我们返回数据。

axios.interceptors.request.use(config=>{
  //为请求头对象,添加token验证的Authorization字段
  config.headers.Authorization = window.sessionStorage.getItem("token")
  return config
})

请求侧边栏数据

在生命周期created阶段调用一次请求函数getMenuList(),同样用await简化Promise,并结构赋值给res,并判断状态码;

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.data
      console.log(res)
    }

拿到数据后将data赋值给menuList,数组对象,每个值为一个对象,代表一个一级选项

 然后通过v-for双重循环渲染左侧菜单,为了防止点击一个选项后,所有选项都展开,需要为每个选项绑定一个唯一的index,由于index只接受字符串,所以不能直接使用id,需要在后面拼接一个字符串来进行类型转换。

<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>

然后为每个选项渲染图标,这里使用对象存储图标名

iconsObj: {
        '125':'iconfont icon-user',
        '103':'iconfont icon-tijikongjian',
        '101':'iconfont icon-shangpin',
        '102':'iconfont icon-danju',
        '145':'iconfont icon-baobiao'
      }

 通过item.id访问,这样使每个选项的图标随id的变化而变化

为了保持左侧菜单每次只能打开一个,显示其中的子菜单;我们可以在el-menu中添加一个属性unique-opened(unique-opened="true")

制作侧边菜单栏的伸缩功能

为了实现左侧菜单的折叠和展开功能,需要在Home.vue的侧边栏里面添加一个div,并绑定点击事件toggleCollapse,该事件触发后使isCollapse的值取反,isCollapse动态绑定在菜单栏容器的el-menu的collapse属性上,该属性为false时,菜单栏展开,为true时菜单栏收起,并通过collapse-transition关闭折叠动画,布尔值也需要动态绑定才会作为js语句执行。

<el-menu
          :collapse="isCollapse"
          :collapse-transition="false"
          ......
 <div class="toggle-button" @click="toggleCollapse">|||</div>

最后根据折叠切换侧边栏的宽度,折叠时设置为64px,否则设置为200px

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

为了使菜单栏选项被点击后,页面发生跳转,需要为二级菜单改为路由链接,el-menu中的router属性,会开启vue-router模式,使选项被激活时路由根据index发生跳转

 

3.3 完成用户列表主体区域

创建user列表,并创建User组件,并在router.js和index.js中导入用户列表组件

在点击二级菜单时,需要高亮提示正在使用该功能,在刷新页面后仍然保持高亮,el-menu中的default-activate属性可以控制当前激活菜单的index,被激活的index会高亮显示,但是这个index不能写死,需要将default-active属性动态绑定为activePath

因此可以为每个二级菜单绑定一个点击事件saveNavState,触发时传递被激活的路由的路径为参数,并将其存入sessionStorage中,并赋值给activePath,使点击时菜单高亮

然后在数据中添加一个activePath绑定数据,当页面刷新并加载时,在其生命周期created将保存在sessionStorage的地址赋值给activePath,使刷新后仍然保持高亮

@click="saveNavState('/'+subItem.path)"
saveNavState( path ){
  //点击二级菜单的时候保存被点击的二级菜单信息
  window.sessionStorage.setItem("activePath",path);
  this.activePath = path;
}

 绘制用户列表基本结构

使用element-ui面包屑组件完成顶部导航路径

使用element-ui卡片组件完成主体表格,再使用element-ui输入框完成搜索框及搜索按钮,此时我们需要使用栅格布局来划分结构(复制卡片组件代码,在element.js中导入组件Row,Col),el-col中的span指定占多宽的位置,el-row中的gutter属性指定每一栏之间的间距。然后再使用el-button制作添加用户按钮

请求用户列表数据  

//获取查询用户信息的参数
      queryInfo: {
        query: '',
        pagenum: 1,
        pagesize: 2
      },
//保存请求回来的用户列表数据
      userList:[],
      total:0

向user发送get请求时需要携带一个参数,这个参数用queryInfo对象展示,表示需要获取的页数,该页有展示多少条数据,以及要查询的query,成功返回后赋值给userList和total,将userList渲染到页面 ,用el-table来展示,data指定数据源,el-table-column中的label指定列明,prop指定对应的值,也就是数据源中的属性

添加表格线,隔行变色,索引列

async getUserList() {
      //发送请求获取用户列表数据
      const { res: data } = await this.$http.get('users', {
        params: this.queryInfo
      })
      //如果返回状态为异常状态则报错并返回
      if (res.meta.status !== 200)
        return this.$message.error('获取用户列表失败')
      //如果返回状态正常,将请求的数据保存在data中
      this.userList = res.data.users;
      this.total = res.data.total;
    }
created() {
    this.getUserList()
  },

改变状态这一列可以通过作用域插槽来渲染

作用域插槽接收scope,通过scope点出来row这个属性,scope.row就是这一行的数据,

拿到这一行的数据,我们就可以通过scope.row.mg_state获取状态的数据,获取到了状态数据,需要通过switch组件渲染成开关

操作栏的按钮使用el-button,并改变颜色

实现数据分页效果

使用el-pagination实现分页效果

当触发size-change和current-change效果时,pagesize和pagenum发送变化,此时重新向服务器发送请求,重新渲染页面

用户状态更改

switch是通过v-model双向数据绑定到用户的状态,我们将用户的数据传过来,如果用户数据发生改变就会触发事件处理函数,将绑定的状态作为参数

触发后调用api接口保存用户的最新状态,判断状态码是否为200,不是则返回提示信息,并且将用户状态恢复到一开始的样子

搜索功能

首先将搜索文本框的数据和data中的数据进行双向绑定,然后我们点击按钮的时候调用获取用户列表的函数进行数据的查询

清空输入框后显示全部用户数据

添加用户功能

点击按钮显示对话框,我们需要给添加按钮绑定一个单击事件,在单击事件中将addDialogVisible重置为true就可以了,addDialogVisible动态绑定给visible.sync属性,控制对话框的显示与否

对邮箱和手机进行自定义规则

在data里定义一个箭头函数,代表一个校验规则,然后给校验规则起一个名字,在具体的规则中通过validator来使用自定义规则

  // 验证邮箱的规则
    const checkEmail = (rules, value, callback) => {
      // 验证邮箱的正则表达式
      const regEmail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/
 
      if (regEmail.test(value)) {
        return callback()
      }
 
      callback(new Error('请输入合法的邮箱'))
    }
 
    // 验证手机的规则
    const checkMobile = (rules, value, callback) => {
      // 验证手机的正则表达式
      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 callback()
      }
 
      callback(new Error('请输入合法的手机'))
    }

 监听对话框的关闭事件,在关闭事件中拿到表单的引用调用reserFields方法重置表单

 添加用户的预验证功能

给确定按钮绑定一个事件处理函数

 

然后发起post请求添加一个新用户

修改用户信息

在添加用户对话框下方添加一个修改用户的对话框,在data中定义一个editDialogVisible,值为false,给修改按钮绑定一个单击事件,事件处理函数只要将editDialogVisible设置为true即可展示对话框

使用作用域插槽的scope.row可以获取一行的数据,而我们就可以使用scope.row.id获取这一行数据的id

在data中定义一个空的用户数据对象,将接收到的id调用api接口查询用户的信息,并把查询到的信息保存到我们的表单数据对象上,然后绘制表单,动态绑定给表单

给对话框添加关闭响应事件,在事件函数中调用引用对象的resetFields方法实现关闭对话框对表单验证的重置,给确定按钮绑定单击事件函数,要对用户的信息进行预验证,发起预验证后才能进行真正的修改,然后发起修改用户的put请求

删除用户

首先要在vue原型上挂载confirm函数,这样子每个组件都可以访问到confirm,给删除按钮绑定一个单击事件函数,传入id作为参数, 在行为区域定义removeUserById函数,复制弹框的代码到removeUserById函数中,this.$confirm函数的返回结果是promise,我们就可以使用async和await来优化promise操作,用户确定删除则返回值为confirm,取消删除返回值为cancel,确认删除后发起delete请求。

 3.4 权限管理制作

权限列表

创建组件Right.vue,防止home的children中

同样是面包屑导航和卡片试图,页面加载时在created里发起get请求获取权限列表数据并存储,使用el-table渲染数据,使用自定义插槽给权限等级加上el-tag标签,使用v-if判断来按需展示,权限为0显示等级一,为2显示等级二,为3显示等级三

角色列表

创建Role组件,获取数据并接收,然后渲染表格,使用自定义插槽来展示操作,在索引列前面添加展开列

 角色数据里的children时角色所拥有的权限,点击展开列时展开该行角色的权限,每个权限有自己的id,使用作用域插槽的scope.row拿到对应的角色信息,通过三层for循环把对应的权限渲染出来

  美化一级,一级权限之间添加间距,给row添加边框线,每个都设置下边框线,索引为0的设置上边框线,给二级权限添加上边框线,索引为0的就去除上边框线,

 居中对齐,定义一个类,给需要的添加这个类

删除权限的功能

为tag设置closable属性,并添加删除小图标 

关闭“删除小图标”就会触发 单击事件 ,弹出确认框,然后发起删除请求

 为了防止删除权限后展开列合上,我们将服务器返回的数据直接赋值给role的children,响应的是当前角色最新的权限数据,并为二级权限和三级选项都添加closable事件。

分配权限

为按钮绑定单击事件,添加对话框, 设置对话框的显示与隐藏,默认隐藏,当点击“分配权限”时请求所有权限的数据,发起数据请求后再将对话框显示出来,将响应的数据以树形结构el-tree渲染到页面中。data绑定需要渲染的数据源,props指定的是数据绑定字段,通过哪个属性来实现父子间的嵌套的,实现父子嵌套使用的children属性,label表示看到的文本

 

 为树形控件添加复选框,并绑定唯一标识属性,和是否默认展开所有节点

 将角色已有的权限默认勾选

思路:点击“分配权限”按钮时将当前角色身上所有三级权限的id获取出来,放到一个数组中,并且把这个数组通过属性绑定交给default-checked-keys

要获取三级节点,可以在页面中定义一个递归函数,把角色信息传到递归函数中,通过递归的形式把所有三级节点的id都保存到一个数组中,这样的话我们把那个数组复制给defKeys,就可以实现点击“分配权限”的时候,把已有的权限默认勾选上。

定义一个递归函数,需要传递一个参数来判断它是否为三级节点,同时还需要一个数组来保存

如果当前node节点不包含children属性,则是三级节点,我们就将node节点的id添加到arr数组中, 如果没有return表示它还不是三级节点,我们需要调用递归来获取到最终的三级节点,循环当前node节点里的所有数组,每循环一项,拿到一个子节点item,再根据item调用递归函数,把当前的item节点传进去,当递归完毕后,所有三级节点的id都保存到arr数组中了

 点击分配权限按钮时,绑定一个点击事件,触发该事件后在现实对h话框前调用这个递归函数,参数为一整行的数据

为了防止数组中的id越来越多。所以我们应该在关闭“分配权限”时都把数组清空一下

在对话框绑定一个对话框关闭的事件处理函数,每次关闭时将数组清空

点击确定后,向服务器发送请求,将新勾选的或者取消的保存在服务器中

 在点击确定的时候,只需要拿到树形结构的引用,然后分别调用getCheckedKeys和getHalfCheckedKeys两个函数,就可以获取到选中的id数组和半选中的id数组,并存入数组,最后拼接为字符串,在弹出分配权限对话框时,将角色id保存,在服务器发送请求时将id拼接到路径中,以刚刚拼接的字符串为参数发送给服务器,最后重新获取一次角色列表数据,关闭对话框

 

 用户列表的分配角色

与分配权限一样,需要一个对话框,开启时获取一行的数据,向服务器发送请求获取所有角色列表,角色渲染在对话框,角色列表渲染在下拉框, 在data中定义selectRoleId,用来保存已选中的角色的id值,点击确定按钮时,把新分配的角色保存到当前的用户角色中,并发起请求保存到服务器,最后重新获取用户列表数据,关闭对话框时,清空对话框中这一行的数据

 3.5 商品分类

(48条消息) 黑马程序员课程Vue实战项目_Element-ui——电商后台管理系统-商品管理(商品分类)_elementui分类管理页面_Super咩咩的博客-CSDN博客

创建组件,绘制页面基本结构,前面操作与之前的相同,定义查询条件,页数,页面大小等

将服务器返回的数据使用vue-table-with-tree-grid

 label指的是列的标题,prop指定的是这一列绑定的属性

 

 隐藏勾选框,将展开项移除,添加索引列,添加纵向边框,取消高亮,使用自定义模板渲染后三列

自定义一个新的列

  在表格中定义一个插槽,它的名字为isok,通过作用域插槽的形式接收到 这一行的数据,渲染对勾和叉号这两个小图标,并按需渲染

 创建一个新的模板列在column中,列名是排序,使用el-tag展示是几级,并按需渲染

 

渲染一个新的模板列,用来放编辑和删除操作的图标 

添加分类功能

添加一个添加分类的对话框,在里面添加表单,定义添加分类表单的数据对象,在data中定义添加分类表单的验证规则对象,点击添加分类,调用发送请求的函数,向服务器获取前两级分类,赋值给父级列表,将父级分类渲染到级联选择框中,动态绑定数据。

 

 监听级联选择器的改变,更新父级分类的id和分类的等级

没有选择父级分类,selectedKeys数组中的length为0,那么a为父级,父级的id为0,a的等级为0

选择了“大家电”,selectedKeys数组中的length为1,父级id为数组中最后一项,那么a的父级id为1,a的等级为1 

选择了“大家电/电视”,selectedKeys数组中的length为2,父级id为数组中最后一项,那么a的父级id为3,a的等级为2

父级id=this.selectedKeys[this.selectedKeys.length-1]

a的等级=this.selectedKeys.length

点击确定,对表单进行验证,向服务器发送请求,刷新数据列表,关闭表单,重置表单

3.6 商品列表

同上步骤,面包屑导航,渲染el-table,作用域插槽放入操作列

服务器返回的时间是一个时间戳,因此需要定义一个全局的时间过滤器

 在创建时间那一列使用作用域插槽的形式,调用过滤器渲染时间

添加分页区重复

搜索功能重复

删除功能重复

商品列表

商品列表使用了一个el-alert警告,后面是一个el-steps步骤条

在data中定义activeIndex值为0,用来控制步骤条激活的索引,步骤条绑定:activate=activeIndex

步骤条后面是一个el-tab标签页,el-tab-pane表示一个标签

tabs可以使用v-model来指定激活的哪个面板,如果点击第一个,就会把第一个的name保存到activeName身上,所以我们需要将步骤条的active和tabs的v-model绑定同一个值,这样子tab改变了name值,activeIndex就会跟着改变,步骤条也会跟着activeIndex改变而发生改变,name是字符串类型,所以要将activeIndex变为字符串0,但是步骤条的active只绑定数字型的值,我们可以将activeIndex字符串-0就可以变成数字了

 使用表单将tabs包裹起来,将label设置在文本框的上面

 在data中定义表单数据对象和表单验证对象,在第一个pane面板中创建form-item,其中有两个属性,label指定标题名称,prop指定验证规则,在form-item里添加输入框

让价格,重量,数量只能输入数字,在input加type=“number”,需要把tabs的固定高度删掉,然后获取商品分类的信息,将获取到商品分类数据渲染成级联选择器,动态绑定goods_cat定义配置项、验证规则

控制级联选择器的选择范围,只允许选择三级,不允许选择二级或者一级的商品分类,使用v-if和v-else,如果数组length=3,我们就允许选中,如果不等于3,我们就清空,我们在handleChange函数中做一下判断

监听标签页的切换事件,然后在事件的处理函数中判断当前是否处于第一个页签,同时还要判断选中的商品分类是否为三级分类,是三级分类则允许切换,否则不允许切换

触发before-leave属性,会调用一个函数,第一个参数是即将要跳转的标签页的name,第二个参数是即将离开的标签页的name,我们拿到这两个参数就可以判断了

商品参数面板

请求路径中的参数是选中的三级分类的id, 通过get方式向服务器提交一个参数叫做sel,我们打开的动态参数面板,所以将sel规定为many就可以了

在点击第二个面板的时候获取参数数据列表,给Tabs标签页绑定tab-click事件,当它被选中的时候会触发

在computed中定义一个计算属性,计算三级商品分类id

触发标签点击事件时,首先先判断是否选中第二个面板,然后再发起数据请求,

渲染表单的item项,item项的label不应该写死,使用v-for循环,将attr_name作为label值,attr_id作为key值

将item项里面的attr_vals渲染成复选框,可以将数组渲染成复选框,但是attr_vals是字符串,首先我们应该先把attr_vals字符串转变为数组

在将参数列表数据赋值之前,参数列表数据forEach循环,每循环一次都会得到一个item项,item项里面有一个attr_vals字符串,先判断是否为空字符串,然后将它使用split(‘ ’)变成数组

 添加复选框

 

然后是商品属性面板

同样获取数据,在el-form-item标签中, 使用v-for循环获取到的数组,每循环一次都会得到一个item项,将item项的attr_name绑定给label,将attr_id绑定给key

渲染文本框,双向绑定每一项的attr_vals

商品图片面板

使用el-upload组件

action属性——图片要上传的后台api地址

on-preview属性——指定预览事件,处理图片预览效果

on-remove属性——点击叉号,触发事件,处理移除图片的操作

list-type属性——当前组件呈现的预览方式

upload组件没有使用axios发送ajax请求,而是它自己内部封装了一套ajax,它自己封装的ajax是没有携带Authorization字段的,需要给upload绑定一个请求头:header, 在data中定义请求头。

监听上传成功:on-success这个操作,将服务器返回的临时路径以对象的形式添加到pics数组中,在事件处理函数中将服务器返回的临时路径以对象的形式添加到pics数组中

监听on-remove事件,将图片从pics数组中移除

添加一个对话框,用来预览图片,在data中定义一个空字符串previewPath,用来存放要预览的图片地址,点击预览时给其赋值,插入图片在对话框中

商品内容面板

 安装vue-quill-editor依赖,注册为全局可用的组件,添加富文本编辑器,双向绑定到data的addForm的goods_introduce

 

 点击添加商品,拿到表单引用对象,进行预验证,发起请求之前,由于addForm中的goods_cat之前被处理成为了数组,由于服务器限制,这里要变为字符串,为了不影响级联选择器,所以需要深拷贝addForm,将深拷贝的数组拼接为字符串

由于attrs里的数据不完整,动态参数和静态属性是分开获取的,我们需要循环manyTableData和onlyTableData这两个数组,将循环的每一项进行处理,将处理的结果push到attrs数组中,最后还需要将addForm里的attrs赋值给form的attrs

 最后将新的表单数据发送给服务器

3.6 分类参数

面包屑导航--》 卡片试图--》警告区域

发送数据请求获取所有的商品分类,渲染级联选择器,功能重复

定义标签,功能重复,不过是横向的标签

selectedCateKeys数组长度为3,启用,selectedCateKeys数组长度不等于3,禁用,通过计算属性,数组长度为三,计算属性为true,绑定在button上,实现禁用和启用。

根据选中的商品分类,结合参数的类型,从而获取表格里的数据,需要分类id,要获取的是静态还是动态。分类id可以通过返回数组中的最后以为来获取,属性类别可以通过tab-pane对应的name获取。默认是动态属性,应该在级联选择项改变的那个函数中去发送数据请求

解决第一个问题

切换面板但是请求并没有发起

所以我们应该把获取数据抽离成一个函数,这样级联选择器发生变化,面板发生变化都可以调用这个函数

解决第二个问题

getParamsData函数获取到的数据只有一份,获取到的是动态参数还是静态属性呢?

我们的页面是需要渲染两个table表格的,获取到的数据是给哪个表格来使用的呢?

所以我们要将获取到的数据进行判断

首先在data中定义两个空数组,分别用来保存动态参数和静态属性的数据, 在getParamsData函数中进行判断赋值

然后渲染表格

添加属性/参数功能重复,唯一不同是这里两个按钮控制的同一个对话框,需要使用计算属性计算出是动态参数还是静态属性

添加表单和验证规则,关闭重置表单,表单打开前发送请求,点击确定时对表单镜像预验证,然后发送请求

然后是编辑,动态和静态的编辑使用同一个对话框,事件处理函数相同,编辑功能重复

删除,动态和静态的删除事件处理函数相同,删除功能重复

渲染参数下的可选项

将获取到的参数的可选项渲染成一个一个的tag标签,首先需要从服务器返回的数组中将获取到attr_vals字符串,然后用空格分割,分割得到的数组,通过for循环就可以渲染成一个一个的tag标签了 ,在展开行渲染tag标签,使用作用域插槽接收这一行的数据

问题1

 解决办法:

 原因:空字符串使用空格split的话会返回一个空字符串,所以渲染出一个空白的el-tag标签

 使用三元表达式判断,不为空则分割,为空则赋值空数组

点击按钮,按钮消失,取而代之的是一个文本框,文本框失去焦点就会隐藏,按钮显示,使用v-if和v-else就可以实现,在这里只需要添加一个布尔值来控制两者的切换

 问题1:

点击一个按钮,两个都变成了输入框,两行数据有联动效果,原因:每渲染一行,它们都绑定同一个值,所以才导致这样子的问题

解决方法:

给每一行的数据都提供一个布尔值和一个value值,绑定自己那一行的布尔值和value值 

 

点击添加按钮的时候应该把这一行数据传过去,把这一行的inputVisible改为true

点击添加按钮的时候还不能立即获取焦点,必须等input输入框渲染出来后再获取焦点

3.7 订单列表

修改功能重复,其中表单中的级联框渲染城市列表数据需要引入js文件

查看物流信息,发起请求获取物流信息,使用时间线渲染物流框

 3.8 数据报表

 安装echarts依赖并导入,需要为echarts准备一个容器,在mounted中初始化图表

设置配置项,展示数据

 发送数据请求,将获取到的数据替换为option

 为了实现鼠标跟随效果,需要合并数据,因为data中的数据不完整

进度条

下载nprogress依赖,并使用npm安装

在request拦截器中,展示进度条

 在response拦截器中,隐藏进度条

 在serve阶段可以打印出console,在build阶段不打印console

安装babel-plugin-transform-remove-console依赖,选择开发依赖

在babel.config.js文件中添加'transform-remove-console'

 添加'transform-remove-console'

让它只在发布阶段生效,测试阶段不生效,在babel.config.js文件中添加一个空数组,如果是发布阶段,就添加'transform-remove-console' 

 项目优化&上线

(48条消息) Vue项目优化&&项目上线_vue项目上线_Super咩咩的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值