IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue项目后台部分2,文件夹介绍,登录页面,路由的搭建,品牌管理页面使用element-ui动态展示 -> 正文阅读

[JavaScript知识库]Vue项目后台部分2,文件夹介绍,登录页面,路由的搭建,品牌管理页面使用element-ui动态展示

文件夹介绍

build----index.js: 是webpack配置文件
mock:mock数据的文件夹【模拟一些假的数据】,实际开发利用的是真实的接口
node_modules:项目依赖的模块
public:ico图标,静态页面,该文件夹里面经常放置一些静态资源,而且在项目打包的时候webpack不会编译这个文件夹,原封不动的打包到dist文件夹里面
src:
---- 程序员源代码的地方
---- api文件夹:涉及相关请求
---- assets文件夹:里面放置一些静态资源(一般是共享的),放在该文件夹里的静态资源,在webpack打包的时候,会进行编译
---- componets文件夹:一般放置非路由组件或是全局组件
---- icons文件夹放置一些svg矢量图
---- layout文件夹放置了组件和混入
---- router文件夹与路由相关
---- store文件夹与vux相关
---- style文件夹与样式相关的
---- utils文件夹:request.js是axios二次封装文件
---- views 文件夹:里面放置的路由组件
App.vue:根组件
main.js:入口文件
permission.js:与导航守卫相关
settings.js:项目的配置项文件

登录页面

1、静态组件完成,使用element-UI
2、将假的接口换成真实的接口并且解决代理跨域问题,在vue.config.js文件里的devServer中配置如下

//配置代理跨域
proxy: {
  '/dev-api': {
    target: 'http://gmall-h5-api.atguigu.cn',
    pathRewrite: { '^/dev-api': '' }
  }
}

然后重启服务器
3、action

  // 这里在处理登录业务
  async login({ commit }, userInfo) {
    // 解构出用户名与密码
    const { username, password } = userInfo
    let result = await login({ username: username.trim(), password: password });
    // 注意:当前登录请求现在使用mock数据,mock数据code是20000
    if (result.code == 20000) {
      // vuex存储token
      commit('SET_TOKEN', result.data.token)
      // 本地持久化存储token
      setToken(result.data.token)
      return 'ok'
    } else {
      return Promise.reject(new Error('faile'))
    }
  },

4、绑定事件

//登录业务:发请求,带着用户名与密码给服务器(成功与失败)
handleLogin() {
  //这里是在验证表单元素(用户名与密码)的是否符合规则
  this.$refs.loginForm.validate(valid => {
    //如果符合验证规则
    if (valid) {
      //按钮会有一个loading效果
      this.loading = true;
      //派发一个action:user/login,带着用户名与密码的载荷
      this.$store.dispatch('user/login', this.loginForm).then(() => {
        //登录成功进行路由的跳转
        this.$router.push({ path: this.redirect || '/' });
        //loading效果结束
        this.loading = false
      }).catch(() => {
        this.loading = false
      })
    } else {
      console.log('error submit!!')
      return false
    }
  })
}

路由的搭建

删掉不需要的路由组件,删除之后无法运行,因为这些路由已经被配置,所以需要删掉。
新建自己需要的路由,然后搭建路由,使用路由懒加载引入组件。

品牌管理

动态展示

1、静态组件,按钮和表格组件以及分页器

<!-- 表格组件 data:表格组件将来需要展示的数据------数组类型
     border:是给表格添加边框
     column属性
     label:显示标题
     width:对应列的宽度
     align:标题的对齐方式
     prop:对应列内容的字段名
     注意1:elmentUI当中的table组件,展示的数据是以一列一列进行展示数据
   -->
<el-table style="width: 100%" border :data="list">
  <el-table-column label="序号" width="80px" align="center">
  </el-table-column>
  <el-table-column label="品牌名称" width="width">
  </el-table-column>
    <!-- 
      分页器 
      当前第几页、数据总条数、每一页展示条数、连续页码数
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"

      current-page:代表的是当前第几页
      total:代表分页器一共需要展示数据条数
      page-size:代表的是每一页需要展示多少条数据
      page-sizes:代表可以设置每一页展示多少条数据
      layout:可以实现分页器布局
      pager-count:按钮的数量  如果 9  连续页码是7

    -->
    <el-pagination
      style="margin-top: 20px; text-align: center"
      :current-page="page"
      :total="total"
      :page-size="limit"
      :pager-count="7"
      :page-sizes="[3, 5, 10]"
      @current-change="getPageList"
      @size-change="handleSizeChange"
      layout="prev, pager, next, jumper,->,sizes,total"
    >
  </el-pagination>

2、接口
3、写一个获取品牌列表数据的方法
4、品牌管理列表的获取

// 获取品牌列表的数据
async getPageList(pager = 1) {
  this.page = pager;
  // 解构出参数
  const { page, limit } = this;
  // 获取品牌列表的接口
  // 当你向服务器发请求的时候,这个函数需要带参数,因此老师在data当中初始化两个字段,代表给服务器传递参数
  let result = await this.$API.trademark.reqTradeMarkList(page, limit);
  if (result.code == 200) {
    // 分别是展示数据总条数与列表展示的数据
    this.total = result.data.total;
    this.list = result.data.records;
  }
},

