| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- const PATH = require('path');
- const fs = require('fs');
- let defaultConfig = {
- path: PATH.resolve('./', 'db')
- }
- /**
- *
- * @param {String} dbName 文件名
- * @param {Object} obj 初始数据,若文件存在将会替换内容
- * @param {Object} config 配置文件
- * @returns {Proxy} 对象
- */
- function create(dbName = Date.now() + '', obj, config) {
- config = { ...defaultConfig, ...config };
- if (typeof dbName !== 'string') throw TypeError('dbName must be string');
- if (!PATH.isAbsolute(config.path)) throw TypeError('config.path must be a absulute path');
- let totalPath = PATH.resolve(config.path, dbName + '.json');
- // 目录是否存在,不存在创建一个
- if (!fs.existsSync(config.path)) {
- fs.mkdirSync(config.path);
- };
- // 文件是否存在,不存在创建一个
- if (!fs.existsSync(totalPath)) {
- fs.closeSync(fs.openSync(totalPath, 'w'));
- if (!obj) { obj = {} };
- fs.writeFileSync(totalPath, JSON.stringify(obj));
- } else {
- if (obj) {
- fs.writeFileSync(totalPath, JSON.stringify(obj));
- } else {
- obj = JSON.parse(fs.readFileSync(totalPath));
- }
- }
- const objectList = new WeakMap()//key: target, value: proxy
- // proxyList 避免proxy对象再次被proxy
- const proxyList = new WeakMap()//key: proxy, value: target
- function reactive(target) {
- let proxy = objectList.get(target);
- //如果存在,即返回
- if (proxy !== void 0) {
- return proxy
- }
- // 如果target是proxy
- if (proxyList.has(target)) {
- return target
- }
- // 如果是基本类型,直接返回
- if (!isObject(target)) {
- return target
- }
- proxy = new Proxy(target, handle)
- objectList.set(target, proxy)
- proxyList.set(proxy, target)
- return proxy;
- }
- const handle = { get, set, deleteProperty };
- function get(target, propKey, receiver) {
- // console.log('get')
- let proxy = Reflect.get(target, propKey, receiver);
- track(target, 'get', propKey)
- return isObject(proxy) ? reactive(proxy) : proxy;
- //实现多层代理,若为对象,需要递归
- }
- function set(target, propKey, value, receiver) {
- const oldvalue = target[propKey];
- let proxy = Reflect.set(target, propKey, value, receiver)
- // 当是新增的属性 或者 数据变化时 ,trigger
- if (!target.hasOwnProperty(propKey)) {
- trigger(target, 'add', propKey)
- } else if (oldvalue !== value) {
- trigger(target, 'set', propKey)
- }
- fs.writeFileSync(totalPath, JSON.stringify(obj));
- return proxy
- }
- function deleteProperty(target, propKey) {
- // console.log('删除')
- let proxy = Reflect.deleteProperty(target, propKey)
- trigger(target, 'delete', propKey)
- fs.writeFileSync(totalPath, JSON.stringify(obj));
- return proxy
- }
- //方法
- function isObject(val) {
- return typeof val === 'object' && val !== null;
- }
- //effect.js
- //收集依赖
- let targetMap = new WeakMap()//所有依赖 key:obj
- //get 时 收集依赖
- function track(target, type, key) {
- // console.log('track-收集依赖', type, target, key)
- if (effectFn) {
- let depsMap = targetMap.get(target);
- //targetMap无target对象,则新建
- if (depsMap === void 0) {
- // console.log('无depsMap')
- targetMap.set(target, (depsMap = new Map()))
- }
- //depsMap无有key这个属性,则新建
- let dep = depsMap.get(key)
- if (dep === void 0) {
- // console.log('无key')
- depsMap.set(key, (dep = new Set()))
- }
- // 放入依赖 effect就是依赖
- if (!dep.has(effectFn)) {
- // console.log('无effect,并放入effect')
- dep.add(effectFn)
- }
- }
- }
- //set 时更新
- function trigger(target, type, key) {
- // console.log('trigger-触发依赖', type, key)
- let depsMap = targetMap.get(target)
- if (depsMap) {
- let deps = depsMap.get(key)
- if (deps) {
- //将当前key对应的effect一次执行
- deps.forEach(effect => {
- effect()
- })
- // 删除
- if (type == 'delete') {
- // console.log('delete')
- depsMap.delete(key)
- }
- }
- }
- }
- //临时存放 effect中的fn参数
- let effectFn = null;
- function effect(fn) {
- try {
- // console.log('try')
- effectFn = fn;
- fn();
- } finally {
- // console.log('finally')
- effectFn = null;
- }
- }
- return reactive(obj);
- }
- module.exports = {
- create
- };
|