12月工作笔记整理(前端)

12月快忙疯了,但是我学到了很多东西吧,由于产品经理的严格,导致我前端被逼无奈加了很多细节交互,不靠谱后端导致联调时间还在补接口,然后延期算在前端头上,很不开心。
好不容易第一个阶段结束了,抽空写一下总结。

一、关于表格的一些交互

1.表头自定义
需求分析:结合了elementUI的table组件做的一个需求,要求通过一个表头选择,触发表格的表头项的变化。
需求拆分:要把表头作为一个数组灵活导入,还要通过选项改变这个数组,就可以修改表头了。

dataHeader是灵活定义的表头数组,在 这里定义表头的属性和值,还可以设置排序、是否固定在一侧等。然后通过选择表头数据的交互,去把表头变化一下就可以实现了。

 < el-table-column
                :label="item.label"
                :property="item.name"
                min-width="150"
                v-for="(item, index) in dataHeader"
                :key="index"
                :fixed="item.fixed"
                :sortable="item.sortable"
              >
              </ el-table-column>
//灵活的表格代码

 <div class="table">
            <el-table
              ref="multipleTable"
              :data="tableData"
              tooltip-effect="dark"
              style="width: 100%"
              :header-cell-style="{ background: '#FAFAFA' }"
            >
              <!-- 空图标显示 -->
              <div slot="empty">
                <div class="imgStyle">
                  <img
                    src="@/assets/img/none.png"
                    alt="暂无数据"
                    width="240"
                    height="208"
                  />
                </div>
                <strong>未查询到记录</strong>
              </div>
              <el-table-column
                :label="item.label"
                :property="item.name"
                min-width="150"
                v-for="(item, index) in dataHeader"
                :key="index"
                :fixed="item.fixed"
                :sortable="item.sortable"
              >
              </el-table-column>
              <el-table-column
                fixed="right"
                label="操作"
                width="160"
                align="center"
              >
                <template slot-scope="scope">
                  <el-button
                    type="text"
                    size="small"
                    class="slot"
                    @click="handleEdit(scope.row)"
                    >编辑</el-button
                  >
                  <el-button
                    type="text"
                    size="small"
                    class="del"
                    @click="handleDelete(scope.row)"
                    >删除</el-button
                  >
                </template>
              </el-table-column>
            </el-table>
          </div>

2.合并同列的表格
需求分析:想要合并表格中相同列的数据,需求是实现第一列的数据合并

在el-table 里加上 :span-method=“objectSpanMethod”

