element-ui 的 Switch 组件封装异步实现

需求场景

近期需求中,要作一个列表。列表中每项数据会有一个快捷启用禁用入口。
clipboard.pngelement-ui

目前,项目使用的是 element-ui,里边有 Switch 组件,画界面是很是容易的。缓存

问题

大概的逻辑是:用户点击这个 Switch 组件后,会发送一个请求。请求得到正确结果后,再切换 Switch 组件的状态。
其中一种场景:用户会快速连续点击这个 Switch 组件,这样请求就会连续被发送。
还一种场景:请求结果是异常的,状态不该该被改变。post

思考和方案

第一个问题处理方式能够是:发送一个请求的时候,吧这个请求缓存起来,若是请求发送成功,再把这个缓存值清空。每次发请求以前都检查这个缓存值是否为空。若是缓存值存在,就取消上一次的请求。
还一种方法:添加一个disable的状态,发送请求前把 Switch 组件变成 disable 状态,请求发送有结果后,再把组件变成正常状态。
第二个问题:element-ui 中其实要变动当前 Switch 按钮状态就是改变绑定值就能够了。可是咱们再一个数据条数不肯定的列表中,并不合适去手动设定一个可控的绑定值。因此须要有一个做用域来控制变动单个 Switch 组件的状态。因此想到了再次封装 Switch 组件。ui

实现与编码

首先,确认咱们组件要传入:this

  • val: 当前状态
  • reqUrl: 改变状态 接口url
  • id: 标识这个状态的id 要传数据的 值
  • idName: 改变状态要传的数据字段名

其次,咱们再组建中建立一个变量,来绑定改组件的值。在建立这个组件的时候,把传进来的状态赋值给组件内的变量值。这样就实现了局部控制。同时,用了一个 isDisabled 变量来控制组件的可用状态。
固然,用了禁用方案,就不会怕用户连续发送变动组件状态了,因此检测请求重复就取消上一个请求的操做是多余的。不过这里既然讲了,就再组件中写了实现的方法。
封装后的组件源码以下:编码

<template>
  <div>
    <el-switch
            :value="value"
            @change="changeStatus"
            active-color="#13ce66" :disabled="isDisabled"
            inactive-color="#ff4949">
    </el-switch>
  </div>
</template>

<script>
  /**
   * val: 当前状态
   * reqUrl: 改变状态 接口url
   * id: 标识这个状态的id 要传数据的 值
   * idName: 改变状态要传的数据字段名
   * */
  export default {
    name:'switchItem',
    props:[
      'val',
      'reqUrl',
      'id',
      'idName',
    ],
    data() {
      return {
        value:false,
        setStatusHttp: null,
        isDisabled: false,
      }
    },
    created() {
      let self = this;
      self.value = self.val
    },
    methods:{
      changeStatus(){
        let self = this;
        self.isDisabled=true
        self.setStatus()
      },
      // setStatus
      setStatus(){
        let self = this;
        if (!self.setStatusHttp) {    // 判断是否已经有请求正在发送
          self.setStatusHttpReq();
        } else {
          // abort 正在发送的请求 而后再次发送请求
          self.setStatusHttp()
          self.setStatusHttpReq();
        }
      },
      setStatusHttpReq(){
        let self = this;
        let CancelToken = self.$http.CancelToken
        let postData = {}
        postData[self.idName] = self.id
        self.$http.post(self.reqUrl,postData,{
          cancelToken: new CancelToken(function executor(c) {
            // An executor function receives a cancel function as a parameter
            self.setStatusHttp = c;
          })
        }).then(res => {
          if(res.data.error_code == '00000'){
            self.$message({
              type: 'success',
              message: '操做成功!'
            });
            self.value = !self.value
          }else{
            self.$message({
              type: 'error',
              message: res.data.message
            });
          }
          self.isDisabled=false
        })
      },
    }
  }
</script>

总结

当一个列表中,某个组件须要一个局部做用域来操做或者控制一些状态的的时候,能够对该组件再次进行封装,这样就会有一个组件的做用域,再这个做用域里边,咱们就能够作一些骚操做来实现特殊场景的需求了。url

相关文章
相关标签/搜索