• 从零开始,搭建一个简单的购物平台(九)


    从零开始,搭建一个简单的购物平台(八):https://blog.csdn.net/time_____/article/details/105452765
    项目源码(持续更新):https://gitee.com/DieHunter/myCode/tree/master/shopping

    这篇文章将前后端管理功能完成,也就是将最后修改用户信息功能实现(由于商品管理与用户管理类似,所以不做描述),并讲述一下遇到的坑

    修改用户数据后端其实就是根据用户id,将从前端传来的字段对应的值更新,如果头像有变化,则删除之前用户的头像,前端相对服务端反而更繁琐一些,当用户点击修改用户信息按钮后,将用户信息初始化到form表单中(头像同样需要加载),这里考虑到初始化用户信息的实现可以直接获取表格中的数据,可减少一次请求,但是有个小坑,当用户点击修改时,Drawer组件中的form表单初始化是异步的,需要两个解决操作:1.将Drawer中的子组件预加载(开启Drawer中的forceRender属性)。2.将form初始化操作放到form更新渲染完成之后(componentDidUpdate),如果放在componentDidMount中,组件初始化只会进行第一次,下一步,直接开始整后端

    • 服务端在command中新增update方法
     /* 更新数据
       * @param {object} mod       数据库model
       * @param {string} _id       数据唯一标识
       * @param {object} data      更新字段及值
       */
      static updateData(mod, _id, data) {
        //改
        return mod
          .updateOne(
            {
              _id,
            },
            data
          )
          .then((res) => {
            return res;
          })
          .catch((err) => {
            return false;
          });
      }
    • 在user.js文件中添加接口用于更新用户信息
    router.post(Config.ServerApi.updateUser, Util.checkToken, async (req, res) => {
      if (!res._data.headPic.length) {//这里判断是否是修改头像,若是新增,则是上传相关的头像信息,是个object类型,length属性不存在
        let findRes = await findData(Mod, {
          _id: res._data._id,
        });
        if (findRes[0].headPic != "public/assets/img/default.gif") {
          Util.delPicFile(findRes[0].headPic);
        }
        res._data.headPic = Util.readPicFile(res._data.headPic || "") || "";
      }
      res._data.password = Util.createBcrypt(res._data.password);//密码盐加密
      let updateRes = await updateData(Mod, res._data._id, res._data);
      if (updateRes) {
        res.send({
          result: 1,
          msg: "修改成功",
        });
        return;
      }
      Util.delPicFile(res._data.headPic);
      res.send({
        result: 0,
        msg: "修改失败",
      });
    });

    之后我们看看前端功能实现

    前端需要在之前实现的新增用户中做修改,达到相关目的

    • 在upload.js组件中添加初始化显示图片功能,也就是渲染组件时给个src,并且把方法传递给父组件以供调用(放到componentDidMount中),在父组件通过组件属性为子组件设置this中的属性达到调用。当然也可以使用全局events传递参数
    this.props.onUpdateRef(this);//放在子组件中,使父组件调用当前组件
    onUpdateRef={(child) => {//放在父组件的子组件的属性里,通过this.updateChild调用子组件的this
        this.updateChild = child;
     }}

     updatePic(url) {
        if (url && url.length > 0) {
          this.setState({
            fileList: [
              {
                uid: "-1",
                name: url,
                status: "done",
                url,
              },
            ],
          });
        }
      }
    • 全部实现后,可以在自定义的drawer.js组件进行新增用户和修改用户的区分
    showDrawer = (record) => {
        if (record) {//传递了参数说明是更新信息,否则是新增用户
          this.setState({
            formType: "updata",
            visible: true,
            record,
          });
          this.updateChild.updatePic(FilePath + record.headPic);//调用上传头像组件,显示图片
        } else {
          this.setState({
            formType: "add",
            visible: true,
            record: {//新增用户的初始值
              sex: "man",
              userType: "user",
              mailurl: "@qq.com",
            },
          });
        }
      };
    • 在componentDidUpdata中添加更新form方法,将state中的record初始化至form中
    componentDidUpdate() {
        this.formRef.current.setFieldsValue(this.state.record);
    }
    • 在Drawer隐藏方法中将表单初始化并清空state中的record
    onClose = () => {
        this.formRef.current.resetFields();
        this.setState({
          visible: false,
          record: null,
        });
     };

    效果如下

    最后,我们试试将数据提交至后端

    总结:

    到现在为止,项目中的用户管理前端+服务端功能已全部实现,商品管理的功能实现与用户同理,但是字段名不同,不做说明,下一篇文章直接开始搭建商城前端及后端功能

  • 相关阅读:
    VB程序破解常用函数
    去VB程序NAG窗口方法-4C法
    error LNK2005: _DllMain@12 已经在 XXXX.obj 中定义
    汇编中的test和cmp指令
    OD保存修改后的数据到EXE
    C++ 异常捕获 try 和 __try的区别
    CListCtrl选中行
    WindowsAPI解析IAT地址
    Usaco 4.3.1 Buy Low, Buy Lower 逢低吸纳详细解题报告
    全国青少年信息学奥林匹克分区联赛(N)竞赛大纲
  • 原文地址:https://www.cnblogs.com/HelloWorld-Yu/p/13514432.html
Copyright © 2020-2023  润新知