index.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. const PATH = require('path');
  2. const fs = require('fs');
  3. let defaultConfig = {
  4. path: PATH.resolve('./', 'db')
  5. }
  6. /**
  7. *
  8. * @param {String} dbName 文件名
  9. * @param {Object} obj 初始数据,若文件存在将会替换内容
  10. * @param {Object} config 配置文件
  11. * @returns {Proxy} 对象
  12. */
  13. function create(dbName = Date.now() + '', obj, config) {
  14. config = { ...defaultConfig, ...config };
  15. if (typeof dbName !== 'string') throw TypeError('dbName must be string');
  16. if (!PATH.isAbsolute(config.path)) throw TypeError('config.path must be a absulute path');
  17. let totalPath = PATH.resolve(config.path, dbName + '.json');
  18. // 目录是否存在,不存在创建一个
  19. if (!fs.existsSync(config.path)) {
  20. fs.mkdirSync(config.path);
  21. };
  22. // 文件是否存在,不存在创建一个
  23. if (!fs.existsSync(totalPath)) {
  24. fs.closeSync(fs.openSync(totalPath, 'w'));
  25. if (!obj) { obj = {} };
  26. fs.writeFileSync(totalPath, JSON.stringify(obj));
  27. } else {
  28. if (obj) {
  29. fs.writeFileSync(totalPath, JSON.stringify(obj));
  30. } else {
  31. obj = JSON.parse(fs.readFileSync(totalPath));
  32. }
  33. }
  34. const objectList = new WeakMap()//key: target, value: proxy
  35. // proxyList 避免proxy对象再次被proxy
  36. const proxyList = new WeakMap()//key: proxy, value: target
  37. function reactive(target) {
  38. let proxy = objectList.get(target);
  39. //如果存在,即返回
  40. if (proxy !== void 0) {
  41. return proxy
  42. }
  43. // 如果target是proxy
  44. if (proxyList.has(target)) {
  45. return target
  46. }
  47. // 如果是基本类型,直接返回
  48. if (!isObject(target)) {
  49. return target
  50. }
  51. proxy = new Proxy(target, handle)
  52. objectList.set(target, proxy)
  53. proxyList.set(proxy, target)
  54. return proxy;
  55. }
  56. const handle = { get, set, deleteProperty };
  57. function get(target, propKey, receiver) {
  58. // console.log('get')
  59. let proxy = Reflect.get(target, propKey, receiver);
  60. track(target, 'get', propKey)
  61. return isObject(proxy) ? reactive(proxy) : proxy;
  62. //实现多层代理,若为对象,需要递归
  63. }
  64. function set(target, propKey, value, receiver) {
  65. const oldvalue = target[propKey];
  66. let proxy = Reflect.set(target, propKey, value, receiver)
  67. // 当是新增的属性 或者 数据变化时 ,trigger
  68. if (!target.hasOwnProperty(propKey)) {
  69. trigger(target, 'add', propKey)
  70. } else if (oldvalue !== value) {
  71. trigger(target, 'set', propKey)
  72. }
  73. fs.writeFileSync(totalPath, JSON.stringify(obj));
  74. return proxy
  75. }
  76. function deleteProperty(target, propKey) {
  77. // console.log('删除')
  78. let proxy = Reflect.deleteProperty(target, propKey)
  79. trigger(target, 'delete', propKey)
  80. fs.writeFileSync(totalPath, JSON.stringify(obj));
  81. return proxy
  82. }
  83. //方法
  84. function isObject(val) {
  85. return typeof val === 'object' && val !== null;
  86. }
  87. //effect.js
  88. //收集依赖
  89. let targetMap = new WeakMap()//所有依赖 key:obj
  90. //get 时 收集依赖
  91. function track(target, type, key) {
  92. // console.log('track-收集依赖', type, target, key)
  93. if (effectFn) {
  94. let depsMap = targetMap.get(target);
  95. //targetMap无target对象,则新建
  96. if (depsMap === void 0) {
  97. // console.log('无depsMap')
  98. targetMap.set(target, (depsMap = new Map()))
  99. }
  100. //depsMap无有key这个属性,则新建
  101. let dep = depsMap.get(key)
  102. if (dep === void 0) {
  103. // console.log('无key')
  104. depsMap.set(key, (dep = new Set()))
  105. }
  106. // 放入依赖 effect就是依赖
  107. if (!dep.has(effectFn)) {
  108. // console.log('无effect,并放入effect')
  109. dep.add(effectFn)
  110. }
  111. }
  112. }
  113. //set 时更新
  114. function trigger(target, type, key) {
  115. // console.log('trigger-触发依赖', type, key)
  116. let depsMap = targetMap.get(target)
  117. if (depsMap) {
  118. let deps = depsMap.get(key)
  119. if (deps) {
  120. //将当前key对应的effect一次执行
  121. deps.forEach(effect => {
  122. effect()
  123. })
  124. // 删除
  125. if (type == 'delete') {
  126. // console.log('delete')
  127. depsMap.delete(key)
  128. }
  129. }
  130. }
  131. }
  132. //临时存放 effect中的fn参数
  133. let effectFn = null;
  134. function effect(fn) {
  135. try {
  136. // console.log('try')
  137. effectFn = fn;
  138. fn();
  139. } finally {
  140. // console.log('finally')
  141. effectFn = null;
  142. }
  143. }
  144. return reactive(obj);
  145. }
  146. module.exports = {
  147. create
  148. };