jsonForest

JsonTransfer

以昆仑三级联动类目为例 对于后端返回的数据 我们可能需要对这些字段进行特殊的配置(如改名)等才能拿到我们可以直接使用的数据。除此之外,消息订阅比较混乱。

我们期望的消息订阅模式如下:
//  监听 listen 事件
this.jsonTransfer.on("listen", value => {
    // 处理 value 值  value 为后端字符串经过特殊处理之后返回给我们需要的字符串
      this.resOptions = value;
    });


// 获取后端数据  并触发监听事件
 axios.get(`${dataObj[value]}`).then(res => {
        //  拿到后端数据之后 触发 listen 事件
        this.jsonTransfer.emit("listen", {
          returnKeys: ["cat_id", "cat_name", "depth", "rank"],
          keymap: {
            label: "cat_name",
            value: "cat_name",
            depth: "depth"
          },
          data: res.data.data[0]
        });
      });
我们将枯燥而繁琐的数据格式转换 类名转换 提供了一个公共的方法取处理

react 和 vue 中使用的时候 挂载在全局对象上即可

class JsonForest {
  constructor () {
    this.eventList = []
    this.data = ''
    this.keymap = {
      name: 'cat_name',
      id: 'cat_id',
      depth: 'depth'
    }
    this.returnKeys = ['cat_id', 'cat_name', 'depth', 'rank']
    this.JsonTransfer = new JsonTransfer()
  }
  init (option) {
    this.option = this.checkParam(option) ? option : ''
    this.data = this.checkParam(option.data)
      ? JSON.parse(JSON.stringify(option.data))
      : ''
    this.keymap = this.checkParam(option.keymap) ? option.keymap : ''
    this.returnKeys = this.checkParam(option.returnKeys)
      ? option.returnKeys
      : ''
  }
  checkParam (param) {
    // 如果为空字符串、 空对象、空数组 以及 undefined null 等值的时候 返回 false 否则返回 true
    if (Object.prototype.toString.call(param) === '[object Array]') {
      return !!param.length
    } else if (Object.prototype.toString.call(param) === '[object Object]') {
      return !!Object.keys(param).length
    } else {
      return !!param
    }
  }
  validateLegal (returnKeys, keymap) {
    if (Object.prototype.toString.call(returnKeys) !== '[object Array]') {
      throw new Error('returnKeys字段,必须为数组')
    } else if (Object.prototype.toString.call(keymap) !== '[object Object]') {
      throw new Error('keymap字段,必须为对象')
    } else {
      return true
    }
  }
  emit (type, option) {
    let arr = this.eventList[type]
    if (!arr) {
      /**
       *  没有 on 的时候 emit的兼容
       */
      arr = []
    }
    // 校验 data 存在的情况下 returnKeys为数组  keymap为对象的合法性
    this.validateLegal(this.returnKeys, this.keymap)
    /**
     * 挂载参数  进行整体校验 不符合规范的 转化为空字符串
     */
    this.init(option)
    // option 不传 或者 data 不传  则可认为在执行订阅和发布任务  不做 dom 转化
    if (!this.option || !this.data) {
      arr.forEach((item, index) => {
        item()
      })
    } else {
      /**
       * 1. 检验 returnKeys  如果不对  给出报错
       * 2. 检验 keymaps  如果映射的类名不对  给出报错
       *
       */
      if (this.returnKeys) {
        this.data = this.JsonTransfer.getDataFormReturnKeys(this.data, this.returnKeys)
      }
      if (this.keymap) {
        this.data = this.JsonTransfer.replaceKeymap(this.data, this.keymap, this.returnKeys)
      }
      arr.forEach(item => {
        item(this.data, this.option)
      })
    }
  }
  on (type, callback) {
    if (!this.eventList[type]) {
      this.eventList[type] = []
    }
    this.eventList[type].push(callback)
  }
}