//核心方法是下面两个
  //判断第一列相同的内容,然后合并行列
    flitterData(arr) {
      //存储要合并的行数
      let spanOneArr = []
      //记录合并的索引
      let concatOne = 0
      arr.forEach((item, index) => {
        //如果是一行的话,直接不用合并
        if (index === 0) {
          spanOneArr.push(1)
        } else {
          //item.合并列的属性
          if (item.period === arr[index - 1].period) {
            //第一列需合并相同内容的判断条件
            spanOneArr[concatOne] += 1
            //被合并的取0
            spanOneArr.push(0)
          } else {
            //不相等就取1,并把当前索引赋值过去
            spanOneArr.push(1)
            concatOne = index
          }
        }
      })
      return {
        one: spanOneArr
      }
    },
    objectSpanMethod({ rowIndex, columnIndex }) {
      // 判断第一列
      if (columnIndex === 0) {
        //拿到列数
        const _row = this.flitterData(this.tableDetail).one[rowIndex]
        //大于0就合并,否则就不合并
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    },

3.实现表格的单选
需求:想把表格当成选择框选中,要限制多选的样式,并及时清空选择的数组

表格设置的参数:

< el-table
            class="tb"
            @select="handleSelectionChange"
          >
    </el-table>
 //记住这里的select不是selection-change,之前因为这个我改了好久的bug
    
//隐藏全选框的样式 css代码
    .tb
      ::v-deep
      .el-table__header
      .el-table-column--selection
      .cell
      .el-checkbox {
      display: none;
    }
   //表格选择方法js
  
  handleSelectionChange(selection, row) {
    //清空所有选中
    this.$refs.multipleTable.clearSelection()
    //选中当前checkbox
    this.$refs.multipleTable.toggleRowSelection(row, true)
    //保存当前选中的对象
    this.templateSelection = row
  },

4.对表格数据进行处理,使用插槽
需求:后端可能传的不是中文,而是id 、code的字段,所以展示的时候需要进行转化展示一下
以最难的图片为例:

//scope.row.属性 去获取表格的属性数据,通过<template slot-scope="scope"></template>放入插槽
 <el-table-column  label="照片" width="400">
          <template slot-scope="scope">
            <el-image
              v-for="(item, index) in scope.row.imgsArr"
              :key="index"
              style="width: 50px; height: 50px; margin-right: 5px"
              :src="item"
              :preview-src-list="scope.row.imgsArr"
            >
            </el-image>
          </template>
        </el-table-column>

二、关于表单填写校验

1.校验输入的数字正则
让输入框只能输入大于0的数字,οnkeyup=“this.value=this.value.replace(/\D|^0/g,’’)”
校验数字要改成v-model.number=’’’

2.手机号码的校验正则

 //检查手机号
    isCellPhone(val) {
      if (
        !/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(
          val
        )
      ) {
        return false
      } else {
        return true
      }
    },

3.自定义校验
有时候空的校验不满足校验,可以自己写校验方法

//以判断值的大小为例
 rules: {
        waterVolume: [
          { required: true, message: '请输入灌溉后水位', trigger: 'change' },
          {
            required: true,
            validator: (rules, value, callback) => {
              if (value < this.farmDetail.sprayWay) {
                return callback(new Error('灌溉后水位不能小于灌溉前水位'))
              }
              //这里callback()一定要有,否则表单校验会不返回通过
              return callback()
            },
            trigger: ['change', 'blur']
          }
        ]
      },

4.校验的触发

 <el-form
      ref="farmDetail"
  ></el-form>
  //在需要触发的地方调用该方法
   this.$refs.farmDetail.validate(valid => {
          if (valid) {
            console.log('验证通过222')
          } else {
            console.log('验证不通过22')
         }
      })

5.表格的校验
属性这样拼 :prop="‘表格名.’ + scope.$index + ‘.属性名’"

//这样就可以对表格里的输入框进行校验了
                   <el-form-item
                        :prop="'tableForm.' + scope.$index + '.content'"
                        :rules="rules.content"
                        :inline-message="true"
                      >
                        <el-input
                          clearable
                          v-model="scope.row.content"
                          placeholder="含量(%)"
                          onkeyup="this.value=this.value.replace(/\D|^0/g,'')"
                          :maxlength="2"
                        ></el-input>
                      </el-form-item>

三、图片的上传与回显

需求:一开始前端交互就是用element ui 里的upload组件,但是项目里的图片文件是要求先文件上传,然后再以获得的id数组传给后端;回显也一样,后端返回id数组给前端,前端通过这个id去下载对应的图片数据,然后用其src进行回显。这里有个附加需求,图片预览和文件预览都要事先,图片预览比较容易,文件预览就需要处理一下。

//是用来隐藏超出文件个数时,最后一个的上传框
 //组件里的属性:
 :class="{ hide: hideUpload }" 
 
  //css:
 .hide .el-upload--picture-card {
     display: none;
 }
//组件里用来响应上传接口的
 :data="updateParam"
 :action="actionURL"
//具体实现代码 html
         <el-upload
              :on-preview="handlePictureCardPreview"
              :data="updateParam"
              :class="{ hide: hideUpload }"
              :action="actionURL"
              list-type="picture-card"
              :limit="limitCountImg"
              :before-upload="dealImgChange"
              :file-list="fileList"
              accept=".png,.jpg,.pdf"
              :on-error="handleError"
              :on-success="handleSuccess"
            >
              <i slot="default" class="el-icon-plus"></i>

              <div
                slot="file"
                slot-scope="{ file }"
                style="width: 80px; height: 80px; border-radius: 5px"
              >
                <img
                  class="el-upload-list__item-thumbnail"
                  :src="filterImg(file)"
                  alt=""
                  fit="contain"
                  style="border-radius: 5px"
                />

               
                  <span class="el-upload-list__item-actions">
                    <span
                      class="el-upload-list__item-preview"
                      @click="handlePictureCardPreview(file)"
                    >
                      <i class="el-icon-zoom-in"></i>
                    </span>
                    <span
                      class="el-upload-list__item-delete"
                      @click="handleRemove(file)"
                    >
                      <i class="el-icon-delete"></i>
                    </span>
                  </span>
              </div>
            </el-upload>
data数据:
 //文件缩略图
      FileImg: require('@/assets/img/pdf.png'),
      hideUpload: false, //用来隐藏最后一个上传框
      limitCountImg: 10, //上传文件的最大数量
      //文件上传列表
      fileList: [],
      //图片的url
      dialogImageUrl: '',
      //图片预览框显示
      dialogVisible: false,
//js代码
   //图片状态改变时触发,在on-change事件中判断图片数量
    dealImgChange(file) {
      //限制图片格式
      this.idtest = file.uid
      let fileName = file.name
      let pos = fileName.lastIndexOf('.')
      let lastName = fileName.substring(pos, fileName.length)
      if (
        lastName.toLowerCase() !== '.jpg' &&
        lastName.toLowerCase() !== '.png' &&
        lastName.toLowerCase() !== '.pdf'
      ) {
        this.$message.error('文件必须jpg、png、pdf 类型')

        return false
      }
      //限制文件大小
      const isLt = file.size / 1024 / 1024 / 10 <= 1
      if (!isLt) {
        this.$message.error('上传文件大小不得大于10MB')

        return false
      }
      return true
    },
    handleSuccess(response, file, fileList) {
      // 上传成功
      if (response.code === '0') {
        this.fileList = fileList
        this.hideUpload = this.fileList.length >= this.limitCountImg
      } else {
        if (response.code === '9') {
          this.$message.error(response.msg)
        }
        // 上传失败重置数组
        this.fileList = [...this.fileList]
      }
    },
    //文件上传失败
    handleError() {
      this.$message.error('上传失败')
    },
    //删除文件
    handleRemove(file) {
      // 删除文件
      if (!file.id && !file.response) {
        return
      }
      const id = file.id || file.response.id
      this.fileList.splice(
        this.fileList.findIndex(item => (item.id || item.response.id) === id),
        1
      )
      this.hideUpload = this.fileList.length >= this.limitCountImg
    },
    //pdf的图片回显展示
    filterImg(item) {
      // 判断文件类型,返回相应显示的图片
      const extStart = item.name.lastIndexOf('.')
      const ext = item.name.substring(extStart, item.name.length).toUpperCase()

      if (ext === '.PDF') {
        return this.FileImg
      } else {
        return item.url
      }
    },
   //文件预览
    handlePictureCardPreview(file) {
      let fileName = file.name
      let pos = fileName.lastIndexOf('.')
      let lastName = fileName.substring(pos, fileName.length)
      if (lastName.toLowerCase() === '.pdf') {
        //如果是pdf打开页面进行预览
        window.open(this.jointDownLoadURL(file), 'top')
      } else {
        //如果是图片就弹窗显示
        this.dialogImageUrl = this.jointDownLoadURL(file)
        this.dialogVisible = true
      }
    },
       jointDownLoadURL(file) {
      // 预览和下载,拼接URL
      const url = file.url
      const base_url = 环境链接
      if (url.indexOf(base_url) >= 0 && file.id) {
        // 若url包含base_url且有file中存在文件id,则说明该文件是网络获取的,否则为本地获取上传的
        return url + 拼接url
      }
      return url
    }

四、其他知识点

1.深拷贝的使用
深拷贝的好处:对象拷贝过来就不会相互影响了,用于区别修改前和修改后的判断
JSON.parse(JSON.stringify(深拷贝的对象))
2.excel导出
接口要加上

responseType: 'blob'
      //获得了后端返回的数据res后
        var blob = res
        var url = window.URL.createObjectURL(blob)
        var aLink = document.createElement('a')
        aLink.style.display = 'none'
        aLink.href = url
        aLink.setAttribute('download', name + '.xlsx')
        document.body.appendChild(aLink)
        aLink.click()

3.watch监听数据变化实现回显功能
通过监听有变化的数据来进行回显

watch:{
     监控的对象或者数据名: {
      handler(val) {
        //这里写回显的方法
      },
      deep: true //深度监听
    },
}

4.content-type的两种类型前端对其的处理
需求:后端想要前端传json数据给他,之前的request的form表单就不能用了,所以就对request.js方法进行修改

// 请求参数
    if (config.method === 'post') {
      if (
        config.data &&
        config.headers['Content-Type'] === 'application/json'
      ) {
      //转为json格式
        config.data = JSON.stringify(config.data)
      }
    } else {
    //拼接
      if (config.data) {
        config.url = config.url + '?' + qs.stringify(config.data)
      }
    }

加班确实能学到很多,但是容易过劳肥,喜欢吃辣、甜、油的东西解压,我感觉一个月我胖了2斤多了。还是要多总结,希望新的一年我能继续坚持,技术稳步上升。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值