5、数据展示

<el-table style="width: 100%" border :data="list">
  <el-table-column type="index" label="序号" width="80px" align="center">
  </el-table-column>
  <el-table-column prop="tmName" label="品牌名称" width="width">
  </el-table-column>
  <el-table-column prop="logoUrl" label="品牌LOGO" width="width">
    <template slot-scope="{ row, $index }">
      <img :src="row.logoUrl" alt="" style="width: 100px; height: 100px" />
    </template>
  </el-table-column>
  <el-table-column prop="prop" label="操作" width="width">
    <template slot-scope="{ row, $index }">
      <el-button
        type="warning"
        icon="el-icon-edit"
        size="mini"
        @click="updateTradeMark(row)"
        >修改</el-button
      >
      <el-button
        type="danger"
        icon="el-icon-delete"
        size="mini"
        @click="deleteTradeMark(row)"
        >删除</el-button
      >
    </template>
  </el-table-column>
</el-table>

6、分页器点击事件

// 获取品牌列表的数据
async getPageList(pager = 1) {
  this.page = pager;
  // 解构出参数
  const { page, limit } = this;
  // 获取品牌列表的接口
  // 当你向服务器发请求的时候,这个函数需要带参数,因此老师在data当中初始化两个字段,代表给服务器传递参数
  let result = await this.$API.trademark.reqTradeMarkList(page, limit);
  if (result.code == 200) {
    // 分别是展示数据总条数与列表展示的数据
    this.total = result.data.total;
    this.list = result.data.records;
  }
},
// 当分页器某一页需要展示数据条数发生变化的时候会触发
handleSizeChange(limit) {
  // 整理参数
  this.limit = limit;
  this.getPageList();
},

添加品牌

1、静态组件

<!--
  对话框
  :visible.sync:控制对话框显示与隐藏用的
  Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可
-->
<el-dialog
  :title="tmForm.id ? '修改品牌' : '添加品牌'"
  :visible.sync="dialogFormVisible"
>
  <!-- form表单 :model属性,这个属性的作用是,把表单的数据收集到那个对象的身上 ,将来表单验证,也需要这个属性-->
  <el-form style="width: 80%" :model="tmForm" :rules="rules" ref="ruleForm">
    <el-form-item label="品牌名称" label-width="100px" prop="tmName">
      <el-input autocomplete="off" v-model="tmForm.tmName"></el-input>
    </el-form-item>
    <el-form-item label="品牌LOGO" label-width="100px" prop="logoUrl">
      <!--这里收集数据:不能使用v-model,因为不是表单元素
        action:设置图片上传的地址
        :on-success:可以检测到图片上传成功,当图片上传成功,会执行一次
        :before-upload:可以在上传图片之前,会执行一次

      -->
      <el-upload
        class="avatar-uploader"
        action="/dev-api/admin/product/fileUpload"
        :show-file-list="false"
        :on-success="handleAvatarSuccess"
        :before-upload="beforeAvatarUpload"
      >
        <img v-if="tmForm.logoUrl" :src="tmForm.logoUrl" class="avatar" />
        <i v-else class="el-icon-plus avatar-uploader-icon"></i>
        <div slot="tip" class="el-upload__tip">
          只能上传jpg/png文件,且不超过500kb
        </div>
      </el-upload>
    </el-form-item>
  </el-form>
  <div slot="footer" class="dialog-footer">
    <el-button @click="dialogFormVisible = false">取 消</el-button>
    <el-button type="primary" @click="addOrUpdateTradeMark"
      >确 定</el-button
    >
  </div>
</el-dialog>

2、点击事件显示对话框

    // 点击添加品牌的按钮
    showDialog() {
      // 显示对话框
      this.dialogFormVisible = true;
      // 清除数据
      this.tmForm = { tmName: "", logoUrl: "" };
    },
    // 修改某一个品牌
    updateTradeMark(row) {
      // row:当前用户选中这个品牌信息
      // 显示对话框
      this.dialogFormVisible = true;
      // 将已有的品牌信息赋值给tmForm进行展示
      // 将服务器返回品牌的信息,直接赋值给了tmForm进行展示。
      // 也就是tmForm存储即为服务器返回品牌信息
      this.tmForm = { ...row };
    },

3、上传图片相关的回调

// 图片上传成功
handleAvatarSuccess(res, file) {
  // res:上传成功之后返回前端数据
  // file:上传成功之后服务器返回前端数据
  // 收集品牌图片数据,因为将来需要带给服务器
  this.tmForm.logoUrl = res.data;
},
// 图片上传之前
beforeAvatarUpload(file) {
  const isJPG = file.type === "image/jpeg";
  const isLt2M = file.size / 1024 / 1024 < 2;

  if (!isJPG) {
    this.$message.error("上传头像图片只能是 JPG 格式!");
  }
  if (!isLt2M) {
    this.$message.error("上传头像图片大小不能超过 2MB!");
  }
  return isJPG && isLt2M;
},

