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']
  }
  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
    }
  }
  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]: data[item]
          })
        }
      })
    } 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) {
    let result = {}
    if (Object.prototype.toString.call(data) === '[object Array]') {
      result = data.map(item => {
        return this.replaceRepeatKeymap(item, keymap)
      })
    } 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]: data[dataKey]
          })
        }
      }
    } else {
      return data
    }
    return result
  }
  replaceKeymap (data, keymap) {
    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)
    } else {
      for (let key in keymap) {
        let chiledStr = keymap[key]
        str = str.replace(new RegExp(chiledStr, 'g'), key)
      }
      return JSON.parse(str)
    }
  }
  emit (type, option) {
    let arr = this.eventList[type]
    if (!arr) {
      /**
       *  没有 on 的时候 emit的兼容
       */
      arr = []
    }
    /**
     * 挂载参数  进行整体校验
     */
    this.init(option)
    // option 不传 或者 data 不传  则可认为在执行订阅和发布任务  不做 dom 转化
    if (!this.option || !this.data) {
      arr.forEach((item, index) => {
        item()
      })
    } else {
      /**
       * 1. 检验 returnKeys  如果不对  给出报错
       * 2. 检验 keymaps  如果映射的类名不对    给出报错
       *
       */
      // 校验 data 存在的情况下 returnKeys为数组  keymap为对象的合法性
      this.validateLegal(this.returnKeys, this.keymap)
      if (this.returnKeys) {
        this.data = this.getDataFormReturnKeys(this.data, this.returnKeys)
      }
      if (this.keymap) {
        this.data = this.replaceKeymap(this.data, this.keymap)
      }
      arr.forEach((item) => {
        item(this.data, this.option)
      })
    }
  }
  on (type, callback) {
    if (!this.eventList[type]) {
      this.eventList[type] = []
    }
    this.eventList[type].push(callback)
  }
}

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券