class JsonTransfer {
  getDataFormReturnKeys (data, returnKeys) {
    let result = {}
    if (Object.prototype.toString.call(data) === '[object Array]') {
      result = data.map(item => {
        return this.getDataFormReturnKeys(item, returnKeys)
      })
    } else if (Object.prototype.toString.call(data) === '[object Object]') {
      let prevKeys = Object.keys(data)
      returnKeys.forEach(item => {
        //  原先数据中存在的key 值   才会生效
        if (prevKeys.includes(item)) {
          result = Object.assign(result, {
            [item]: this.getDataFormReturnKeys(data[item], returnKeys)
          })
        }
      })
    } else {
      return data
    }
    return result
  }
  checkKeymapRepeat (keymap) {
    let arr = Object.values(keymap)
    let hash = {}
    for (let i = 0; i < arr.length; i++) {
      if (hash[arr[i]]) {
        return true
      }
      hash[arr[i]] = true
    }
    return false
  }
  replaceRepeatKeymap (data, keymap, returnKeys) {
    let result = {}
    if (Object.prototype.toString.call(data) === '[object Array]') {
      result = data.map(item => {
        return this.replaceRepeatKeymap(item, keymap, returnKeys)
      })
    } else if (Object.prototype.toString.call(data) === '[object Object]') {
      for (let key in keymap) {
        let dataKey = keymap[key]
        if (data.hasOwnProperty(dataKey)) {
          result = Object.assign(result, {
            [key]: this.replaceRepeatKeymap(data[dataKey], keymap, returnKeys)
          })
        }
      }
      // 补充returnKeys 遗留的 key 值
      let filterArr = returnKeys.filter((item) => {
        return !Object.values(keymap).includes(item)
      })
      if (filterArr.length) {
        filterArr.forEach((key) => {
          if (data.hasOwnProperty(key)) {
            result = Object.assign(result, {
              [key]: this.replaceRepeatKeymap(data[key], keymap, returnKeys)
            })
          }
        })
      }
    } else {
      return data
    }
    return result
  }
  replaceKeymap (data, keymap, returnKeys) {
    let str = JSON.stringify(data)
    /**
     * 1.   keymap 中存在相同的 value 值  (特殊情况)
     *  keymap: {
            label: "cat_name",
            value: "cat_name",
            depth: "depth"
          },
     * 2.   keymap 中的 value 值都不相同(正常情况)
     */
    if (this.checkKeymapRepeat(keymap)) {
      return this.replaceRepeatKeymap(data, keymap, returnKeys)
    } else {
      for (let key in keymap) {
        let chiledStr = keymap[key]
        str = str.replace(new RegExp(chiledStr, 'g'), key)
      }
      return JSON.parse(str)
    }
  }
}
export default JsonForest


使用说明
api 使用方法 说明
data 赋值数据 数据源 如果不传 将不对数据做任何处理
returnKeys ['cat_id', 'cat_name', 'depth', 'rank'] 需要返回的字段,以数组的形式包围
keymap {label: 'cat_name',
value: 'cat_name',}
映射改变的字段 ,以对象的形式包裹,支持1对1、1对多
使用
mounted () {
    this.jsonTransfer.on('listen', value => {
      console.log('111')
      console.log(value)
      this.resOptions = value
    })
  },
methods: {
    chooseValue (value) {
      console.log(value)
      axios.get(`${dataObj[value]}`).then(res => {
        console.log(this.jsonTransfer)
        this.jsonTransfer.emit('listen', {
          returnKeys: ['cat_id', 'cat_name', 'depth', 'rank'],
          keymap: {
            label: 'cat_name',
            value: 'cat_name',
            depth: 'depth'
          },
          data: res.data.data
        })
        console.log(res)
      })
    }
  }
测试案例

配置异步请求数据源 我使用本地 mock、改变一级类目 随即可以看到二级类目数据发生改变

image.png
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Online payment to buy things is always a big headache. 网购...
    新活力英语教育阅读 302评论 0 0
  • “懦夫,你就是个懦夫……” 没等刘强说完,我就摁下了眼镜上的挂机按钮,他粗粝的声音嘎然而止,感觉就像把一块肥皂突然...
    不完美世界阅读 393评论 0 2
  • 昨天总体来说,心情还可以,因为有些事好像得到了答案,而答案也没有想象中那么糟,当我们放开,事情的发展其实也没想象中...
    颜丽娜阅读 175评论 1 1
  • “江南忆,最忆是杭州。山寺月中寻桂子,郡亭枕上看潮头。何日更重游?”——白居易 提到江南,总绕不开...
    周颖_3286阅读 589评论 3 6

友情链接更多精彩内容