4、完成功能
(1)接口
(2)

//处理添加品牌
//新增品牌: /admin/product/baseTrademark/save   post  携带两个参数:品牌名称、品牌logo
//切记:对于新增的品牌,给服务器传递数据,不需要传递ID,ID是由服务器生成

//修改品牌的
//修改品牌 /admin/product/baseTrademark/update   put   携带三个参数:id、品牌名称、品牌logo
//切记:对于修改某一个品牌的操作,前端携带的参数需要带上id,你需要告诉服务器修改的是哪一个品牌

export const reqAddOrUpdateTradeMark = (tradeMark) => {
    //带给服务器数据携带ID---修改
    if (tradeMark.id) {
        return request({ url: '/admin/product/baseTrademark/update', method: 'put', data: tradeMark });
    } else {
        //新增品牌
        return request({ url: '/admin/product/baseTrademark/save', method: 'post', data: tradeMark });
    }
}

图片收集,action:设置图片上传的地址
(3)功能实现

// 添加按钮(添加品牌|修改品牌)
addOrUpdateTradeMark() {
  // 当全部验证字段通过,再去书写业务逻辑
  this.$refs.ruleForm.validate(async (success) => {
    // 如果全部字段符合条件
    if (success) {
      this.dialogFormVisible = false;
      // 发请求(添加品牌|修改品牌)
      let result = await this.$API.trademark.reqAddOrUpdateTradeMark(
        this.tmForm
      );
      if (result.code == 200) {
        // 弹出信息:添加品牌成功、修改品牌成功
        this.$message({
          type: "success",
          message: this.tmForm.id ? "修改品牌成功" : "添加品牌成功",
        });
        // 添加或者修改品牌成功以后,需要再次获取品牌列表进行展示
        // 如果添加品牌: 停留在第一页,修改品牌应该留在当前页面
        this.getPageList(this.tmForm.id ? this.page : 1);
      }
    } else {
      console.log("error submit!!");
      return false;
    }
  });
},
// 修改某一个品牌
updateTradeMark(row) {
  // row:当前用户选中这个品牌信息
  // 显示对话框
  this.dialogFormVisible = true;
  // 将已有的品牌信息赋值给tmForm进行展示
  // 将服务器返回品牌的信息,直接赋值给了tmForm进行展示。
  // 也就是tmForm存储即为服务器返回品牌信息
  this.tmForm = { ...row };
},

注意:
由于tmFrom是直接影响列表展示的,而服务器收集数据也是用到的tmFrom,当修改品牌时,如果直接将row赋值给tmFrom,tmFrom会影响到服务器返回的值,即使点击取消,表单列表展示的数据也发生了改变,所以此时需要用到浅拷贝,即将服务器的数据拷贝一份赋值给tmFrom而不会影响到row。

(4)表单验证功能

// 自定义校验规则
var validateTmName = (rule, value, callback) => {
  // 自定义校验规则
  if (value.length < 2 || value.length > 10) {
    callback(new Error("品牌名称2-10位"));
  } else {
    callback();
  }
};
  // 表单验证规则
  rules: {
    // 品牌名称的验证规则
    // require:必须要校验字段(前面五角星有关系)  message 提示信息    trigger:用户行为设置(事件的设置:blur、change)
    tmName: [
      { required: true, message: "请输入品牌名称", trigger: "blur" },
      // 自定义校验规则
      { validator: validateTmName, trigger: "change" },
    ],
    // 品牌的logo验证规则
    logoUrl: [{ required: true, message: "请选择品牌的图片" }],
  },

需要所有表单验证通过才可以发送请求

删除品牌

1、弹框设置

    // 删除品牌的操作
    deleteTradeMark(row) {
      // 弹框
      this.$confirm(`你确定删除${row.tmName}?`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(async () => {
          // 当用户点击确定按钮的时候会出发
          // 向服务器发请求
          let result = await this.$API.trademark.reqDeleteTradeMark(row.id);
          // 如果删除成功
          if (result.code == 200) {
            this.$message({
              type: "success",
              message: "删除成功!",
            });
            // 再次获取品牌列表数据
            this.getPageList(this.list.length > 1 ? this.page : this.page - 1);
          }
        })
        .catch(() => {
          // 当用户点击取消按钮的时候会触发
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
  },

2、接口

//删除品牌
///admin/product/baseTrademark/remove/{id}  delete

export const reqDeleteTradeMark = (id)=>request({url:`/admin/product/baseTrademark/remove/${id}`,method:'delete'});

3、当点击确认按钮,要向服务器发请求

// 当用户点击确定按钮的时候会出发
// 向服务器发请求
let result = await this.$API.trademark.reqDeleteTradeMark(row.id);
// 再次获取品牌列表数据
this.getPageList(this.list.length > 1 ? this.page : this.page - 1);
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:05:12  更:2022-09-13 11:06:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:50:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码