极客时间返利平台,你可以在上边通过山月的链接购买课程,并添加我的微信 (shanyue94) 领取返现。

# 如何实现一个 ORM 类似的 find 链式调用

更多描述

如下代码所示,使用 find 函数实现链式调用

const data = [
  {userId: 8, title: 'title1'},
  {userId: 11, title: 'other'},
  {userId: 15, title: null},
  {userId: 19, title: 'title2'}
];

// 查找data中,符合where中条件的数据,并根据orderBy中的条件进行排序
const result = find(data).where({
  "title": /\d$/   // 这里意思是过滤出数组中,满足title字段中符合 /\d$/的项
}).orderBy('userId', 'desc');  // 这里的意思是对数组中的项按照userId进行倒序排列

//=> 返回 [{ userId: 19, title: 'title2'}, { userId: 8, title: 'title1' }];
console.log(result.value);

Issue

欢迎在 Gtihub Issue 中回答此问题: Issue 712 (opens new window)

代码见 codepen,如何实现链式调用 (opens new window)

function find (data) {
  return {
    data,
    where (match) {
      this.data = this.data.filter((item) => {
        return Object.entries(match).every(([key, value]) => {
          if (value instanceof RegExp) {
            return value.test(item[key])
          }
          return item[key] === value
        })
      })
      return this
    },

    orderBy (key, type) {
      this.data.sort((x, y) => type !== 'desc' ? x[key] - y[key] : y[key] - x[key])
      return this
    }
  }
}
function find(data) {
  class FindManager {
    constructor(data) {
      this.data = data;
    }
    where(query) {
      const data = [...this.data];
      return new FindManager(
        data.filter((item) => {
          return Object.entries(query).every(([key, filter]) => {
            if (
              Object.prototype.toString.call(filter).slice(8, -1) === "Regex"
            ) {
              return filter.test(item[key]);
            } else {
              return filter === item[key];
            }
          });
        })
      );
    }
    orderBy(key, order) {
      const data = [...this.data];
      data.sort((a, b) => {
        return order === "asc" ? a[key] - b[key] : b[key] - a[key];
      });
      return new FindManager(data);
    }
    get value() {
      return this.data;
    }
  }
  return new FindManager(data);
}
function find(data) {
  const temp = Array.isArray(data) ? [...data] : { ...data };
  let opt = {
    where: function where(opt) {
      return find(
        Object.entries(opt).reduce((prev, [key, match]) => {
          return prev.filter((curr) => {
            return match.test(curr[key]);
          });
        }, this)
      );
    },
    orderBy: function order(key, type) {
      return this.sort((prev, next) => {
        switch (type) {
          case "desc":
            return next - prev;
          case "asc":
            return prev - next;
          default:
            return prev - next;
        }
      });
    },
  };
  Object.setPrototypeOf(opt, Array.prototype);
  Object.setPrototypeOf(temp, opt);
  return temp;
}
// 综合一下两位大佬的写法
class Find {
  constructor(data) {
    this.data = [...data];
  }

  where(query) {
    this.data = this.data.filter((item) => {
      return Object.entries(query).every(([key, value]) => {
        if (value instanceof RegExp) {
          return value.test(item[key]);
        } else {
          return item[key] === value;
        }
      });
    });

    return this;
  }

  orderBy(key, type) {
    this.data = this.data.sort((a, b) =>
      type !== "desc" ? a[key] - b[key] : b[key] - a[key]
    );

    return this;
  }

  get value() {
    return this.data;
  }
}

function find(data) {
  return new Find(data);
}
Last Updated: 11/27/2021, 6:11:48 PM