-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmini-vue.js.map
More file actions
1 lines (1 loc) · 70.8 KB
/
Copy pathmini-vue.js.map
File metadata and controls
1 lines (1 loc) · 70.8 KB
1
{"version":3,"file":"mini-vue.js","mappings":";;;;;;;;;;;;;;;;AAAA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;ACrB4C;AACE;AACR;AACtC;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,GAAG;AACd;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,6CAAc;AACvB;AACA,SAAS,gDAAiB;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,sDAAuB;AAChC;AACA,SAAS,6CAAc;AACvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,gCAAgC,IAAI;AAC1D;AACA;AACA;AACA;AACA,0BAA0B,iBAAiB;AAC3C;AACA;AACA;AACA,6BAA6B,qBAAqB;AAClD,0BAA0B,yBAAyB;AACnD;AACA;AACA;AACA,UAAU,aAAa;AACvB;AACA;AACA;AACA,6CAA6C,cAAc;AAC3D;AACA;AACA;AACA;AACA;AACA;AACA,wEAAwE;AACxE;AACA;AACA;AACA;AACA,UAAU,eAAe;AACzB,UAAU,aAAa,KAAK,kCAAkC;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0CAA0C;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,kCAAkC;AACrD,uCAAuC;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0BAA0B,gDAAiB;AAC3C;AACA;AACA;AACA,uBAAuB,mCAAmC;AAC1D;AACA;AACA;AACA,sDAAsD;AACtD,uBAAuB,mCAAmC;AAC1D;AACA,eAAe;AACf;AACA;AACA,cAAc,WAAW,IAAI,OAAO,IAAI,QAAQ;AAChD;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8B,mBAAmB,GAAG;AACpD,sCAAsC;AACtC,QAAQ,eAAe;AACvB,qBAAqB,cAAc,GAAG;AACtC;AACA,gBAAgB,mDAAoB;AACpC;AACA,4BAA4B,IAAI,IAAI;AACpC;AACA;AACA;AACA;AACA;AACA,gBAAgB,IAAI;AACpB;AACA;AACA;AACA,gBAAgB,IAAI,IAAI,MAAM;AAC9B;AACA,cAAc,IAAI,IAAI,MAAM,IAAI,SAAS,IAAI;AAC7C;AACA;AACA;AACA,UAAU,oBAAoB;AAC9B;AACA;AACA;AACA;AACA;AACA,cAAc,kDAAmB;AACjC;AACA;AACA;AACA,gBAAgB,0DAA2B;AAC3C;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA,cAAc,kDAAmB;AACjC;AACA;AACA,gBAAgB,0DAA2B;AAC3C,kCAAkC,oBAAoB;AACtD;AACA,SAAS;AACT;AACA,gBAAgB,0DAA2B;AAC3C;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,8BAA8B,UAAU,IAAI,uBAAuB;AACnE;AACA;AACA;AACA;AACA,oBAAoB,gBAAgB,IAAI,oBAAoB;AAC5D;AACA,6BAA6B,kDAAU;AACvC;AACA,YAAY,GAAG;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8B,EAAE,KAAK;AACrC;AACA;AACA,oBAAoB,MAAM,IAAI,IAAI;AAClC;AACA,+BAA+B,oBAAoB;AACnD;AACA,oBAAoB,6BAA6B,IAAI,oBAAoB;AACzE,uBAAuB;AACvB;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,UAAU,WAAW;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA6B,EAAE,oBAAoB;AACnD;AACA;AACA;AACA;AACA,WAAW,GAAG;AACd,WAAW,GAAG;AACd,WAAW,SAAS;AACpB;AACA;AACA,gEAAgE;AAChE;AACA;AACA,+BAA+B;AAC/B;AACA;AACA;;;;;;;;;;;;;;;;;AC/PqC;AACL;AAChC;AACO;AACP,cAAc,6CAAK,YAAY;AAC/B,eAAe,kDAAQ,OAAO;AAC9B;AACA;;;;;;;;;;;;;;;;;;;;;;;;ACP4D;AACxB;AACC;AACL;;;;;;;;;;;;;;;;;ACH4B;AACA;AAC5D;AACO;AACP;AACA;AACA;AACA;AACA;AACA,SAAS,gDAAU;AACnB;AACA;AACA;AACA;AACA;AACA,sBAAsB,MAAM;AAC5B,eAAe;AACf,iBAAiB;AACjB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAkB,kBAAkB;AACpC;AACA,sBAAsB,gDAAc;AACpC;AACA;AACA;AACA;AACA;AACA,mEAAmE;AACnE,QAAQ;AACR;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB,mDAAiB;AAC1C,0BAA0B,mDAAiB;AAC3C;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC;AACnC;AACA,6CAA6C;AAC7C,iDAAiD;AACjD,oCAAoC;AACpC,6BAA6B,wBAAwB,QAAQ,IAAI;AACjE;AACA;AACA,UAAU,yDAAuB;AACjC;AACA,YAAY,6DAA2B;AACvC;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,oCAAoC,MAAM;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAqC;AACrC;AACA;AACA;AACA;AACA;AACA,6CAA6C;AAC7C,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA,wBAAwB;AACxB,uCAAuC;AACvC,0BAA0B;AAC1B;AACA;AACA,UAAU,oBAAoB;AAC9B;AACA;AACA;AACA;AACA,6CAA6C;AAC7C,0BAA0B;AAC1B;AACA;AACA,MAAM,wDAAsB;AAC5B,MAAM,sDAAoB;AAC1B;AACA;AACA,UAAU,mDAAiB;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,qDAAmB;AACzC;AACA,MAAM;AACN;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B;AAC3B,4BAA4B;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA,MAAM;AACN,iDAAiD;AACjD;AACA;AACA;AACA,YAAY,qDAAmB;AAC/B;AACA;AACA;AACA,cAAc,6DAA2B;AACzC;AACA;AACA,OAAO;AACP;AACA;AACA,cAAc,6DAA2B;AACzC,iBAAiB,gDAAQ;AACzB;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA,UAAU,qDAAmB;AAC7B;AACA;AACA,YAAY,gDAAc;AAC1B;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB;AACA;AACA,yBAAyB;AACzB,0BAA0B;AAC1B,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA,UAAU,gDAAc;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yCAAyC;AACzC;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;ACtSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACsC;AACY;AAClD;AACA;AACA;AACA;AACA,6BAA6B;AAC7B,wBAAwB;AACxB,kBAAkB,+CAAM;AACxB;AACA;AACA;AACA;AACA;AACA,8BAA8B;AAC9B,UAAU,gDAAO;AACjB;AACA;AACA,aAAa;AACb;AACA,OAAO;AACP,KAAK,GAAG;AACR;AACA;AACA;AACA;AACA;AACA,2BAA2B;AAC3B;AACA,uBAAuB;AACvB,MAAM,8CAAK,iBAAiB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA,gBAAgB,kDAAU;AAC1B,QAAQ;AACR,QAAQ;AACR;AACA;AACA;;;;;;;;;;;;;;;;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B;AAC/B,YAAY;AACZ,eAAe;AACf;AACA;AACA;AACO,gCAAgC;AACvC;AACA;AACA;AACA;AACA,kBAAkB;AAClB;AACA;AACA,MAAM;AACN;AACA;AACA,MAAM;AACN;AACA,mBAAmB;AACnB;AACA,4BAA4B;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAkD;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;;;;;;;;;;;;;;;;;;;;;ACzFsC;AACV;AACU;AACJ;;;;;;;;;;;;;;;;;;ACHuB;AACf;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA,OAAO,gDAAQ;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,8CAAK;AACX;AACA;AACA,aAAa,gDAAQ;AACrB,KAAK;AACL;AACA;AACA,WAAW,kDAAU;AACrB,qBAAqB;AACrB;AACA;AACA;AACA,UAAU,+CAAO,gCAAgC,kDAAU;AAC3D,QAAQ,gDAAO,oBAAoB;AACnC;AACA;AACA,MAAM,gDAAO,eAAe;AAC5B;AACA,KAAK;AACL,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;;;;;;;;;;;;;;;;;;;;ACnEgD;AACN;AACJ;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kCAAkC;AAClC;AACA;AACA;AACA;AACA,IAAI,8CAAK;AACT;AACA;AACA,qBAAqB;AACrB;AACA,SAAS,kDAAU;AACnB;AACA;AACA;AACA,IAAI,iDAAO;AACX;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACO;AACP,SAAS,gDAAQ,UAAU,mDAAQ;AACnC;;;;;;;;;;;;;;;;;;;;;;AC7C4C;AACJ;AACC;AACzC;AACsC;AACW;AACjD;AACA;AACA,4BAA4B,SAAS,YAAY;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA4B;AAC5B,2BAA2B;AAC3B;AACA;AACA;AACA;AACA,UAAU,qCAAqC,SAAS;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA,mBAAmB,qDAAQ,kBAAkB;AAC7C;AACA;AACO;AACP,UAAU,kBAAkB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,WAAW;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,kDAAO;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,iBAAiB;AACjB,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,mDAAM;AACzB;AACA;AACA;AACA,0CAA0C,sDAAc;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,gDAAK;AACX;AACA,KAAK;AACL;AACA,iBAAiB,iDAAS;AAC1B;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACO;AACP,EAAE,kDAAO;AACT;;;;;;;;;;;;;;;;;;;ACtJ0D;AACtB;AACR;AAC5B;AACA;AACO;AACP;AACA;AACA;AACA,UAAU,gDAAQ;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA4B;AAC5B;AACA;AACA,MAAM,iDAAM,CAAC,yCAAC;AACd,KAAK;AACL;AACA;AACA;AACA;AACO;AACP;AACA;AACA,eAAe,gDAAQ;AACvB,eAAe,kDAAU,CAAC,gDAAQ;AAClC;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACoE;AACpE;AACO;AACP;AACA;AACA;AACA,IAAI,+CAAO;AACX,KAAK,gDAAQ;AACb;AACA;AACA;AACA;AACA;AACA,MAAM,gDAAQ;AACd;AACA,gCAAgC,iBAAiB;AACjD,oBAAoB,aAAa;AACjC;AACA;AACA;AACA;AACA;AACA,MAAM,gDAAQ;AACd;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnC0D;AACf;AACJ;AACiB;;;;;;;;;;;;;;;;;;;;;ACHnB;AAC0C;AACzC;AACtC;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,GAAG;AACd,WAAW,cAAc;AACzB;AACO;AACP;AACA,UAAU,SAAS;AACnB;AACA,qBAAqB;AACrB,IAAI;AACJ,qCAAqC;AACrC;AACA,4BAA4B;AAC5B;AACA;AACO;AACP,UAAU,YAAY;AACtB,kBAAkB,sDAAkB;AACpC;AACA,IAAI,qBAAqB,mDAAe;AACxC;AACA,IAAI,qBAAqB,uDAAmB;AAC5C;AACA,IAAI,qBAAqB,wDAAoB;AAC7C,IAAI,0DAAc;AAClB;AACA;AACA;AACO;AACP,UAAU,YAAY;AACtB,kBAAkB,sDAAkB,gBAAgB,mDAAe;AACnE;AACA,YAAY,KAAK;AACjB;AACA,IAAI,qBAAqB,uDAAmB;AAC5C;AACA,IAAI,qBAAqB,wDAAoB;AAC7C,IAAI,4DAAgB;AACpB;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wDAAwD;AACxD;AACA;AACA;AACA;AACA,mBAAmB;AACnB;AACA;AACA;AACA;AACA,UAAU,YAAY;AACtB,kBAAkB,sDAAkB;AACpC;AACA,IAAI,qBAAqB,mDAAe;AACxC;AACA,IAAI,qBAAqB,uDAAmB;AAC5C;AACA,IAAI,qBAAqB,wDAAoB;AAC7C,IAAI,0DAAc;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,yBAAyB;AACnC;AACA,+BAA+B;AAC/B;AACA,kBAAkB,4DAAwB;AAC1C;AACA,IAAI,qBAAqB,6DAAyB;AAClD;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA,sCAAsC;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,mBAAmB;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yCAAyC;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,6CAA6C;AACvD,UAAU,sBAAsB;AAChC;AACA,kBAAkB,4DAAwB;AAC1C;AACA,qBAAqB,4DAAwB;AAC7C;AACA,MAAM,sBAAsB,6DAAyB;AACrD,kCAAkC;AAClC;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA,IAAI,qBAAqB,6DAAyB;AAClD;AACA,qBAAqB,4DAAwB;AAC7C;AACA;AACA,MAAM,sBAAsB,6DAAyB;AACrD;AACA,MAAM;AACN;AACA;AACA,IAAI;AACJ;AACA,qBAAqB,4DAAwB;AAC7C;AACA,MAAM,sBAAsB,6DAAyB;AACrD;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAkB,aAAa;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB;AACA;AACA;AACA,4BAA4B;AAC5B;AACA;AACA;AACA;AACA,oCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,kDAAU;AACpB;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;AC7RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB;AACvB;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,mBAAmB;AACnB,OAAO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACA,OAAO;AACP;AACA;;;;;;;;;;;;;;;;;;;;;ACxCoD;AACa;AACjE;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACA;AACP;AACA;AACA;AACA,WAAW,mCAAmC;AAC9C,WAAW,eAAe;AAC1B,WAAW,yBAAyB;AACpC;AACA;AACO;AACP;AACA;AACA;AACA,yCAAyC;AACzC;AACA;AACA,uCAAuC;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,+CAAO;AAC1B;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,gEAAU;AAClB,8BAA8B;AAC9B;AACA;AACA,QAAQ,gEAAU;AAClB,oCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP,MAAM,+CAAO;AACb;AACA;AACA,MAAM,gDAAQ;AACd;AACA;AACA,MAAM,gDAAQ,WAAW,gDAAQ;AACjC;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;ACjFO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACA;;;;;;;UCvDP;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;;WCtBA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA;;;;;WCPA;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D;;;;;;;;;;;;;;;;;ACN4C;AAUzB;AAC4C;AAC/D;AACO;AACP,WAAW;AACX,OAAO;AACP,QAAQ;AACR,GAAG;AACH,MAAM;AACN,UAAU;AACV,UAAU;AACV,UAAU;AACV,KAAK;AACL,UAAU;AACV,QAAQ;AACR,SAAS;AACT,YAAY;AACZ,kBAAkB;AAClB,CAAC;AACD;AACA;AACA;AACA,mBAAmB;AACnB;AACA;AACA,UAAU,OAAO;AACjB;AACA","sources":["webpack://mini-vue/./src/compiler/ast.js","webpack://mini-vue/./src/compiler/codegen.js","webpack://mini-vue/./src/compiler/compile.js","webpack://mini-vue/./src/compiler/index.js","webpack://mini-vue/./src/compiler/parse.js","webpack://mini-vue/./src/reactivity/computed.js","webpack://mini-vue/./src/reactivity/effect.js","webpack://mini-vue/./src/reactivity/index.js","webpack://mini-vue/./src/reactivity/reactive.js","webpack://mini-vue/./src/reactivity/ref.js","webpack://mini-vue/./src/runtime/component.js","webpack://mini-vue/./src/runtime/createApp.js","webpack://mini-vue/./src/runtime/helper/renderList.js","webpack://mini-vue/./src/runtime/index.js","webpack://mini-vue/./src/runtime/renderer.js","webpack://mini-vue/./src/runtime/scheduler.js","webpack://mini-vue/./src/runtime/vnode.js","webpack://mini-vue/./src/utils/index.js","webpack://mini-vue/webpack/bootstrap","webpack://mini-vue/webpack/runtime/define property getters","webpack://mini-vue/webpack/runtime/hasOwnProperty shorthand","webpack://mini-vue/webpack/runtime/make namespace object","webpack://mini-vue/./src/index.js"],"sourcesContent":["/* 定义不同的节点类型,如元素节点、属性节点、指令节点、文本节点、插值节点等,共有七种类型 */\r\nexport const NodeTypes = {\r\n ROOT: \"ROOT\" /* 根节点 */,\r\n ELEMENT: \"ELEMENT\" /* 元素节点 */,\r\n TEXT: \"TEXT\" /* 文本节点 */,\r\n SIMPLE_EXPRESSION: \"SIMPLE_EXPRESSION\" /* 表达式节点 */,\r\n INTERPOLATION: \"INTERPOLATION\" /* 插值节点 mustache语法 */,\r\n ATTRIBUTE: \"ATTRIBUTE\" /* 属性节点 */,\r\n DIRECTIVE: \"DIRECTIVE\" /* 指令节点 */,\r\n};\r\n\r\nexport const ElementTypes = {\r\n ELEMENT: \"ELEMENT\" /* 普通标签 */,\r\n COMPONENT: \"COMPONENT\" /* 组件,自定义标签 */,\r\n};\r\n\r\nexport function createRoot(children) {\r\n return {\r\n type: NodeTypes.ROOT,\r\n children,\r\n };\r\n}\r\n","import { NodeTypes, ElementTypes } from \".\";\r\nimport { resolveComponent } from \"../runtime\";\r\nimport { capitalize } from \"../utils\";\r\n\r\n// 接受一段语法树,返回对应的以h函数代码片段形式表达的虚拟dom树\r\nexport function generate(ast) {\r\n return traverseNode(ast);\r\n}\r\n\r\n/**\r\n * 编译节点树,关注四个基本的节点类型,生成h函数的字符串\r\n * 注意,这些函数都是生成h函数的代码,即一段代码文本,而不是直接执行函数\r\n * 刚开始执行必然是ROOT节点,parent首先是undefined,\r\n * traverseChildren函数是parent参数的真正入口\r\n * @param {*} node\r\n * @returns\r\n */\r\nfunction traverseNode(node, parent) {\r\n // debugger;\r\n\r\n switch (node.type) {\r\n case NodeTypes.ROOT:\r\n return traverseChildren(node);\r\n case NodeTypes.ELEMENT:\r\n // 指令节点都在元素节点中,处理元素节点的同时也处理指令节点\r\n // 对于v-for v-if 等能够改变dom结构的结构型指令来说,需要配合runtime进行实现\r\n // v-for使用renderList,\r\n\r\n // traverseChildren是parent参数的真正入口\r\n return resolveElementVNode(node, parent);\r\n // return createElementVNode(node);\r\n case NodeTypes.INTERPOLATION:\r\n return createInterpolationVNode(node);\r\n case NodeTypes.TEXT:\r\n return createTextVNode(node);\r\n default:\r\n break;\r\n }\r\n}\r\n\r\n/* 通过isStatic来判断是否为静态节点,从而生成对应的代码片段,如插值不需要引号,静态文本需要引号,注意是生成可执行的代码片段 */\r\nfunction createText({ isStatic = true, content = \"\" } = {}) {\r\n return isStatic ? JSON.stringify(content) : content;\r\n}\r\n\r\nfunction createTextVNode(node) {\r\n return `h(Text, null, ${createText(node)})`;\r\n}\r\n/* 将插值节点也看成是虚拟dom的Text类型 */\r\nfunction createInterpolationVNode(node) {\r\n // return `h(Text, null, ${node.content.content})`;\r\n return `h(Text, null, ${createText(node.content)})`;\r\n}\r\n\r\nfunction resolveElementVNode(node, parent) {\r\n const { directives } = node;\r\n // 特殊的指令如v-for,v-if处理,而普通的bind,on,v-model(on、bind的语法糖)等在createElementVNode中处理\r\n const forNode = pluck(directives, \"for\");\r\n if (forNode) {\r\n // <div v-for=\"(item, index) in items\">{{item + index}}</div>\r\n // 编译目标\r\n // h(\r\n // Fragment,\r\n // null,\r\n // renderList(items, (item, index) => h('div', null, item + index))\r\n // );\r\n const [args, sources] = forNode.exp.content.split(/\\sin\\s|\\sof\\s/); // in of 相同\r\n return `h(\r\n Fragment, \r\n null, \r\n renderList(\r\n ${sources.trim()}, \r\n ${args.trim()} => ${resolveElementVNode(node, parent)})\r\n )`;\r\n }\r\n\r\n const ifNode = pluck(directives, \"if\") || pluck(directives, \"else-if\");\r\n if (ifNode) {\r\n // <div v-if=\"ok\"></div>\r\n // v-if编译目标\r\n // ok ? h('div') : h(Text, null, ''); 空文本节点\r\n\r\n // <h1 v-if=\"ok\"></h1>\r\n // <h2 v-else></h2>\r\n // <h3></h3>\r\n // v-else编译目标\r\n // [\r\n // ok ? h(\"h1\") : h(\"h2\"),\r\n // h(\"h3\")\r\n // ]\r\n\r\n // <h1 v-if=\"ok\"></h1>\r\n // <h2 v-else-if=\"ok2\"></h2>\r\n // v-else-if编译目标\r\n // ok\r\n // ? h('h1')\r\n // : ok2\r\n // ? h('h2')\r\n // : h(Text, null, '');\r\n\r\n const condition = ifNode.exp.content;\r\n let ifExp = `${resolveElementVNode(node, parent)}`;\r\n let elseExp = `h(Text, null, '')`; // 默认的else表达式\r\n\r\n // 当前node是ifNode的父节点,elseNode存放于当前node的parent的后续children中,需要与当前node相邻,中间可以存在空白字符节点,只需要检查下一个Element类型的节点是否包含else指令,如果是需要删除中间的空白字符节点,不需要一直判断下去\r\n // 需要parent节点才能拿到children,改造函数resolveElementVNode(node, parent),traverseChildren是parent参数的真正入口\r\n const ifIdx = parent.children.indexOf(node);\r\n let idx = ifIdx;\r\n while (idx < parent.children.length) {\r\n const child = parent.children[++idx];\r\n // 检查下一个ELEMENT节点,而不是下一个节点\r\n if (child?.type === NodeTypes.ELEMENT) {\r\n // 如果存在elseIfNode,删除中间空白节点,但是此时else-if不能删除,可以看成是小范围的if,在ifNode时删除即可\r\n if (pluck(child.directives, \"else-if\", false)) {\r\n parent.children.splice(ifIdx, idx - ifIdx);\r\n elseExp = `${resolveElementVNode(child, parent)}`;\r\n }\r\n // 如果存在elseNode,删除中间的空白字符节点\r\n if (pluck(child.directives, \"else\")) {\r\n parent.children.splice(ifIdx, idx - ifIdx); // 需要先删除,否则会重复\r\n elseExp = `${resolveElementVNode(child, parent)}`;\r\n }\r\n break; // 只检查下一个ELEMENT类型的节点\r\n }\r\n }\r\n return `${condition} ? ${ifExp} : ${elseExp}`;\r\n }\r\n\r\n return createElementVNode(node);\r\n}\r\n\r\nfunction createElementVNode(node) {\r\n // const tag = createText({ content: node.tag }); //创建文本\r\n // 真实的场景中,还会有自定义组件,即通过components:{} 传入的组件名称,需要在createApp函数中获取组件的名称\r\n let { tag, tagType } = node;\r\n tag = createText({ content: tag }); // 无论是普通标签还是组件对象名称都是字符串\r\n tag =\r\n tagType === ElementTypes.ELEMENT\r\n ? tag // 普通类型\r\n : `resolveComponent(${tag})`; // 组件对象类型,使用对应的方法获取\r\n\r\n /* 不需要单独的判断子元素的个数,通过遍历即可,但是为了存储的优化,需要进行判断 */\r\n const props = formatProps(node);\r\n const children = traverseChildren(node);\r\n if (props === \"null\" && children === \"[]\") {\r\n return `h(${tag})`;\r\n }\r\n if (children === \"[]\") {\r\n // 此时props不可能为 null\r\n return `h(${tag}, ${props})`;\r\n }\r\n return `h(${tag}, ${props}, ${children})`; // props可能为null,符合正常逻辑\r\n}\r\n\r\nfunction createPropArr(node) {\r\n const { props, directives } = node;\r\n // v-model是一个on+bind的语法糖,使用map不会自动更新length,提前设置\r\n const vModel = pluck(node.directives, \"model\");\r\n if (vModel) {\r\n directives.push(\r\n {\r\n type: NodeTypes.DIRECTIVE,\r\n name: \"bind\",\r\n exp: vModel.exp, // 表达式节点\r\n arg: {\r\n type: NodeTypes.SIMPLE_EXPRESSION,\r\n content: \"value\",\r\n isStatic: true,\r\n }, // 表达式节点\r\n },\r\n {\r\n type: NodeTypes.DIRECTIVE,\r\n name: \"on\",\r\n exp: {\r\n type: NodeTypes.SIMPLE_EXPRESSION,\r\n content: `($event) => ${vModel.exp.content} = $event.target.value`,\r\n isStatic: false,\r\n }, // 表达式节点\r\n arg: {\r\n type: NodeTypes.SIMPLE_EXPRESSION,\r\n content: \"input\",\r\n isStatic: true,\r\n }, // 表达式节点\r\n }\r\n );\r\n }\r\n\r\n return [\r\n ...props.map((prop) => `${prop.name}: ${createText(prop.value)}`),\r\n ...directives.map((dir) => {\r\n /* 从ast中抽出dirname */\r\n switch (dir.name) {\r\n case \"bind\":\r\n return `${dir.arg.content}: ${createText(dir.exp)}`;\r\n case \"on\":\r\n const event = `on${capitalize(\r\n dir.arg.content\r\n )}`; /* 事件名称格式化,如onClick */\r\n\r\n let exp = dir.exp.content;\r\n\r\n /* 不包含 => 即不是一个箭头函数 */\r\n if (\r\n (/\\([^)]*?\\)$/.test(exp) || // 带有括号形式\r\n /\\+\\+|--|\\+=|-=|\\*=|\\/=|\\%=|==|===/.test(exp)) && // ++ -- 形式\r\n !exp.includes(\"=>\") // 不是箭头函数\r\n ) {\r\n exp = `$event => {${exp}}`;\r\n }\r\n\r\n return `${event}: ${exp}`;\r\n case \"html\":\r\n return `innerHTML: ${createText(dir.exp)}`;\r\n default:\r\n return `${dir.arg?.content || dir.name}: ${createText(dir.exp)}`;\r\n // return dir; // 没有处理的不能原样返回\r\n }\r\n }),\r\n ];\r\n}\r\n\r\nfunction traverseChildren(node) {\r\n const { children } = node;\r\n // 多级嵌套需要使用递归的形式进行解析,h函数中,子元素应该使用中括号包裹\r\n // 特别注意map会返回一个相同长度的数组,可能会返回item === undefined的元素,需要filter去除,或者使用reduce\r\n return (\r\n \"[\" +\r\n children\r\n .map((child) => traverseNode(child, node))\r\n .filter((child) => child)\r\n .join(\", \") +\r\n \"]\"\r\n );\r\n}\r\n\r\nfunction formatProps(node) {\r\n // 每一个不同的指令节点,不能共用,因为pluck会删除元素\r\n /* 解析属性节点和指令节点,生成对应的字符串格式 */\r\n const propArr = createPropArr(node);\r\n return propArr?.length ? `{${propArr.join(\", \")}}` : \"null\";\r\n}\r\n\r\n/**\r\n * 表示接受一个指令集合、指令名称、是否移除指令\r\n * @param {*} directives\r\n * @param {*} name\r\n * @param {Boolean} remove:true\r\n */\r\nfunction pluck(directives = [], name, remove = true) {\r\n const idx = directives.findIndex((dir) => dir.name === name); // 找对应名字的指令\r\n const dir = directives[idx];\r\n if (dir && remove) {\r\n directives.splice(idx, 1); // 如果存在,并且需要删除,则删除对应的指令节点\r\n }\r\n return dir;\r\n}\r\n","import { generate } from \"./codegen\";\r\nimport { parse } from \"./parse\";\r\n\r\nexport function compile(template) {\r\n const ast = parse(template); // 解析模板得到ast\r\n const code = generate(ast); // 解析ast得到一段可执行的代码\r\n return code;\r\n}\r\n","export { NodeTypes, ElementTypes, createRoot } from \"./ast\";\r\nexport { compile } from \"./compile\";\r\nexport { generate } from \"./codegen\";\r\nexport { parse } from \"./parse\";\r\n","import { isVoidTag, isNativeTag, camelize } from \"../utils\";\r\nimport { createRoot, ElementTypes, NodeTypes } from \"./ast\";\r\n\r\nexport function parse(content) {\r\n /* 保存原有字符串,并加上一些配置信息 */\r\n const context = createParseContext(content);\r\n /* 通过context及配置信息,编译children的ast */\r\n const children = parseChildren(context);\r\n /* 生成编译后带有根节点的初始抽象语法树 */\r\n return createRoot(children);\r\n}\r\n\r\nfunction createParseContext(content) {\r\n return {\r\n options: {\r\n delimiters: [\"{{\", \"}}\"], //分隔符,可配置,\r\n isVoidTag, // 为了跨平台设计的\r\n isNativeTag,\r\n },\r\n source: content, //source保存原有的模板字符串 */\r\n };\r\n}\r\n\r\nfunction parseChildren(context) {\r\n let nodes = [];\r\n while (!isTextEnd(context)) {\r\n const s = context.source;\r\n // 分为三个阶段,\r\n // 1. 解析元素节点,包括解析标签内部属性、指令等\r\n // 2. 解析内部节点:分为两个 文本节点和插值节点\r\n let node = null;\r\n if (s.startsWith(context.options.delimiters[0])) {\r\n // 如果是给定的分割符号\r\n node = parseInterpolation(context);\r\n } else if (s.startsWith(\"<\")) {\r\n // 如果是一个起始的标签\r\n node = parseElement(context);\r\n } else {\r\n // 文本节点,假设给定的内容就是正常的,不含有特殊的符号\r\n node = parseText(context);\r\n }\r\n nodes.push(node);\r\n }\r\n\r\n let removedWhiteSpaces = false;\r\n // 对空白字符做优化处理\r\n for (let i = 0; i < nodes.length; i++) {\r\n const node = nodes[i];\r\n if (node.type === NodeTypes.TEXT) {\r\n // 如果是文本节点,区分文本节点内容是否全是空白\r\n // /^[\\t\\r\\n\\f ]*$/\r\n // debugger\r\n if (/[^\\t\\r\\n\\f ]/.test(node.content)) {\r\n /* 如果文本内容有一些字符 */\r\n node.content = node.content.replace(/[\\t\\r\\n\\f ]+/g, \" \"); // 将多个空格替换成一个空格\r\n } else {\r\n /* 如果全是空白,做出一些判断进行节点的删除 */\r\n const prev = nodes[i - 1];\r\n const next = nodes[i + 1];\r\n // 如果其中一个为undefined或前后一个都是元素节点,并且node带有换行符,删除节点\r\n if (\r\n !prev ||\r\n !next ||\r\n (prev.type === NodeTypes.ELEMENT &&\r\n next.type === NodeTypes.ELEMENT &&\r\n /[\\r\\n]/.test(node.content))\r\n ) {\r\n /* 删除节点 */\r\n removedWhiteSpaces = true;\r\n nodes[i] = null;\r\n } else {\r\n node.content = \" \";\r\n }\r\n }\r\n }\r\n }\r\n\r\n return removedWhiteSpaces ? nodes.filter((node) => node) : nodes;\r\n}\r\n\r\nfunction isTextEnd(context) {\r\n const s = context.source;\r\n return s === \"\" || s.startsWith(\"</\");\r\n}\r\n\r\nfunction parseInterpolation(context) {\r\n // 一种形式:遇到左大括号,即分隔符好的左符号\r\n const [open, close] = context.options.delimiters;\r\n advanceBy(context, open.length); // 移除左边分割符号\r\n advanceSpaces(context);\r\n const len = context.source.indexOf(close); // 不要和数组的方法findIndex混淆了\r\n const content = sliceStr(context, len).trim(); // 获取插值变量,注意需要去除空格\r\n advanceBy(context, close.length); // 移除右边分隔符号\r\n // advanceSpaces(context); 此时不能移除剩余的空格,后续会有空格优化!如{{index}} : {{item}}\r\n\r\n return {\r\n type: NodeTypes.INTERPOLATION,\r\n content: {\r\n type: NodeTypes.SIMPLE_EXPRESSION,\r\n content,\r\n isStatic: false,\r\n },\r\n };\r\n}\r\n\r\n// <div id=\"foo\" v-if=\"show\">Text {{name}}</div>\r\nfunction parseElement(context) {\r\n // 解析分为三部分\r\n // 1. 开始标签\r\n // 2. children\r\n // 3. 结束标签\r\n // debugger;\r\n\r\n const element = parseTag(context); // 开始标签\r\n if (element.isSelfClosing) {\r\n // 如果是自闭合的标签,可以返回\r\n return element;\r\n }\r\n // debugger\r\n element.children = parseChildren(context); // children\r\n parseTag(context); // 结束标签\r\n return element;\r\n}\r\n\r\nfunction parseTag(context) {\r\n const match = /^<\\/?([a-z][^\\t\\r\\n\\f />]*)/i.exec(context.source);\r\n // 正则分组改变优先级, match[0]包含<,而match[1]不包含<,只是标签名\r\n const tag = match[1]; // 标签名\r\n advanceBy(context, match[0].length); // 去除<div\r\n advanceSpaces(context); // 去除空格\r\n\r\n /* 属性节点、指令节点 */\r\n const { props, directives } = parseAttributes(context);\r\n\r\n // 自闭合形式,但是<br>也是正确的,需要另外一个函数的辅助\r\n const isSelfClosing =\r\n context.source.startsWith(\"/>\") || context.options.isVoidTag(tag);\r\n advanceBy(context, isSelfClosing ? 2 : 1); // 自闭合截取2,非自闭合截取1\r\n advanceSpaces(context); // 每当advanceBy后,需要注意去掉空格,但是不一定是一次advanceBy就一次advanceSpaces()\r\n\r\n const tagType = isComponent(context, tag)\r\n ? ElementTypes.COMPONENT\r\n : ElementTypes.ELEMENT;\r\n\r\n return {\r\n type: NodeTypes.ELEMENT,\r\n tag, // 标签名,\r\n tagType, // 是组件还是原生元素,\r\n props, // 属性节点数组,\r\n directives, // 指令数组\r\n isSelfClosing, // 是否是自闭合标签,\r\n children: [],\r\n };\r\n}\r\n\r\nfunction parseAttributes(context) {\r\n const props = [];\r\n const directives = [];\r\n\r\n function isTagEnd(context) {\r\n const s = context.source;\r\n return s === \"\" || s.startsWith(\">\") || s.startsWith(\"/>\");\r\n }\r\n\r\n while (!isTagEnd(context)) {\r\n const attr = parseSingleAttribute(context);\r\n if (attr.type === NodeTypes.DIRECTIVE) {\r\n directives.push(attr);\r\n } else {\r\n props.push(attr);\r\n }\r\n }\r\n\r\n return { props, directives };\r\n}\r\n\r\nfunction parseSingleAttribute(context) {\r\n const match = /^[^\\t\\r\\n\\f />][^\\t\\r\\n\\f />=]*/.exec(context.source);\r\n // 分为两种匹配,第一个key=value结构,如id=\"app\",第二个没有key=value结构,如checkd\r\n const name = match[0];\r\n advanceBy(context, name.length);\r\n advanceSpaces(context);\r\n\r\n let value = null;\r\n const s = context.source;\r\n if (s[0] === \"=\") {\r\n /* 如果是key=value结构 */\r\n advanceBy(context, 1); // 去除等号\r\n advanceSpaces(context); // 去除多余的空格\r\n value = parseAttributeValue(context);\r\n }\r\n\r\n // 指令节点,通过name判断,一定是v-, @, :开头\r\n if (/^(v-|@|:)/.test(name)) {\r\n let dirName = null;\r\n let arg = null;\r\n // 三种形式\r\n if (name[0] === \":\") {\r\n dirName = \"bind\";\r\n arg = name.slice(1);\r\n } else if (name[0] === \"@\") {\r\n dirName = \"on\";\r\n arg = name.slice(1);\r\n } else if (name.startsWith(\"v-\")) {\r\n [dirName, arg] = name.slice(2).split(\":\"); // v-if v-on v-model不存在arg,而v-bind:class存在arg\r\n }\r\n\r\n return {\r\n type: NodeTypes.DIRECTIVE,\r\n name: dirName,\r\n exp: value && {\r\n //等号之后的内容\r\n type: NodeTypes.SIMPLE_EXPRESSION,\r\n content: value.content,\r\n isStatic: false,\r\n },\r\n arg: arg && {\r\n // 等号之前的内容\r\n type: NodeTypes.SIMPLE_EXPRESSION,\r\n content: camelize(arg),\r\n isStatic: true,\r\n },\r\n };\r\n }\r\n\r\n // 普通的属性节点\r\n return {\r\n type: NodeTypes.ATTRIBUTE,\r\n name,\r\n value: value && {\r\n type: NodeTypes.TEXT,\r\n content: value.content,\r\n },\r\n };\r\n}\r\n\r\nfunction parseAttributeValue(context) {\r\n // 三种情况:双引号,单引号,没有引号,默认都是带有引号的\r\n const quote = context.source[0];\r\n advanceBy(context, 1); //去除第一个引号\r\n const end = context.source.indexOf(quote);\r\n const content = sliceStr(context, end);\r\n advanceBy(context, 1); // 去除后一个引号\r\n advanceSpaces(context); // 去除空格\r\n return { content };\r\n}\r\n\r\nfunction parseText(context) {\r\n /* 注意:结束的标志不是</,而是<,因为中间还可以子元素节点 */\r\n const endTags = [\"<\", context.options.delimiters[0]];\r\n\r\n // 三种结束方式\r\n // 1. 遇到插值的分隔符{{\r\n // 2. 遇到结束标签</\r\n // 3. 一行的末尾\r\n let textLen = context.source.length;\r\n textLen = endTags.reduce((prev, tag) => {\r\n const idx = context.source.indexOf(tag);\r\n if (idx !== -1) {\r\n prev = Math.min(prev, idx);\r\n }\r\n return prev;\r\n }, textLen);\r\n\r\n const content = sliceStr(context, textLen);\r\n\r\n return {\r\n type: NodeTypes.TEXT,\r\n content,\r\n };\r\n}\r\n\r\nfunction sliceStr(context, textLen) {\r\n const content = context.source.slice(0, textLen);\r\n advanceBy(context, textLen);\r\n advanceSpaces(context);\r\n return content;\r\n}\r\n\r\nfunction advanceBy(context, numberOfCharacters) {\r\n // 指定前进的字符数量,即\r\n context.source = context.source.slice(numberOfCharacters);\r\n}\r\nfunction advanceSpaces(context) {\r\n // 将下一个非空白字符前的空白字符串去掉\r\n const match = /^[\\t\\r\\n\\f ]+/.exec(context.source);\r\n // 如果匹配到相应的空白字符串\r\n if (match) {\r\n advanceBy(context, match[0].length); // 第一个就是匹配成功的空白字符串\r\n }\r\n}\r\n\r\nfunction isComponent(context, tag) {\r\n return !context.options.isNativeTag(tag);\r\n}\r\n","/* 无论是基本数据还是传入的函数,都是放入一个对象中存储,不同的是为了设计computed的缓存特性增加了lazy与scheduler调用\r\n lazy避免第一次运行,通过effect函数保存scheduler,最后在trigger中判断是否有调度器,\r\n 如果有调度器调用调度器,否则才是调用传入的函数\r\n\r\n 通过自身的属性_dirty判断自身的依赖是否更新\r\n 通过get捕获中的track,捕获依赖自身的那些函数\r\n 通过调度器调用时,进行触发依赖于自身的函数,注意:computed自身的依赖与依赖自身的变量是两个概念!\r\n */\r\n\r\nimport { isFunction } from \"../utils\";\r\nimport { effect, track, trigger } from \"./effect\";\r\n\r\nclass ComputedImpl {\r\n constructor(options) {\r\n this._setter = options.setter;\r\n this._value = undefined; /* 当前的值 */\r\n this._dirty = true; /* 表示computed依赖的变量有更新,不是依赖computed的函数! */\r\n this.effect = effect(options.getter, {\r\n lazy: true,\r\n scheduler: () => {\r\n /* 调度器是为了满足缓存的特性而设计的!trigger只会调用调度器,通过调度器控制_ditry来更新,并且不会直接调用 */\r\n if (!this._dirty) {\r\n // 如果未更新不需要重新计算\r\n this._dirty = true; /* 当scheduler被调用时,表示的变量发生了更新,但是getter不会被调用,而是自身的value被引用即触发get操作时才会判断_dirty并决定是否重新计算 */\r\n trigger(\r\n this,\r\n \"value\"\r\n ); /* 通知依赖自身的函数更新,通过get捕获判断_dirty重新计算,注意和trigger函数中进行区分! */\r\n }\r\n },\r\n }); /* 修改effect函数,如果传入了lazy初始默认不执行,如果传入了scheduler,则保存在自身上! */\r\n }\r\n\r\n get value() {\r\n if (this._dirty) {\r\n // 通过判断自身依赖的变量是否发生了更新,从而确定自身是否更新\r\n this._dirty = false; // 重新计算后,将_dirty置为false\r\n this._value =\r\n this.effect(); /* 此时调用的函数是从effect函数中返回的,是getter操作被封装成一个effectFn,最后返回的 */\r\n track(this, \"value\"); /* 第一次默认进行会被收集依赖 */\r\n }\r\n return this._value;\r\n }\r\n\r\n set value(value) {\r\n /* 判断是否只读! */\r\n this._setter(value)\r\n }\r\n}\r\n\r\nexport function computed(getterOrOption) {\r\n let getter = () => {}\r\n let setter = () => {\r\n console.error(\"The computed is readonly!\");\r\n };\r\n\r\n let options = isFunction(getterOrOption)\r\n ? { getter: getterOrOption, setter }\r\n : { getter: getterOrOption.getter || getter, setter: getterOrOption.set || setter };\r\n \r\n return new ComputedImpl(options)\r\n}\r\n","let activeEffect;\r\n\r\n/**\r\n * 一个对象可以有多个属性\r\n * 一个属性可以在多个effect中使用\r\n * 一个effect可以同时使用多个不同的对象|对象属性\r\n *\r\n * 分析依赖关系,确定是对象|对象属性的变化导致effect,\r\n * 那么应该这样设计依赖关系结构\r\n * AMap:key为target,value为一个BMap 解释:区分不同对象的AMap\r\n * BMap:key为对象的不同属性,value为一个CSet 解释:区分一个对象的不同属性\r\n * CSet:存储effect 解释:存储所有依赖于某个对象的某个属性的effect,可以使用数组,但是需要进行去重,使用Set更合适\r\n * 注意:这些关系结构都是基于:对象|对象属性的变量导致effect的执行\r\n */\r\nlet targetMap = new WeakMap(); /* 区分不同的对象 */\r\nlet keyMap; /* 区分同一个对象的不同属性,不同targetMap元素生成不同的keyMap */\r\nlet effectSet; /* 存储所有依赖于某个对象的某个属性的effect */\r\n\r\nlet effectStack = [];\r\n\r\nexport function effect(fn, options = {}) {\r\n const effectFn = () => {\r\n let result;\r\n try {\r\n activeEffect =\r\n effectFn; /* 当前的函数会被标记,在reactive代理对象的get操作收集依赖时,activeEffect会被收集,此时的fn就是对应变量的依赖项 */\r\n effectStack.push(activeEffect);\r\n result = fn();\r\n } catch (error) {\r\n /* watchEffect默认调用,用户的函数可能出错,但是不能影响库代码 */\r\n console.error(error);\r\n } finally {\r\n activeEffect =\r\n undefined; /* 必须要重新置为null或者undefined,否则在进行判断收集使会出错 */\r\n // 为了解决嵌套的effect,需要从effectFns中弹出\r\n // effectStack.pop(); /* 已经被记录过了! */\r\n // activeEffect = effectStack.length ? effectStack.pop() : undefined;\r\n effectStack.pop();\r\n /* 如果为0,length-1=-1不会报错,而是一个undefined,js数组越界不会报错,访问只会返回undefined */\r\n activeEffect = effectStack[effectStack.length - 1];\r\n return result;\r\n }\r\n };\r\n if (!options.lazy) {\r\n effectFn();\r\n }\r\n effectFn.scheduler = options.scheduler;\r\n return effectFn;\r\n}\r\n\r\n/* track 收集依赖 */\r\nexport function track(target, key) {\r\n /* 如果不存在activeEffect,返回即可 */\r\n if (!activeEffect) {\r\n return;\r\n }\r\n\r\n /* ================可以使用三元表达式====================== */\r\n\r\n let depsMap = targetMap.get(target);\r\n if (!depsMap) {\r\n targetMap.set(target, (depsMap = new Map())); /* 另外一种写法 */\r\n }\r\n\r\n let deps = depsMap.get(key);\r\n if (!deps) {\r\n depsMap.set(key, (deps = new Set()));\r\n }\r\n\r\n deps.add(activeEffect);\r\n}\r\n\r\n/* trigger 触发依赖 */\r\nexport function trigger(target, key) {\r\n /* 更新触发,取出targetMap中的target,keyMap中的effectSet */\r\n targetMap\r\n .get(target)\r\n ?.get(key)\r\n ?.forEach((effect) => {\r\n /* 如果有调度器,应该只调用调度器,其余的操作由调度器来完成。\r\n 这是不同于watchEffect的逻辑,通过调用调度器来实现不立即更新,\r\n 这是computed依赖的变量更新了,不是要依赖于computed的函数立即更新。\r\n scheduler通知_ditry变化,而后scheduler自身中再调用computed的trigger通知依赖自身的函数,\r\n 达到computed的知道自身依赖的变量更新了,但是不马上计算,\r\n 只有依赖于自身的函数使用了我,我才判断是否重新计算的功能\r\n 如果依赖于computed的变量没有访问,那么computed就不会重新计算,\r\n 因为计算的过程在get捕获中!只有访问了才能重新计算! */\r\n effect.scheduler ? effect.scheduler(effect) : effect();\r\n });\r\n}\r\n","export { reactive } from \"./reactive\";\r\nexport { ref } from \"./ref\";\r\nexport { computed } from \"./computed\";\r\nexport { effect } from \"./effect\";\r\n","import { hasChanged, isArray, isObject } from \"../utils\";\r\nimport { track, trigger } from \"./effect\";\r\n\r\n/**\r\n * 为了能够正确的收集依赖,传入的target对象必须要再包裹一层,\r\n * 因为只适用对象本身则无法触发get操作!再次包裹一层就能够触发外层的get\r\n *\r\n * 但是在尝试后发现:Vue官方也没有做这个处理\r\n */\r\nclass Target {\r\n constructor(target) {\r\n this.value = target;\r\n }\r\n}\r\n\r\nconst proxyMap = new WeakMap();\r\n\r\n// reactive建立了一个响应式对象,即Proxy对象,它一般与effect函数建立联系\r\nexport function reactive(target) {\r\n /* 如果不是一个对象,不代理即不做任何处理 */\r\n if (!isObject(target)) {\r\n return target;\r\n }\r\n\r\n /* 特殊情况一:嵌套使用reactive,只代理一次,reactive(reactive(obj)),给obj添加私有的属性_isReactive */\r\n if (!isReactive(target)) {\r\n target._isReactive = true;\r\n }\r\n\r\n /* 特殊情况二:多个依赖依赖于同一个对象,只生成一个代理对象,使用一个WeakMap来存储每一个代理对象 */\r\n if (proxyMap.has(target)) {\r\n return proxyMap.get(target);\r\n }\r\n\r\n /* 如果是一个对象,那么就返回一个代理对象 */\r\n const proxy = new Proxy(target, {\r\n get(target, key, receiver) {\r\n const res = Reflect.get(target, key, receiver);\r\n /* 特殊情况六:嵌套的effect,会导致外层的effect丢失!在effect函数中利用栈解决 */\r\n track(target, key);\r\n /* 特殊情况四:深层代理,在vue2中所有的对象都被代理了,但是vue3可以选择哪些被代理 */\r\n // return res;\r\n return isObject(res) ? reactive(res) : res;\r\n },\r\n set(target, key, value, receiver) {\r\n /* 特殊情况三:只有值变化了才更新,如果前后是相同的值,不进行更新 */\r\n if (!hasChanged(target[key], value))\r\n return true; /* 注意set需要返回true代表更新成功,否则报错! */\r\n const flag = Reflect.set(target, key, value, receiver);\r\n \r\n /* 特殊情况五:数组的问题,数组长度的问题 数组的key需要手动触发 */\r\n if (isArray(target) && key === 'length' && hasChanged(target.length, value)) {\r\n trigger(target, \"length\"); /* 数组的key需要手动触发 */\r\n }\r\n \r\n trigger(target, key); /* 必须等对象更新完成后再触发 */\r\n return flag;\r\n },\r\n });\r\n\r\n proxyMap.set(target, proxy);\r\n\r\n return proxy;\r\n}\r\n\r\nexport function isReactive(target) {\r\n return !!(target && target._isReactive);\r\n}\r\n","import { hasChanged, isObject } from \"../utils\";\r\nimport { track, trigger } from \"./effect\";\r\nimport { reactive } from \"./reactive\";\r\n\r\nclass RefImpl {\r\n constructor(value) {\r\n this._isRef = true;\r\n /* 用私有属性来实现功能,通过简便的写法,即get value() set value()即可完成相应的get set捕获! */\r\n // 如果是一个对象,则用reactive来实现\r\n // 无论是基本数据类型还是引用数据类型,最终都是存储在一个对象的_value属性中的\r\n this._value = convert(value); /* 需要用convert来转换,否则引用类型的数据无法捕获! */\r\n }\r\n\r\n /* vue3中实现基本数据类型的响应还是Object.definedProperty,注意是基本数据类型! */\r\n get value() {\r\n track(this, 'value')\r\n return this._value /* 注意:此时返回的是私有属性的值! */\r\n }\r\n set value(value) { /* 注意:使用ref包装的对象特别注意没有引用对象属性,不会被加入依赖的!\r\n reactive函数同样也是如此,必须要使用对象的某一个属性,单纯使用对象不使用某个对象的属性是不会加入依赖的!而ref一定要使用.value取出才能够获得响应式!*/\r\n if (!hasChanged(this._value, value)) {\r\n return ;\r\n }\r\n this._value = convert(value) /* 此时也需要转换,如果传入的数据一个引用类型的数据,那么就需要转换一下! */\r\n trigger(this, 'value') \r\n }\r\n}\r\n\r\n/* ref函数用于记忆基本数据类型,引用数据类型都交给reactive函数 */\r\n/* 因为基本数据类型存储在栈上,所以难以判断是否为同一个对象,用一个对象实现存储,和reactive一样。 */\r\nexport function ref(value) {\r\n if (isRef(value)) {\r\n return value;\r\n }\r\n return new RefImpl(value); /* 用一个对象来存储,因为基本数据类型不能在同一个内存地址上,\r\n 所以在判断是否为同一个变量时应该使用一个对象来存储这些基本数据类型的变量,以方便进行比较是否为同一个变量对象 */\r\n}\r\n\r\n/* ref函数的实现喝reactive函数实现类似,包括特殊的功能等! */\r\nexport function isRef(value) {\r\n return !!(value && value._isRef);\r\n}\r\n\r\nexport function convert(value) {\r\n return isObject(value) ? reactive(value) : value;\r\n}\r\n","import { patch, unmount } from \"./renderer\";\r\nimport { scheduler } from \"./scheduler\";\r\nimport { normalizeVNode } from \"./vnode\";\r\n\r\nimport { compile } from \"../compiler\";\r\nimport { effect, reactive } from \"../reactivity\";\r\n\r\n// 组件由两个阶段生成\r\n// 第一阶段是原生的不经过h函数包裹的组件对象 如 {setup(){}, render() {return h('div', null, \"我是小明\")}}\r\n// 第二阶段是经过h函数包裹的vnode对象,如 h(Comp, vnodeProps);\r\n\r\n// vnode的props属性有两种:1. 内部使用的props父传子,2.组件attrs标签属性\r\n// 组件对象:Component,虚拟DOM:vnode\r\n\r\nfunction fallThrough(instance, subTree) {\r\n subTree.props = {\r\n ...(instance.attrs || {}),\r\n ...(subTree.props || {}),\r\n };\r\n}\r\n\r\nfunction patchInsProps(instance, vnode) {\r\n const { type: Component, props: vnodeProps } = vnode; /* 获取组件对象 */\r\n\r\n // 区分不同的属性\r\n instance.props ||= {};\r\n instance.attrs ||= {};\r\n for (const key in vnodeProps) {\r\n if (Component.props?.includes(key)) {\r\n instance.props[key] = vnodeProps[key];\r\n } else {\r\n instance.attrs[key] = vnodeProps[key];\r\n }\r\n }\r\n instance.props = reactive(instance.props); /* 做响应式处理 */\r\n}\r\n\r\nexport function mountComponent(vnode, container, anchor) {\r\n const { type: Component } = vnode;\r\n\r\n const instance = (vnode.component = {\r\n props: null,\r\n attrs: null,\r\n\r\n setupState: null,\r\n ctx: null,\r\n\r\n subTree: null,\r\n patch: null,\r\n\r\n next: null,\r\n });\r\n\r\n patchInsProps(instance, vnode);\r\n\r\n // 对于vue3,执行setup函数,获取返回值setupState,通过effect确定响应数据,最终通过render产出vnode,render接收ctx\r\n instance.setupState = Component.setup?.(instance.props, {\r\n attrs: instance.attrs,\r\n });\r\n instance.ctx = {\r\n ...instance.props,\r\n ...instance.setupState,\r\n };\r\n\r\n // 判断render函数是否存在,如果不存在,通过generate生成的h代码片段,通过new Function生成render函数\r\n if (!Component.render && Component.template) {\r\n let { template } = Component;\r\n\r\n if (template[0] === \"#\") {\r\n /* 如果是一个#开头的mount 如#template */\r\n const el = document.querySelector(template);\r\n template = el ? el.innerHTML : \"\";\r\n // 删除原template节点\r\n el.parentNode.removeChild(el);\r\n }\r\n\r\n const code = compile(template);\r\n // 通过new Function生成可执行代码,同时为了便于解决参数问题,使用with改变作用域链\r\n Component.render = new Function(\r\n \"ctx\",\r\n `with(ctx) {\r\n const {\r\n createApp,\r\n parse,\r\n render,\r\n h,\r\n Text,\r\n Fragment,\r\n nextTick,\r\n reactive,\r\n ref,\r\n computed,\r\n effect,\r\n compile,\r\n renderList,\r\n resolveComponent,\r\n } = MiniVue;\r\n return ${code} ;\r\n }`\r\n );\r\n }\r\n\r\n console.log(\"组件的render\");\r\n\r\n // 执行render函数\r\n /* 通过effect默认执行代表mount,当变量发生改变时也会重新执行 */\r\n instance.patch = effect(\r\n () => {\r\n const preTree = instance.subTree;\r\n /* 生成vnode,存储在自身的subTree属性,作为旧tree */\r\n const subTree = (instance.subTree = normalizeVNode(\r\n Component.render(instance.ctx)\r\n ));\r\n\r\n console.log(\"patch执行了\")\r\n\r\n // preTree存在,表示更新\r\n if (preTree) {\r\n // next存在,被动更新\r\n if (instance.next) {\r\n vnode = instance.next;\r\n instance.next = null;\r\n patchInsProps(instance, vnode);\r\n instance.ctx = {\r\n ...instance.props,\r\n ...instance.setupState,\r\n };\r\n }\r\n }\r\n\r\n // 当返回单根节点时,属性继承\r\n fallThrough(instance, subTree);\r\n /* 并不会造成递归,因为render函数生成vnode不再是Comp对象,生成的是div等vnode */\r\n patch(preTree, subTree, container, anchor);\r\n vnode.el = subTree.el;\r\n },\r\n {\r\n scheduler: scheduler, //trigger优先执行scheduler,并将传入的fn传入scheduler函数,\r\n }\r\n );\r\n}\r\n\r\nexport function patchComponent(_vnode, vnode, container, anchor) {\r\n vnode.component = _vnode.component;\r\n vnode.component.next = vnode;\r\n vnode.component.patch();\r\n}\r\n\r\nexport function unmountComponent(vnode) {\r\n unmount(vnode.component.subTree);\r\n}\r\n","import { camelize, capitalize, isString } from \"../utils\";\r\nimport { render } from \"./renderer\";\r\nimport { h } from \"./vnode\";\r\n\r\nlet components = {};\r\nexport function createApp(root) {\r\n components = root.components || {};\r\n const app = {\r\n mount(container) {\r\n if (isString(container)) {\r\n container = document.querySelector(container);\r\n }\r\n\r\n if (!root.template && !root.render) {\r\n /* 如果既没有template模板,也没有render函数,那么就是以mount中的内容为主,\r\n 经过上一个if的流程,此时的container可能已经是一个HTML元素节点了,需要判断 */\r\n const app =\r\n container instanceof HTMLElement\r\n ? container\r\n : document.querySelector(container);\r\n root.template = app.innerHTML;\r\n app.innerHTML = \"\"; // 需要清空原有的元素\r\n }\r\n\r\n render(h(root), container);\r\n },\r\n };\r\n return app;\r\n}\r\n\r\nexport function resolveComponent(name) {\r\n return (\r\n components[name] ||\r\n components[camelize(name)] ||\r\n components[capitalize(camelize(name))]\r\n );\r\n}\r\n","// 编译目标\r\n// h(\r\n// Fragment,\r\n// null,\r\n// renderList(items, (item, index) => h('div', null, item + index))\r\n// );\r\n\r\nimport { isArray, isNumber, isObject, isString } from \"../../utils\";\r\n\r\nexport function renderList(sources, renderItem) {\r\n // v-for可能存在的形式\r\n // Array,Object,String,Number\r\n if (\r\n isArray(sources) ||\r\n (isString(sources) && (sources = sources.split(\"\")))\r\n ) {\r\n // debugger\r\n return sources.map((source, index) => renderItem(source, index));\r\n }\r\n\r\n if (isNumber(sources)) {\r\n let nodes = [];\r\n // const arr = Array.from({ length: sources }, (v, i) => i + 1);\r\n for (let i = 0; i < sources; i++) {\r\n nodes.push(renderItem(i + 1, i));\r\n }\r\n return nodes;\r\n }\r\n\r\n if (isObject(sources)) {\r\n // for in, for of, Object.keys\r\n return Object.keys(sources).map((key, index) =>\r\n renderItem(sources[key], key, index)\r\n );\r\n }\r\n}\r\n","export { createApp, resolveComponent } from \"./createApp\";\r\nexport { render, mount } from \"./renderer\";\r\nexport { nextTick } from \"./scheduler\";\r\nexport { h, ShapeFlags, Text, Fragment } from \"./vnode\";\r\nexport { renderList } from \"./helper\";","import { ShapeFlags } from \"./vnode\";\r\nimport { mountComponent, patchComponent, unmountComponent } from \"./component\";\r\nimport { isFunction } from \"../utils\";\r\n\r\n/**\r\n * 渲染VNode,每种vnode对应不同的mount/unmount/patch函数\r\n * 真实DOM只存在两种节点,标签和文本(包括注释)\r\n * createElement | createTextNode 两种方式\r\n * type关注自身,shapeFlag关注自身与children,方便运算\r\n * @param {*} vnode\r\n * @param {HTML Element} container\r\n */\r\nexport function render(vnode, container) {\r\n // _vnode即旧vnode,将_vnode放在对应真实DOM上,方便进行与新VNode的diff对比\r\n const { _vnode } = container;\r\n if (!vnode) {\r\n unmount(_vnode); // 新vnode不存在,卸载旧vnode,后续流程均存在vnode\r\n } else {\r\n patch(_vnode, vnode, container); // 更新\r\n }\r\n container._vnode = vnode; // 代表旧vnode\r\n}\r\n\r\nexport function mount(vnode, container, anchor) {\r\n const { shapeFlag } = vnode;\r\n if (shapeFlag & ShapeFlags.ELEMENT) {\r\n mountElement(vnode, container, anchor);\r\n } else if (shapeFlag & ShapeFlags.TEXT) {\r\n mountText(vnode, container, anchor);\r\n } else if (shapeFlag & ShapeFlags.FRAGMENT) {\r\n mountFragment(vnode, container, anchor);\r\n } else if (shapeFlag & ShapeFlags.COMPONENT) {\r\n mountComponent(vnode, container, anchor);\r\n }\r\n}\r\n\r\nexport function unmount(vnode) {\r\n const { shapeFlag } = vnode;\r\n if (shapeFlag & ShapeFlags.ELEMENT || shapeFlag & ShapeFlags.TEXT) {\r\n /* 所有真实DOM的移除:Element和Text节点通过移除children实现 */\r\n const { el } = vnode;\r\n el.parentNode.removeChild(el);\r\n } else if (shapeFlag & ShapeFlags.FRAGMENT) {\r\n unmountFragment(vnode);\r\n } else if (shapeFlag & ShapeFlags.COMPONENT) {\r\n unmountComponent(vnode);\r\n }\r\n}\r\n\r\nexport function patch(_vnode, vnode, container, anchor) {\r\n // debugger\r\n if (!_vnode) {\r\n // 挂载\r\n mount(vnode, container, anchor);\r\n return;\r\n }\r\n\r\n if (!isSameVNodeType(_vnode, vnode)) {\r\n // 类型不同,卸载旧vnode,需要更新锚位置,即新vnode插入的位置\r\n // anchor = _vnode.anchor || _vnode.el.nextSibling; 错误\r\n // debugger\r\n anchor = _vnode.el?.nextSibling || _vnode.anchor;\r\n unmount(_vnode);\r\n mount(vnode, container, anchor);\r\n _vnode = null; // 不放在unmount中,vnode可能还会复用,但类型不同肯定不复用\r\n return;\r\n }\r\n // debugger\r\n /* 同类型vnode,shapeFlag相同 */\r\n const { shapeFlag } = vnode;\r\n if (shapeFlag & ShapeFlags.ELEMENT) {\r\n patchElement(_vnode, vnode, container, anchor);\r\n } else if (shapeFlag & ShapeFlags.TEXT) {\r\n patchText(_vnode, vnode, container, anchor);\r\n } else if (shapeFlag & ShapeFlags.FRAGMENT) {\r\n patchFragment(_vnode, vnode, container, anchor);\r\n } else if (shapeFlag & ShapeFlags.COMPONENT) {\r\n patchComponent(_vnode, vnode, container, anchor);\r\n }\r\n}\r\n\r\nfunction isSameVNodeType(_vnode, vnode) {\r\n return _vnode.type === vnode.type;\r\n}\r\n\r\nfunction mountElement(vnode, container, anchor) {\r\n const { type, props, shapeFlag } = vnode;\r\n const el = document.createElement(type);\r\n patchProps(null, props, el); /* 用patch改造mount */\r\n\r\n if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {\r\n mountText(vnode, el);\r\n } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\r\n mountChildren(vnode.children, el);\r\n }\r\n\r\n container.insertBefore(el, anchor);\r\n vnode.el = el; /* 为了在更新时拿到对应的真实dom */\r\n vnode.anchor = anchor;\r\n}\r\n\r\nfunction mountText(vnode, container, anchor) {\r\n /* 文本节点,没有标签! */\r\n const textNode = document.createTextNode(vnode.children);\r\n // container.appendChild(textNode); /* 添加子元素 */\r\n container.insertBefore(textNode, anchor);\r\n vnode.el = textNode;\r\n}\r\n\r\nfunction mountFragment(vnode, container, anchor) {\r\n /* 将当前的Fragment子元素挂载到Fragment父元素上*/\r\n\r\n // 思想:在初始Fragment子元素数组中,创建开始和结束两个空文本节点作为锚定位【\"\", ..., \"\"】\r\n\r\n const startAnchor = document.createTextNode(\"\");\r\n const endAnchor = document.createTextNode(\"\");\r\n vnode.el = startAnchor;\r\n vnode.anchor = endAnchor;\r\n\r\n // 使用的是insertBefore函数,endAnchor可以起到定位作用\r\n // anchor参数未指定或为undefined,默认在最后插入,和appendChild的功能一致\r\n // container.appendChild(startAnchor);\r\n // container.appendChild(endAnchor);\r\n container.insertBefore(startAnchor, anchor);\r\n container.insertBefore(endAnchor, anchor);\r\n\r\n // 将endAnchor作为参数一致传递下去,最终会传递到自身,使用即可\r\n mountChildren(vnode.children, container, endAnchor);\r\n}\r\n\r\nfunction mountChildren(children, container, anchor) {\r\n children.forEach((child) => mount(child, container, anchor));\r\n}\r\n\r\nfunction unmountFragment(vnode) {\r\n // 添加了anchor后,还需要删除刚开始添加的两个子元素,不能直接调用unmountChildren\r\n let { el: curr, anchor } = vnode;\r\n const parent = el.parentNode;\r\n while (curr !== anchor) {\r\n /* anchor是最后一个节点 */\r\n let next = curr.nextSibling;\r\n parent.removeChild(curr);\r\n curr = next;\r\n }\r\n parent.removeChild(anchor);\r\n}\r\n\r\nfunction unmountChildren(children) {\r\n children.forEach((child) => unmount(child));\r\n}\r\n\r\nfunction patchElement(_vnode, vnode, container) {\r\n vnode.el = _vnode.el;\r\n patchProps(_vnode.props, vnode.props, vnode.el);\r\n patchChildren(_vnode, vnode, vnode.el);\r\n}\r\n\r\nfunction patchText(_vnode, vnode, container, anchor) {\r\n vnode.el = _vnode.el;\r\n vnode.anchor = _vnode.anchor;\r\n vnode.el.textContent = vnode.children; /* 更新真实dom的内容 */\r\n}\r\n\r\nfunction patchFragment(_vnode, vnode, container) {\r\n // anchor传递给新vnode\r\n const startAnchor = (vnode.el = _vnode.el);\r\n const endAnchor = (vnode.anchor = _vnode.anchor);\r\n patchChildren(_vnode, vnode, container, endAnchor);\r\n}\r\n\r\nfunction patchChildren(_vnode, vnode, container, anchor) {\r\n /* 更新children函数 */\r\n const { shapeFlag: _shapeFlag, children: _children } = _vnode;\r\n const { shapeFlag, children } = vnode;\r\n\r\n if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {\r\n // 如果新vnode是TEXT_CHILDREN类型\r\n if (_shapeFlag & ShapeFlags.TEXT_CHILDREN) {\r\n // container.textContent = children;\r\n } else if (_shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\r\n unmountChildren(_children); /* 卸载旧组件! */\r\n // container.textContent = children;\r\n } else if (_vnode === null) {\r\n // container.textContent = children;\r\n }\r\n if (_children !== children) {\r\n container.textContent = children;\r\n }\r\n } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\r\n // 如果新vnode是ARRAY_CHILDREN类型\r\n if (_shapeFlag & ShapeFlags.TEXT_CHILDREN) {\r\n container.textContent = \"\";\r\n mountChildren(children, container, anchor);\r\n } else if (_shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\r\n patchArrayChildren(_children, children, container, anchor);\r\n } else if (_vnode === null) {\r\n mountChildren(children, container, anchor);\r\n }\r\n } else if (vnode === null) {\r\n // 如果新vnode是null类型\r\n if (_shapeFlag & ShapeFlags.TEXT_CHILDREN) {\r\n container.textContent = \"\";\r\n } else if (_shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\r\n unmountChildren(_children);\r\n } else if (_vnode === null) {\r\n // 都不存在即不执行任何操作!\r\n }\r\n }\r\n}\r\n\r\n/* patchUnkeyChildren,后续完善diff过程 */\r\nfunction patchArrayChildren(_children, children, container, anchor) {\r\n const [_len, len] = [_children.length, children.length];\r\n const baseLen = Math.min(_len, len);\r\n // debugger;\r\n for (let i = 0; i < baseLen; i++) {\r\n /* 更新元素 */\r\n patch(_children[i], children[i], container, anchor);\r\n }\r\n if (_len > len) {\r\n /* 如果旧len大于新len,卸载多余的 */\r\n unmountChildren(_children.slice(baseLen));\r\n } else if (_len < len) {\r\n /* 增加新元素 */\r\n mountChildren(children.slice(baseLen), container, anchor);\r\n }\r\n}\r\n\r\nconst domPropsRE = /[A-Z]|^(value|checked|selected|muted|disabled)$/;\r\nfunction patchProps(_props, props, el) {\r\n _props = _props || {};\r\n props = props || {};\r\n\r\n for (const key in _props) {\r\n /* 如果新props不包含的key,通过patch移除 */\r\n if (!props[key]) {\r\n patchSingleProp(_props[key], null, key, el);\r\n }\r\n }\r\n for (const key in props) {\r\n /* 新的props */\r\n const _value = _props[key];\r\n const value = props[key];\r\n if (_value !== value)\r\n /* 不相等进行更新,仅更新style样式 */\r\n patchSingleProp(_value, value, key, el);\r\n }\r\n}\r\nfunction patchSingleProp(_value, value, key, el) {\r\n _value = _value || \"\"; /* 如果传入的为null,默认参数形式会报错! */\r\n value ||= \"\";\r\n switch (key) {\r\n case \"class\":\r\n el.className = value; /* 去除false null类型 */\r\n break;\r\n case \"style\":\r\n for (const styleName in _value) {\r\n if (!value[styleName]) {\r\n el.style[styleName] = \"\"; /* 移除新props中没有的style */\r\n }\r\n }\r\n for (const styleName in value) {\r\n el.style[styleName] = value[styleName];\r\n }\r\n break;\r\n default:\r\n if (/^on[^a-z]/.test(key)) {\r\n if (_value) {\r\n /* 移除原有的事件 */\r\n el.removeEventListener(key.slice(2).toLowerCase(), _value);\r\n }\r\n el.addEventListener(\r\n key.slice(2).toLowerCase(),\r\n isFunction(value) ? value : () => value\r\n );\r\n return;\r\n }\r\n /* 属性设置,分为可直接读取与不可直接读取 */\r\n if (domPropsRE.test(key)) {\r\n el[key] = value;\r\n } else if (value !== false && value !== null) {\r\n // 如果是false | null,那么setAttribute会将false转成字符串,此时就代表了true,应该去掉\r\n el.setAttribute(key, value);\r\n }\r\n }\r\n}\r\n","// 调度的出现是为了性能的提高,即通过合并相同的操作,只执行一次渲染,这样就可以提高性能,调度的实现和计算属性的实现是很类似的\r\n/**\r\n * scheduler是一个类似节流的过程,\r\n * 但同时jobs是可变的,又有类似防抖的过程,\r\n * 如果执行一个job就删除一个job,那么就是一个节流的过程\r\n */\r\nlet jobs = [];\r\n\r\nexport function scheduler(job) {\r\n // 如果队列不包含相同的job,进行push\r\n if (!jobs.includes(job)) {\r\n jobs.push(job);\r\n flushJobs(); /* 类似节流函数 */\r\n }\r\n}\r\n\r\nlet isFlushing = false;\r\nconst RESOLVED = Promise.resolve();\r\nlet curr = null;\r\nfunction flushJobs() {\r\n if (!isFlushing) {\r\n isFlushing = true; /* 在刷新job的过程中,可能还会有push过程 */\r\n curr = RESOLVED.then(() => {\r\n /* 将render函数放入到微任务队列中,也就是一个类似节流的过程 */\r\n jobs.forEach((job) => job());\r\n })\r\n .catch(console.log)\r\n .finally(() => {\r\n isFlushing = false;\r\n jobs = []; /* 清空 */\r\n });\r\n }\r\n}\r\n\r\nexport function nextTick(fn) {\r\n return curr /* 如果队列中存在任务,那么需要使用当前的promise,如果不存在则使用RESOLVED */\r\n ? curr.then(fn).finally(() => {\r\n curr = null;\r\n })\r\n : RESOLVED.then(fn);\r\n}\r\n","import { isReactive } from \"../reactivity/reactive\";\r\nimport { isArray, isNumber, isObject, isString } from \"../utils\";\r\n\r\nexport const ShapeFlags = {\r\n ELEMENT: 1, // 00000001\r\n TEXT: 1 << 1, // 00000010\r\n FRAGMENT: 1 << 2, // 00000100\r\n COMPONENT: 1 << 3, // 00001000\r\n TEXT_CHILDREN: 1 << 4, // 00010000\r\n ARRAY_CHILDREN: 1 << 5, // 00100000\r\n CHILDREN: (1 << 4) | (1 << 5), //00110000\r\n};\r\n\r\nexport const Text = Symbol(\"Text\");\r\nexport const Fragment = Symbol(\"Fragment\");\r\n\r\n/**\r\n * h 生成VNode\r\n * @param {string | Object | Text | Fragment} type\r\n * @param {Object | null} props\r\n * @param {string | number | Array} children\r\n * @returns VNode\r\n */\r\nexport function h(type, props, children) {\r\n let shapeFlag = 0;\r\n switch (typeof type /* 判断自身 */) {\r\n case \"object\":\r\n shapeFlag |= ShapeFlags.COMPONENT; /* 组件对象 */\r\n break;\r\n case \"string\":\r\n shapeFlag |= ShapeFlags.ELEMENT; /* 普通元素标签 */\r\n break;\r\n case \"symbol\" /* 符号类型要么是TEXT要么是FRAGMENT */:\r\n shapeFlag |= type === Text ? ShapeFlags.TEXT : ShapeFlags.FRAGMENT;\r\n break;\r\n }\r\n switch (typeof children /* 判断 */) {\r\n case \"object\":\r\n shapeFlag |= isArray(children)\r\n ? ShapeFlags.ARRAY_CHILDREN\r\n : 0; /* 如果是数组,那么添加进shapeFlag中,否则不变 */\r\n break;\r\n case \"number\":\r\n case \"boolean\":\r\n case \"string\":\r\n shapeFlag |= ShapeFlags.TEXT_CHILDREN;\r\n children = children.toString();\r\n break;\r\n }\r\n\r\n if (props) {\r\n // 更新了props,需要重新浅拷贝触发render\r\n if (isReactive(props)) { \r\n props = Object.assign({}, props);\r\n }\r\n // reactive state objects need to be cloned since they are likely to be\r\n if (isReactive(props.style)) {\r\n props.style = Object.assign({}, props.style);\r\n }\r\n }\r\n\r\n return {\r\n type,\r\n props,\r\n children,\r\n shapeFlag,\r\n el: null /* 代表当前虚拟dom对应的真实dom */,\r\n anchor: null /* 锚用于定位 */,\r\n };\r\n}\r\n\r\nexport function normalizeVNode(vnode) {\r\n if (isArray(vnode)) {\r\n return h(Fragment, null, vnode);\r\n }\r\n if (isObject(vnode)) {\r\n return vnode;\r\n }\r\n if (isString(vnode) || isNumber(vnode)) {\r\n return h(Text, null, vnode.toString());\r\n }\r\n}\r\n","export function isObject(target) {\r\n return typeof target === \"object\" && target !== null;\r\n}\r\n\r\nexport function isFunction(getter) {\r\n return typeof getter === \"function\";\r\n}\r\n\r\nexport function isArray(target) {\r\n return Array.isArray(target);\r\n}\r\n\r\nexport function isString(target) {\r\n return typeof target === \"string\";\r\n}\r\n\r\nexport function isNumber(target) {\r\n return typeof target === \"number\";\r\n}\r\n\r\nexport function hasChanged(origin, current) {\r\n return origin !== current && !Number.isNaN(origin) && !Number.isNaN(current);\r\n}\r\n\r\nexport function camelize(str) {\r\n return str.replace(/-(\\w)/g, (_, c) => (c ? c.toUpperCase() : \" \"));\r\n}\r\n\r\nexport function capitalize(str) {\r\n return str[0].toUpperCase() + str.slice(1);\r\n}\r\n\r\nconst HTML_TAGS =\r\n \"html,body,base,head,link,meta,style,title,address,article,aside,footer,\" +\r\n \"header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,\" +\r\n \"figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,\" +\r\n \"data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,\" +\r\n \"time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,\" +\r\n \"canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,\" +\r\n \"th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,\" +\r\n \"option,output,progress,select,textarea,details,dialog,menu,\" +\r\n \"summary,template,blockquote,iframe,tfoot\";\r\n\r\nconst VOID_TAGS =\r\n \"area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr\";\r\n\r\nfunction makeMap(str) {\r\n const map = str\r\n .split(\",\")\r\n // 逗号运算符会返回后一个的表达式,如(,map)返回map,(1,2,3,alert)(\"世界你好\")可以成功调用alert!\r\n .reduce((map, item) => ((map[item] = true), map), Object.create(null));\r\n return (val) => !!map[val];\r\n}\r\n\r\nexport const isVoidTag = makeMap(VOID_TAGS);\r\nexport const isNativeTag = makeMap(HTML_TAGS);\r\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { compile, parse } from \"./compiler\";\r\nimport {\r\n createApp,\r\n resolveComponent,\r\n render,\r\n h,\r\n Text,\r\n Fragment,\r\n nextTick,\r\n renderList,\r\n} from \"./runtime\";\r\nimport { reactive, ref, computed, effect } from \"./reactivity\";\r\n\r\nexport const MiniVue = (window.MiniVue = {\r\n createApp,\r\n parse,\r\n render,\r\n h,\r\n Text,\r\n Fragment,\r\n nextTick,\r\n reactive,\r\n ref,\r\n computed,\r\n effect,\r\n compile,\r\n renderList,\r\n resolveComponent,\r\n});\r\n\r\n// console.log(\r\n// parse(`<div v-on=\"ok\">\r\n// Hello World {{Hello}}\r\n// <div>Hello\r\n// World\r\n// {{Hello}}</div>\r\n// </div>`)\r\n// );\r\n"],"names":[],"sourceRoot":""}