美文网首页
jsonForest

jsonForest

作者: majunchang | 来源:发表于2019-04-23 17:59 被阅读0次

    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

    相关文章

      网友评论

          本文标题:jsonForest

          本文链接:https://www.haomeiwen.com/subject/lajbgqtx.html