├── (1) zVue(简版vue源码)
├── 2.0
│ ├── zVue.html
│ └── zVue.js
└── 3.0
│ ├── zVue.html
│ └── zVue.js
├── (2) zReact(简版react源码)
├── package-lock.json
├── package.json
├── public
│ └── index.html
├── src
│ ├── index.js
│ └── wzReact
│ │ ├── ReactDOM.js
│ │ └── index.js
└── yarn.lock
├── (3) zWebpack(简版webpack源码)
├── bin
│ ├── index.js
│ └── main.47340442.js
├── dist
│ ├── index.html
│ └── main.71360163.js
├── lib
│ ├── WebpackCompiler.js
│ ├── comTest.js
│ ├── loader
│ │ ├── less-loader.js
│ │ └── style-loader.js
│ ├── main.ejs
│ └── utils.js
├── package-lock.json
├── package.json
├── public
│ └── index.html
├── src
│ ├── index.js
│ ├── index2.js
│ ├── test.css
│ └── test.less
└── webpack.config.js
├── (4) zQuery(简版jquery源码)
├── zQuery.html
└── zQuery.js
├── (5)zVuex(简版vuex源码)
└── my-vuex
│ ├── .gitignore
│ ├── README.md
│ ├── babel.config.js
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ └── index.html
│ └── src
│ ├── App.vue
│ ├── assets
│ └── logo.png
│ ├── components
│ ├── compA.vue
│ └── compB.vue
│ ├── main.js
│ └── vuex
│ ├── moduels
│ ├── other-model.js
│ └── user-model.js
│ ├── myVuex.js
│ └── store.js
├── (6)zVueRouter(简版vueRouter源码)
├── my-html-hash-router
│ ├── zRouter.html
│ └── zRouter.js
└── my-vue-router
│ ├── .babelrc
│ ├── .editorconfig
│ ├── .gitignore
│ ├── .postcssrc.js
│ ├── README.md
│ ├── build
│ ├── build.js
│ ├── check-versions.js
│ ├── logo.png
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
│ ├── config
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
│ ├── index.html
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ ├── First.vue
│ │ └── Second.vue
│ ├── main.js
│ ├── router
│ │ └── index.js
│ └── vue-router
│ │ └── index.js
│ └── static
│ └── .gitkeep
├── (7)zDiff(简版diff流程)
├── zDiff.html
├── zDiff.js
└── zVirtualDom.html
├── (8)zPromise(简版promise流程)
├── zPromise.html
└── zPromise.js
└── README.md
/(1) zVue(简版vue源码)/2.0/zVue.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | z手写vue源码
6 |
7 |
8 |
9 |
12 |
13 |
姓名:{{name}}
14 |
15 | 年龄:{{age}}
16 |
17 |
{{content}}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
60 |
61 |
87 |
88 |
89 |
欢迎访问主页
90 |
93 |
96 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/(1) zVue(简版vue源码)/2.0/zVue.js:
--------------------------------------------------------------------------------
1 | /*
2 | 本代码来自weizhan
3 | github链接:https://github.com/zhuangweizhan
4 | csdn链接:https://blog.csdn.net/zhuangweizhan/
5 | */
6 | class zVue {
7 | constructor(options){
8 | this.$options = options;
9 | console.log("this.$options===" + JSON.stringify(this.$options) );
10 | this.$data = options.data;
11 | this.$el = options.el;
12 | this.observer( this.$data );//添加observer监听
13 | new zCompile( options.el, this);//添加文档解析
14 | if ( options.created ) {
15 | options.created.call(this);
16 | }
17 | }
18 |
19 | observer( data ){//监听data数据,双向绑定
20 | if( !data || typeof(data) !== 'object'){
21 | return;
22 | }
23 | Object.keys(data).forEach(key => {//如果是对象进行解析
24 | this.observerSet(key, data, data[key]);//监听data对象
25 | this.proxyData(key);//本地代理服务
26 | });
27 | }
28 |
29 | observerSet( key, obj, value ){
30 | this.observer(key);
31 | const dep = new Dep();
32 | Object.defineProperty( obj, key, {
33 | get(){
34 | Dep.target && dep.addDep(Dep.target);
35 | return value;
36 | },
37 | set( newValue ){
38 | if (newValue === value) {
39 | return;
40 | }
41 | value = newValue;
42 | //通知变化
43 | dep.notiyDep();
44 | }
45 | })
46 | }
47 |
48 | proxyData(key){
49 | Object.defineProperty( this, key, {
50 | get(){
51 | return this.$data[key];
52 | },
53 | set( newVal ){
54 | this.$data[key] = newVal;
55 | }
56 | })
57 | }
58 |
59 | }
60 |
61 | //存储数据数组
62 | class Dep{
63 | constructor(){
64 | this.deps = [];
65 | }
66 |
67 | addDep(dep){
68 | this.deps.push(dep);
69 | }
70 |
71 | notiyDep(){
72 | this.deps.forEach(dep => {
73 | dep.update();
74 | })
75 | }
76 | }
77 |
78 | //个人编译器
79 | class zCompile{
80 | constructor(el, vm){
81 | this.$el = document.querySelector(el);
82 |
83 | this.$vm = vm;
84 | if (this.$el) {
85 | this.$fragment = this.getNodeChirdren( this.$el );
86 | this.compile( this.$fragment);
87 | this.$el.appendChild(this.$fragment);
88 | }
89 | }
90 |
91 | getNodeChirdren(el){
92 | const frag = document.createDocumentFragment();
93 |
94 | let child;
95 | while( (child = el.firstChild )){
96 | frag.appendChild( child );
97 | }
98 | return frag;
99 | }
100 |
101 | compile( el ){
102 | const childNodes = el.childNodes;
103 | Array.from(childNodes).forEach( node => {
104 | if( node.nodeType == 1 ) {//1为元素节点
105 | const nodeAttrs = node.attributes;
106 | Array.from(nodeAttrs).forEach( attr => {
107 | const attrName = attr.name;//属性名称
108 | const attrVal = attr.value;//属性值
109 | if( attrName.slice(0,2) === 'z-' ){
110 | var tagName = attrName.substring(2);
111 | switch( tagName ){
112 | case "model":
113 | this.zDir_model( node, attrVal );
114 | break;
115 | case "html":
116 | this.zDir_html( node, attrVal );
117 | break;
118 | }
119 | }
120 | if( attrName.slice(0,1) === '@' ){
121 | var tagName = attrName.substring(1);
122 | this.zDir_click( node, attrVal );
123 | }
124 | })
125 | } else if( node.nodeType == 2 ){//2为属性节点
126 | console.log("nodeType=====22");
127 | } else if( node.nodeType == 3 ){//3为文本节点
128 | this.compileText( node );
129 | }
130 |
131 | // 递归子节点
132 | if (node.childNodes && node.childNodes.length > 0) {
133 | this.compile(node);
134 | }
135 | })
136 | }
137 |
138 | zDir_click(node, attrVal){
139 | var fn = this.$vm.$options.methods[attrVal];
140 | node.addEventListener( 'click', fn.bind(this.$vm));
141 | }
142 |
143 | zDir_model( node, value ){
144 | const vm = this.$vm;
145 | this.updaterAll( 'model', node, node.value );
146 | node.addEventListener("input", e => {
147 | vm[value] = e.target.value;
148 | });
149 | }
150 |
151 | zDir_html( node, value ){
152 | this.updaterHtml( node, this.$vm[value] );
153 | }
154 |
155 | updaterHtml( node, value ){
156 | node.innerHTML = value;
157 | }
158 |
159 | compileText( node ){
160 | if( typeof( node.textContent ) !== 'string' ) {
161 | return "";
162 | }
163 | const reg = /({{(.*)}})/;
164 | const reg2 = /[^/{/}]+/;
165 | const key = String((node.textContent).match(reg)).match(reg2);//获取监听的key
166 | this.updaterAll( 'text', node, key );
167 | }
168 |
169 | updaterAll( type, node, key ) {
170 | switch( type ){
171 | case 'text':
172 | if( key ){
173 | const updater = this.updateText;
174 | const initVal = node.textContent;//记录原文本第一次的数据
175 | updater( node, this.$vm[key], initVal);
176 | new Watcher( this.$vm, key, initVal, function( value, initVal ){
177 | updater( node, value, initVal );
178 | });
179 | }
180 | break;
181 | case 'model':
182 | const updater = this.updateModel;
183 | new Watcher( this.$vm, key, null, function( value, initVal ){
184 | updater( node, value );
185 | });
186 | break;
187 | }
188 | }
189 |
190 | updateModel( node, value ){
191 | node.value = value;
192 | }
193 |
194 | updateText( node, value, initVal ){
195 | var reg = /{{(.*)}}/ig;
196 | var replaceStr = String( initVal.match(reg) );
197 | var result = initVal.replace(replaceStr, value );
198 | node.textContent = result;
199 | }
200 |
201 | }
202 |
203 | class Watcher{
204 |
205 | constructor( vm, key, initVal, cb ){
206 | this.vm = vm;
207 | this.key = key;
208 | this.cb = cb;
209 | this.initVal = initVal;
210 | Dep.target = this;
211 | this.vm[this.key];
212 | Dep.target = null;
213 | }
214 |
215 | update(){
216 | this.cb.call( this.vm, this.vm[this.key], this.initVal );
217 | }
218 |
219 | }
220 |
--------------------------------------------------------------------------------
/(1) zVue(简版vue源码)/3.0/zVue.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | z手写vue源码
7 |
8 |
9 |
10 |
11 |
14 |
15 |
姓名:{{name}}
16 |
{{content}}
17 |
18 |
19 |
20 |
21 |
22 |
61 |
62 |
72 |
73 |
74 |
欢迎访问主页
75 |
78 |
81 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/(1) zVue(简版vue源码)/3.0/zVue.js:
--------------------------------------------------------------------------------
1 | /*
2 | 本代码来自weizhan
3 | github链接:https://github.com/zhuangweizhan
4 | csdn链接:https://blog.csdn.net/zhuangweizhan/
5 | */
6 | class zVue {
7 | constructor(options){
8 | this.$options = options;
9 | this.$data = options.data;
10 | this.$el = options.el;
11 | this.$binding = {};//替换原来的dep
12 | this.proxyData( this.$data );//添加observer监听
13 | new zCompile( options.el, this);//添加文档解析
14 | }
15 |
16 | pushWatch( watcher ){
17 | if( !this.$binding[watcher.key] ){
18 | this.$binding[watcher.key] = [];
19 | }
20 | this.$binding[watcher.key].push(watcher);
21 | }
22 |
23 | proxyData( data ){//监听data数据,双向绑定
24 | if( !data || typeof(data) !== 'object'){
25 | return;
26 | }
27 | const _this = this;
28 | const handler = {
29 | set( target, key, value ) {
30 | const rest = Reflect.set(target, key, value);
31 | _this.$binding[key].map( item => {
32 | item.update();
33 | })
34 | return rest;
35 | }
36 | }
37 | this.$data = new Proxy( data, handler );
38 | }
39 |
40 | }
41 |
42 | //个人编译器
43 | class zCompile{
44 | constructor(el, vm){
45 | this.$el = document.querySelector(el);
46 |
47 | this.$vm = vm;
48 | if (this.$el) {
49 | this.$fragment = this.getNodeChirdren( this.$el );
50 | this.compile( this.$fragment);
51 | this.$el.appendChild(this.$fragment);
52 | }
53 | }
54 |
55 | getNodeChirdren(el){
56 | const frag = document.createDocumentFragment();
57 |
58 | let child;
59 | while( (child = el.firstChild )){
60 | frag.appendChild( child );
61 | }
62 | return frag;
63 | }
64 |
65 | compile( el ){
66 | const childNodes = el.childNodes;
67 | Array.from(childNodes).forEach( node => {
68 | if( node.nodeType == 1 ) {//1为元素节点
69 | const nodeAttrs = node.attributes;
70 | Array.from(nodeAttrs).forEach( attr => {
71 | const attrName = attr.name;//属性名称
72 | const attrVal = attr.value;//属性值
73 | if( attrName.slice(0,2) === 'z-' ){
74 | var tagName = attrName.substring(2);
75 | switch( tagName ){
76 | case "model":
77 | this.zDir_model( node, attrVal );
78 | break;
79 | case "html":
80 | this.zDir_html( node, attrVal );
81 | break;
82 | }
83 | }
84 | if( attrName.slice(0,1) === '@' ){
85 | var tagName = attrName.substring(1);
86 | this.zDir_click( node, attrVal );
87 | }
88 | })
89 | } else if( node.nodeType == 2 ){//2为属性节点
90 | } else if( node.nodeType == 3 ){//3为文本节点
91 | this.compileText( node );
92 | }
93 |
94 | // 递归子节点
95 | if (node.childNodes && node.childNodes.length > 0) {
96 | this.compile(node);
97 | }
98 | })
99 | }
100 |
101 | zDir_click(node, attrVal){
102 | var fn = this.$vm.$options.methods[attrVal];
103 | node.addEventListener( 'click', fn.bind(this.$vm));
104 | }
105 |
106 | zDir_model( node, value ){
107 | const vm = this.$vm;
108 | this.updaterAll( 'model', node, node.value );
109 | node.addEventListener("input", e => {
110 | vm.$data[value] = e.target.value;
111 | });
112 | }
113 |
114 | zDir_html( node, value ){
115 | this.updaterHtml( node, this.$vm[value] );
116 | }
117 |
118 | updaterHtml( node, value ){
119 | node.innerHTML = value;
120 | }
121 |
122 | compileText( node ){
123 | if( typeof( node.textContent ) !== 'string' ) {
124 | return "";
125 | }
126 | const reg = /({{(.*)}})/;
127 | const reg2 = /[^/{/}]+/;
128 | const key = String((node.textContent).match(reg)).match(reg2);//获取监听的key
129 | this.updaterAll( 'text', node, key );
130 | }
131 |
132 | updaterAll( type, node, key ) {
133 | switch( type ){
134 | case 'text':
135 | if( key ){
136 | const updater = this.updateText;
137 | const initVal = node.textContent;//记录原文本第一次的数据
138 | updater( node, this.$vm.$data[key], initVal);
139 | this.$vm.pushWatch(
140 | new Watcher( this.$vm, key, initVal, function( value, initVal ){
141 | updater( node, value, initVal );
142 | })
143 | );
144 | }
145 | break;
146 | case 'model':
147 | const updater = this.updateModel;
148 | this.$vm.pushWatch(
149 | new Watcher( this.$vm, key, null, function( value, initVal ){
150 | updater( node, value );
151 | })
152 | );
153 | break;
154 | }
155 | }
156 |
157 | updateModel( node, value ){
158 | node.value = value;
159 | }
160 |
161 | updateText( node, value, initVal ){
162 | var reg = /{{(.*)}}/ig;
163 | var replaceStr = String( initVal.match(reg) );
164 | var result = initVal.replace(replaceStr, value );
165 | node.textContent = result;
166 | }
167 |
168 | }
169 |
170 | class Watcher{
171 |
172 | constructor( vm, key, initVal, cb ){
173 | this.vm = vm;
174 | this.key = key;
175 | this.cb = cb;
176 | this.initVal = initVal;
177 | }
178 |
179 | update(){
180 | this.cb.call( this.vm, this.vm.$data[this.key], this.initVal );
181 | }
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/(2) zReact(简版react源码)/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zwz_react_origin",
3 | "scripts": {
4 | "start": "react-scripts start"
5 | },
6 | "version": "0.1.0",
7 | "private": true,
8 | "dependencies": {
9 | "react-scripts": "3.4.1"
10 | },
11 | "browserslist": {
12 | "production": [
13 | ">0.2%",
14 | "not dead",
15 | "not op_mini all"
16 | ],
17 | "development": [
18 | "last 1 chrome version",
19 | "last 1 firefox version",
20 | "last 1 safari version"
21 | ]
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/(2) zReact(简版react源码)/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
欢迎访问主页
10 |
13 |
16 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/(2) zReact(简版react源码)/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "./wzReact/";
2 | import ReactDOM from "./wzReact/ReactDOM";
3 |
4 | class MyClassCmp extends React.Component {
5 |
6 | constructor(props) {
7 | super(props);
8 | }
9 |
10 | render() {
11 | return (
12 | MyClassCmp表示:{this.props.name}
13 | );
14 | }
15 |
16 | }
17 |
18 | function MyFuncCmp(props) {
19 | return MyFuncCmp表示:{props.name}
;
20 | }
21 |
22 |
23 | let jsx = (
24 |
25 |
你好
26 |
前端小伙子
27 |
28 |
29 |
30 | );
31 |
32 |
33 | ReactDOM.render(jsx, document.getElementById("root"));
34 |
--------------------------------------------------------------------------------
/(2) zReact(简版react源码)/src/wzReact/ReactDOM.js:
--------------------------------------------------------------------------------
1 | function render(vnode, container) {
2 | console.log("render", vnode);
3 | //vnode-> node
4 | mount(vnode, container);
5 | // container.appendChild(node)
6 | }
7 | // vnode-> node
8 | function mount(vnode, container) {
9 | const { vtype } = vnode;
10 | if (!vtype) {
11 | mountTextNode(vnode, container); //处理文本节点
12 | }
13 | if (vtype === 1) {
14 | mountHtml(vnode, container); //处理原生标签
15 | }
16 |
17 | if (vtype === 3) {
18 | //处理函数组件
19 | mountFunc(vnode, container);
20 | }
21 |
22 | if (vtype === 2) {
23 | //处理class组件
24 | mountClass(vnode, container);
25 | }
26 | }
27 |
28 | //处理文本节点
29 | function mountTextNode(vnode, container) {
30 | const node = document.createTextNode(vnode);
31 | container.appendChild(node);
32 | }
33 |
34 | //处理原生标签
35 | function mountHtml(vnode, container) {
36 | const { type, props } = vnode;
37 | const node = document.createElement(type);
38 |
39 | const { children, ...rest } = props;
40 | children.map(item => {
41 | if (Array.isArray(item)) {
42 | item.map(c => {
43 | mount(c, node);
44 | });
45 | } else {
46 | mount(item, node);
47 | }
48 | });
49 |
50 | Object.keys(rest).map(item => {
51 | if (item === "className") {
52 | node.setAttribute("class", rest[item]);
53 | }
54 | if (item.slice(0, 2) === "on") {
55 | node.addEventListener("click", rest[item]);
56 | }
57 | });
58 |
59 | container.appendChild(node);
60 | }
61 |
62 | function mountFunc(vnode, container) {
63 | const { type, props } = vnode;
64 | const node = new type(props);
65 | mount(node, container);
66 | }
67 |
68 | function mountClass(vnode, container) {
69 | const { type, props } = vnode;
70 | const cmp = new type(props);
71 | const node = cmp.render();
72 | mount(node, container);
73 | }
74 |
75 | export default {
76 | render,
77 | };
78 |
--------------------------------------------------------------------------------
/(2) zReact(简版react源码)/src/wzReact/index.js:
--------------------------------------------------------------------------------
1 | function createElement(type, props, ...children) {
2 | console.log("createElement", arguments);
3 | props.children = children;
4 | let vtype;
5 | if (typeof type === "string") {
6 | vtype = 1;
7 | }
8 | if (typeof type === "function") {
9 | vtype = type.isReactComponent ? 2 : 3;
10 | }
11 | return {
12 | vtype,
13 | type,
14 | props,
15 | };
16 | }
17 |
18 | class Component {
19 | static isReactComponent = true;
20 | constructor(props) {
21 | this.props = props;
22 | this.state = {};
23 | }
24 | setState = () => {};
25 | }
26 |
27 | export default {
28 | Component,
29 | createElement,
30 | };
31 |
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/bin/index.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | const config = require(path.resolve('webpack.config.js'))
4 | const WebpackCompiler = require('../lib/WebpackCompiler.js')
5 |
6 | const webpackCompiler = new WebpackCompiler(config)
7 | webpackCompiler.run();
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/bin/main.47340442.js:
--------------------------------------------------------------------------------
1 | (function (modules) {
2 | var installedModules = {};
3 |
4 | function __webpack_require__(moduleId) {
5 |
6 | if (installedModules[moduleId]) {
7 | return installedModules[moduleId].exports;
8 | }
9 | var module = installedModules[moduleId] = {
10 | i: moduleId,
11 | l: false,
12 | exports: {}
13 | };
14 |
15 | modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
16 |
17 | module.l = true;
18 |
19 | return module.exports;
20 | }
21 |
22 |
23 | // Load entry module and return exports
24 | return __webpack_require__(__webpack_require__.s = "./src\index.js");
25 | })({
26 |
27 | "./src\index.js":
28 | (function (module, exports,__webpack_require__) {
29 | eval(`const a = __webpack_require__("./src\\index2.js");
30 |
31 | alert("a=" + JSON.stringify(a)); // require("./test.css");
32 |
33 | __webpack_require__("./src\\test.less");
34 |
35 | module.exports = {
36 | name: "aaa"
37 | };`);
38 | }),
39 |
40 | "./src\index2.js":
41 | (function (module, exports,__webpack_require__) {
42 | eval(`alert("hello word 2");
43 | module.exports = {
44 | a: 5
45 | };`);
46 | }),
47 |
48 | "./src\test.less":
49 | (function (module, exports,__webpack_require__) {
50 | eval(`let style = document.createElement('style');
51 | style.innerHTML = ".a {\\n font-size: 1px;\\n}\\n.a .b {\\n font-size: 2px;\\n}\\n";
52 | document.head.appendChild(style);`);
53 | }),
54 |
55 | });
56 |
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 个人webpack
6 |
7 |
8 |
9 |
10 |
11 |
欢迎小伙子小姑凉!
12 |
13 |
14 |
15 |
16 |
19 |
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/dist/main.71360163.js:
--------------------------------------------------------------------------------
1 | (function (modules) {
2 | var installedModules = {};
3 |
4 | function __webpack_require__(moduleId) {
5 |
6 | if (installedModules[moduleId]) {
7 | return installedModules[moduleId].exports;
8 | }
9 | var module = installedModules[moduleId] = {
10 | i: moduleId,
11 | l: false,
12 | exports: {}
13 | };
14 |
15 | modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
16 |
17 | module.l = true;
18 |
19 | return module.exports;
20 | }
21 |
22 |
23 | // Load entry module and return exports
24 | return __webpack_require__(__webpack_require__.s = "./src\index.js");
25 | })
26 |
27 |
28 | ({
29 |
30 | "./src\index.js":
31 | (function (module, exports,__webpack_require__) {
32 | eval(`__webpack_require__("./src\\test.less");
33 |
34 | const index2Obj = __webpack_require__("./src\\index2.js");
35 |
36 | alert("index文件告诉你:小伙子很帅");
37 | alert("index2文件告诉你:" + index2Obj.value);
38 | module.exports = {};`);
39 | }),
40 |
41 | "./src\test.less":
42 | (function (module, exports,__webpack_require__) {
43 | eval(`let style = document.createElement('style');
44 | style.innerHTML = "body {\\n text-align: center;\\n}\\nbody .my_page {\\n margin-top: 50px;\\n line-height: 50px;\\n}\\n";
45 | document.head.appendChild(style);`);
46 | }),
47 |
48 | "./src\index2.js":
49 | (function (module, exports,__webpack_require__) {
50 | eval(`module.exports = {
51 | value: '小姑凉也很赞!'
52 | };`);
53 | }),
54 |
55 | });
56 |
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/lib/WebpackCompiler.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const fs = require('fs')
3 | const { assert } = require('console')
4 | // babylon 将源码转成ast Babylon 是 Babel 中使用的 JavaScript 解析器。
5 | // @babel/traverse 对ast解析遍历语法树
6 | // @babel/types 用于AST节点的Lodash-esque实用程序库
7 | // @babel/generator 结果生成
8 |
9 | const babylon = require('babylon')
10 | const traverse = require('@babel/traverse').default;
11 | const type = require('@babel/types');
12 | const generator = require('@babel/generator').default
13 | const ejs = require('ejs')
14 | const tapable = require('tapable')
15 |
16 | class WebpackCompiler {
17 | constructor(config) {
18 | this.config = config
19 | this.modules = {}
20 | this.root = process.cwd() //当前项目地址
21 | this.entryPath = './' + path.relative(this.root, this.config.entry);
22 | this.hooks = {
23 | entryInit: new tapable.SyncHook(),
24 | beforeCompile: new tapable.SyncHook(),
25 | afterCompile: new tapable.SyncHook(),
26 | afterPlugins: new tapable.SyncHook(),
27 | afteremit: new tapable.SyncWaterfallHook(['hash']),
28 | }
29 | const plugins = this.config.plugins
30 | if (Array.isArray(plugins)) {
31 | plugins.forEach(item => {
32 | // 每个均是实例,调用实例上的一个方法即可,传入当前Compiler实例
33 | item.run(this)
34 | })
35 | }
36 |
37 | }
38 |
39 | // 获取源码
40 | getSourceByPath(modulePath) {
41 | // 事先拿module中的匹配规则与路径进行匹配
42 | const rules = this.config.module.rules
43 | let content = fs.readFileSync(modulePath, 'utf8')
44 | for (let i = 0; i < rules.length; i++) {
45 | let { test, use } = rules[i]
46 | let len = use.length
47 |
48 | // 匹配到了开始走loader,特点从后往前
49 | if (test.test(modulePath)) {
50 | function changeLoader() {
51 | // 先拿最后一个
52 | let loader = require(use[--len])
53 | content = loader(content)
54 | if (len > 0) {
55 | changeLoader()
56 | }
57 | }
58 | changeLoader()
59 | }
60 | }
61 | return content
62 | }
63 |
64 | // 根据路径解析源码
65 | parse(source, parentPath) {
66 | let ast = babylon.parse(source)//
67 | // 用于存取依赖
68 | let dependencies = []
69 | traverse(ast, {//对ast解析遍历语法树 负责替换,删除和添加节点
70 | CallExpression(p) {
71 | let node = p.node
72 | if (node.callee.name === 'require') {
73 | node.callee.name = '__webpack_require__';//将require替换成__webpack_require__
74 | const moduledName = './' + path.join(parentPath, node.arguments[0].value )
75 | dependencies.push(moduledName);//记录包含的requeir的名称,后边需要遍历替换成源码
76 | node.arguments = [type.stringLiteral(moduledName)] // 源码替换
77 | }
78 | }
79 | })
80 | let sourceCode = generator(ast).code
81 | return { sourceCode, dependencies };
82 | }
83 |
84 | // 构建模块
85 | buildMoudle(modulePath) {
86 | const source = this.getSourceByPath(modulePath);//根据路径拿到源码
87 | const moduleName = './' + path.relative(this.root, modulePath);//转换一下路径名称
88 | const { sourceCode, dependencies } = this.parse(source, path.dirname(moduleName))//根据路径拿到源码,以及源码中已经require的文件名称数组
89 | this.modules[moduleName] = sourceCode;// 每个模块的代码都通过路径为Key,存入到modules对象中
90 | dependencies.forEach(item => { // 递归需要转换的文件名称
91 | this.buildMoudle(path.resolve(this.root, item));////再对应的文件名称,替换成对应的源码
92 | })
93 | }
94 |
95 | //输出文件
96 | outputFile() {
97 | let templateStr = this.getSourceByPath(path.join(__dirname, 'main.ejs')); // 拿到步骤1写好的模板
98 | let code = ejs.render(templateStr, {
99 | entryPath: this.entryPath,
100 | modules: this.modules,
101 | })// 填充模板数据
102 | let outPath = path.join(this.config.output.path, this.config.output.filename)// 拿到输出地址
103 | fs.writeFileSync(outPath, code )// 写入
104 | }
105 |
106 | run() {
107 | this.hooks.entryInit.call(); //启动项目
108 | this.hooks.beforeCompile.call(); //编译前运行
109 | this.buildMoudle( this.entryPath )
110 | this.hooks.afterCompile.call( ); //编译后运行
111 | this.outputFile();
112 | this.hooks.afterPlugins.call( );//执行完plugins后运行
113 | this.hooks.afteremit.call( );//结束后运行
114 | }
115 |
116 | }
117 |
118 | module.exports = WebpackCompiler;
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/lib/comTest.js:
--------------------------------------------------------------------------------
1 |
2 | class Compiler {
3 |
4 | constructor(config) {
5 | this.config = config
6 | }
7 |
8 | }
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/lib/loader/less-loader.js:
--------------------------------------------------------------------------------
1 | const less = require('less')
2 |
3 | function loader(source) {
4 | let css = ''
5 | less.render(source, function(err, output) {
6 | css = output.css
7 | })
8 |
9 | css = css.replace(/\n/g, '\\n')
10 | let style = `
11 | let style = document.createElement('style')
12 | style.innerHTML = \n${JSON.stringify(css)}
13 | document.head.appendChild(style)
14 | `
15 | return style
16 | }
17 | module.exports = loader;
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/lib/loader/style-loader.js:
--------------------------------------------------------------------------------
1 | function loader(source) {
2 | let style = `
3 | let style = document.createElement('style')
4 | style.innerHTML = \n${JSON.stringify(source)}
5 | document.head.appendChild(style)
6 | `
7 | return style
8 | }
9 | module.exports = loader;
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/lib/main.ejs:
--------------------------------------------------------------------------------
1 | (function (modules) {
2 | var installedModules = {};
3 |
4 | function __webpack_require__(moduleId) {
5 |
6 | if (installedModules[moduleId]) {
7 | return installedModules[moduleId].exports;
8 | }
9 | var module = installedModules[moduleId] = {
10 | i: moduleId,
11 | l: false,
12 | exports: {}
13 | };
14 |
15 | modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
16 |
17 | module.l = true;
18 |
19 | return module.exports;
20 | }
21 |
22 |
23 | // Load entry module and return exports
24 | return __webpack_require__(__webpack_require__.s = "<%-entryPath %>");
25 | })
26 |
27 |
28 | ({
29 | <% for(let key in modules){ %>
30 | "<%- key %>":
31 | (function (module, exports,__webpack_require__) {
32 | eval(`<%-modules[key] %>`);
33 | }),
34 | <% } %>
35 | });
36 |
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/lib/utils.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require('path')
3 |
4 |
5 | function delFileFolderByName(url) {
6 | var files = [];
7 | /**
8 | * 判断给定的路径是否存在
9 | */
10 | if (fs.existsSync(url)) {
11 | /**
12 | * 返回文件和子目录的数组
13 | */
14 | files = fs.readdirSync(url);
15 | files.forEach(function (file, index) {
16 |
17 | var curPath = path.join(url, file);
18 | /**
19 | * fs.statSync同步读取文件夹文件,如果是文件夹,在重复触发函数
20 | */
21 | if (fs.statSync(curPath).isDirectory()) { // recurse
22 | delFileFolderByName(curPath);
23 | } else {
24 | fs.unlinkSync(curPath);
25 | }
26 | });
27 | /**
28 | * 清除文件夹
29 | */
30 | // fs.rmdirSync(url);
31 | } else {
32 | console.log("给定的路径不存在,请给出正确的路径");
33 | }
34 | }
35 |
36 | function delFileByName( url ){
37 | var curPath = path.join(url);
38 | fs.unlinkSync(curPath);
39 | }
40 |
41 | module.exports = {
42 | delFileFolderByName,
43 | delFileByName,
44 | }
45 |
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zwzpack",
3 | "version": "0.1.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@babel/code-frame": {
8 | "version": "7.10.4",
9 | "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.10.4.tgz?cache=0&sync_timestamp=1593522948158&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.10.4.tgz",
10 | "integrity": "sha1-Fo2ho26Q2miujUnA8bSMfGJJITo=",
11 | "requires": {
12 | "@babel/highlight": "^7.10.4"
13 | }
14 | },
15 | "@babel/generator": {
16 | "version": "7.10.5",
17 | "resolved": "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.10.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fgenerator%2Fdownload%2F%40babel%2Fgenerator-7.10.5.tgz",
18 | "integrity": "sha1-G5A1VLyMWD7o0l8eiWlzLmuCmmk=",
19 | "requires": {
20 | "@babel/types": "^7.10.5",
21 | "jsesc": "^2.5.1",
22 | "source-map": "^0.5.0"
23 | }
24 | },
25 | "@babel/helper-function-name": {
26 | "version": "7.10.4",
27 | "resolved": "https://registry.npm.taobao.org/@babel/helper-function-name/download/@babel/helper-function-name-7.10.4.tgz?cache=0&sync_timestamp=1593522977138&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-function-name%2Fdownload%2F%40babel%2Fhelper-function-name-7.10.4.tgz",
28 | "integrity": "sha1-0tOyDFmtjEcRL6fSqUvAnV74Lxo=",
29 | "requires": {
30 | "@babel/helper-get-function-arity": "^7.10.4",
31 | "@babel/template": "^7.10.4",
32 | "@babel/types": "^7.10.4"
33 | }
34 | },
35 | "@babel/helper-get-function-arity": {
36 | "version": "7.10.4",
37 | "resolved": "https://registry.npm.taobao.org/@babel/helper-get-function-arity/download/@babel/helper-get-function-arity-7.10.4.tgz?cache=0&sync_timestamp=1593521294451&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-get-function-arity%2Fdownload%2F%40babel%2Fhelper-get-function-arity-7.10.4.tgz",
38 | "integrity": "sha1-mMHL6g4jMvM/mkZhuM4VBbLBm6I=",
39 | "requires": {
40 | "@babel/types": "^7.10.4"
41 | }
42 | },
43 | "@babel/helper-split-export-declaration": {
44 | "version": "7.10.4",
45 | "resolved": "https://registry.npm.taobao.org/@babel/helper-split-export-declaration/download/@babel/helper-split-export-declaration-7.10.4.tgz?cache=0&sync_timestamp=1593522967620&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-split-export-declaration%2Fdownload%2F%40babel%2Fhelper-split-export-declaration-7.10.4.tgz",
46 | "integrity": "sha1-LHBXbqo7VgmyTLmdsoiMw/xCUdE=",
47 | "requires": {
48 | "@babel/types": "^7.10.4"
49 | }
50 | },
51 | "@babel/helper-validator-identifier": {
52 | "version": "7.10.4",
53 | "resolved": "https://registry.npm.taobao.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.10.4.tgz?cache=0&sync_timestamp=1593521083613&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-validator-identifier%2Fdownload%2F%40babel%2Fhelper-validator-identifier-7.10.4.tgz",
54 | "integrity": "sha1-p4x6clHgH2FlEtMbEK3PUq2l4NI="
55 | },
56 | "@babel/highlight": {
57 | "version": "7.10.4",
58 | "resolved": "https://registry.npm.taobao.org/@babel/highlight/download/@babel/highlight-7.10.4.tgz?cache=0&sync_timestamp=1593521095576&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhighlight%2Fdownload%2F%40babel%2Fhighlight-7.10.4.tgz",
59 | "integrity": "sha1-fRvf1ldTU4+r5sOFls23bZrGAUM=",
60 | "requires": {
61 | "@babel/helper-validator-identifier": "^7.10.4",
62 | "chalk": "^2.0.0",
63 | "js-tokens": "^4.0.0"
64 | }
65 | },
66 | "@babel/parser": {
67 | "version": "7.10.5",
68 | "resolved": "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.10.5.tgz?cache=0&sync_timestamp=1594750823758&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.10.5.tgz",
69 | "integrity": "sha1-58a/Wn3v+VfOyfBLVR4nYpCdgms="
70 | },
71 | "@babel/template": {
72 | "version": "7.10.4",
73 | "resolved": "https://registry.npm.taobao.org/@babel/template/download/@babel/template-7.10.4.tgz",
74 | "integrity": "sha1-MlGZbEIA68cdGo/EBfupQPNrong=",
75 | "requires": {
76 | "@babel/code-frame": "^7.10.4",
77 | "@babel/parser": "^7.10.4",
78 | "@babel/types": "^7.10.4"
79 | }
80 | },
81 | "@babel/traverse": {
82 | "version": "7.10.5",
83 | "resolved": "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.10.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftraverse%2Fdownload%2F%40babel%2Ftraverse-7.10.5.tgz",
84 | "integrity": "sha1-d85GT1sli+Jlr2GNj93wU28gtWQ=",
85 | "requires": {
86 | "@babel/code-frame": "^7.10.4",
87 | "@babel/generator": "^7.10.5",
88 | "@babel/helper-function-name": "^7.10.4",
89 | "@babel/helper-split-export-declaration": "^7.10.4",
90 | "@babel/parser": "^7.10.5",
91 | "@babel/types": "^7.10.5",
92 | "debug": "^4.1.0",
93 | "globals": "^11.1.0",
94 | "lodash": "^4.17.19"
95 | }
96 | },
97 | "@babel/types": {
98 | "version": "7.10.5",
99 | "resolved": "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.10.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.10.5.tgz",
100 | "integrity": "sha1-2Irn4v3oa/v+hR1Nga+nCpl7XRU=",
101 | "requires": {
102 | "@babel/helper-validator-identifier": "^7.10.4",
103 | "lodash": "^4.17.19",
104 | "to-fast-properties": "^2.0.0"
105 | }
106 | },
107 | "@types/json-schema": {
108 | "version": "7.0.5",
109 | "resolved": "https://registry.npm.taobao.org/@types/json-schema/download/@types/json-schema-7.0.5.tgz",
110 | "integrity": "sha1-3M5EMOZLRDuolF8CkPtWStW6xt0="
111 | },
112 | "ajv": {
113 | "version": "6.12.3",
114 | "resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.3.tgz?cache=0&sync_timestamp=1593876933357&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.3.tgz",
115 | "integrity": "sha1-GMWvOKER3etPJpe9eNaKvByr1wY=",
116 | "requires": {
117 | "fast-deep-equal": "^3.1.1",
118 | "fast-json-stable-stringify": "^2.0.0",
119 | "json-schema-traverse": "^0.4.1",
120 | "uri-js": "^4.2.2"
121 | }
122 | },
123 | "ajv-keywords": {
124 | "version": "3.5.1",
125 | "resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.1.tgz?cache=0&sync_timestamp=1594153583457&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.1.tgz",
126 | "integrity": "sha1-uDyonF1C1pAx9CTK1JqtoCNsaVc="
127 | },
128 | "ansi-styles": {
129 | "version": "3.2.1",
130 | "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz",
131 | "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
132 | "requires": {
133 | "color-convert": "^1.9.0"
134 | }
135 | },
136 | "async": {
137 | "version": "0.9.2",
138 | "resolved": "https://registry.npm.taobao.org/async/download/async-0.9.2.tgz?cache=0&sync_timestamp=1582540512270&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fasync%2Fdownload%2Fasync-0.9.2.tgz",
139 | "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
140 | },
141 | "babylon": {
142 | "version": "6.18.0",
143 | "resolved": "https://registry.npm.taobao.org/babylon/download/babylon-6.18.0.tgz",
144 | "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM="
145 | },
146 | "balanced-match": {
147 | "version": "1.0.0",
148 | "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz",
149 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
150 | },
151 | "big.js": {
152 | "version": "5.2.2",
153 | "resolved": "https://registry.npm.taobao.org/big.js/download/big.js-5.2.2.tgz",
154 | "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg="
155 | },
156 | "brace-expansion": {
157 | "version": "1.1.11",
158 | "resolved": "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz",
159 | "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
160 | "requires": {
161 | "balanced-match": "^1.0.0",
162 | "concat-map": "0.0.1"
163 | }
164 | },
165 | "chalk": {
166 | "version": "2.4.2",
167 | "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz",
168 | "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=",
169 | "requires": {
170 | "ansi-styles": "^3.2.1",
171 | "escape-string-regexp": "^1.0.5",
172 | "supports-color": "^5.3.0"
173 | }
174 | },
175 | "clone": {
176 | "version": "2.1.2",
177 | "resolved": "https://registry.npm.taobao.org/clone/download/clone-2.1.2.tgz",
178 | "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
179 | },
180 | "color-convert": {
181 | "version": "1.9.3",
182 | "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz?cache=0&sync_timestamp=1566248870121&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcolor-convert%2Fdownload%2Fcolor-convert-1.9.3.tgz",
183 | "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=",
184 | "requires": {
185 | "color-name": "1.1.3"
186 | }
187 | },
188 | "color-name": {
189 | "version": "1.1.3",
190 | "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz",
191 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
192 | },
193 | "concat-map": {
194 | "version": "0.0.1",
195 | "resolved": "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz",
196 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
197 | },
198 | "debug": {
199 | "version": "4.1.1",
200 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz?cache=0&sync_timestamp=1589891993007&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.1.1.tgz",
201 | "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=",
202 | "requires": {
203 | "ms": "^2.1.1"
204 | }
205 | },
206 | "ejs": {
207 | "version": "3.1.3",
208 | "resolved": "https://registry.npm.taobao.org/ejs/download/ejs-3.1.3.tgz",
209 | "integrity": "sha1-UU2WeoiUCE0Y09R70WmhwFYPCT0=",
210 | "requires": {
211 | "jake": "^10.6.1"
212 | }
213 | },
214 | "emojis-list": {
215 | "version": "3.0.0",
216 | "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz",
217 | "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang="
218 | },
219 | "errno": {
220 | "version": "0.1.7",
221 | "resolved": "https://registry.npm.taobao.org/errno/download/errno-0.1.7.tgz",
222 | "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=",
223 | "optional": true,
224 | "requires": {
225 | "prr": "~1.0.1"
226 | }
227 | },
228 | "escape-string-regexp": {
229 | "version": "1.0.5",
230 | "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz",
231 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
232 | },
233 | "fast-deep-equal": {
234 | "version": "3.1.3",
235 | "resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz",
236 | "integrity": "sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU="
237 | },
238 | "fast-json-stable-stringify": {
239 | "version": "2.1.0",
240 | "resolved": "https://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz?cache=0&sync_timestamp=1576340291001&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-json-stable-stringify%2Fdownload%2Ffast-json-stable-stringify-2.1.0.tgz",
241 | "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM="
242 | },
243 | "filelist": {
244 | "version": "1.0.1",
245 | "resolved": "https://registry.npm.taobao.org/filelist/download/filelist-1.0.1.tgz",
246 | "integrity": "sha1-8Q0aOuhsFpSAjo8gkG9D1MkTLbs=",
247 | "requires": {
248 | "minimatch": "^3.0.4"
249 | }
250 | },
251 | "globals": {
252 | "version": "11.12.0",
253 | "resolved": "https://registry.npm.taobao.org/globals/download/globals-11.12.0.tgz?cache=0&sync_timestamp=1591426414289&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglobals%2Fdownload%2Fglobals-11.12.0.tgz",
254 | "integrity": "sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4="
255 | },
256 | "graceful-fs": {
257 | "version": "4.2.4",
258 | "resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz?cache=0&sync_timestamp=1589682809142&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.4.tgz",
259 | "integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs=",
260 | "optional": true
261 | },
262 | "has-flag": {
263 | "version": "3.0.0",
264 | "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz",
265 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
266 | },
267 | "image-size": {
268 | "version": "0.5.5",
269 | "resolved": "https://registry.npm.taobao.org/image-size/download/image-size-0.5.5.tgz",
270 | "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
271 | "optional": true
272 | },
273 | "inherits": {
274 | "version": "2.0.3",
275 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz?cache=0&sync_timestamp=1560975547815&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finherits%2Fdownload%2Finherits-2.0.3.tgz",
276 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
277 | },
278 | "jake": {
279 | "version": "10.8.2",
280 | "resolved": "https://registry.npm.taobao.org/jake/download/jake-10.8.2.tgz",
281 | "integrity": "sha1-68nehVgWCmbYLQ6txqLlj7xQCns=",
282 | "requires": {
283 | "async": "0.9.x",
284 | "chalk": "^2.4.2",
285 | "filelist": "^1.0.1",
286 | "minimatch": "^3.0.4"
287 | }
288 | },
289 | "js-tokens": {
290 | "version": "4.0.0",
291 | "resolved": "https://registry.npm.taobao.org/js-tokens/download/js-tokens-4.0.0.tgz",
292 | "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk="
293 | },
294 | "jsesc": {
295 | "version": "2.5.2",
296 | "resolved": "https://registry.npm.taobao.org/jsesc/download/jsesc-2.5.2.tgz",
297 | "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q="
298 | },
299 | "json-schema-traverse": {
300 | "version": "0.4.1",
301 | "resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz",
302 | "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA="
303 | },
304 | "json5": {
305 | "version": "2.1.3",
306 | "resolved": "https://registry.npm.taobao.org/json5/download/json5-2.1.3.tgz",
307 | "integrity": "sha1-ybD3+pIzv+WAf+ZvzzpWF+1ZfUM=",
308 | "requires": {
309 | "minimist": "^1.2.5"
310 | }
311 | },
312 | "less": {
313 | "version": "3.12.2",
314 | "resolved": "https://registry.npm.taobao.org/less/download/less-3.12.2.tgz?cache=0&sync_timestamp=1594915586681&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fless%2Fdownload%2Fless-3.12.2.tgz",
315 | "integrity": "sha1-FX5t0ypohp34hZMUrTjnAhGvOrQ=",
316 | "requires": {
317 | "errno": "^0.1.1",
318 | "graceful-fs": "^4.1.2",
319 | "image-size": "~0.5.0",
320 | "make-dir": "^2.1.0",
321 | "mime": "^1.4.1",
322 | "native-request": "^1.0.5",
323 | "source-map": "~0.6.0",
324 | "tslib": "^1.10.0"
325 | },
326 | "dependencies": {
327 | "source-map": {
328 | "version": "0.6.1",
329 | "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
330 | "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
331 | "optional": true
332 | }
333 | }
334 | },
335 | "less-loader": {
336 | "version": "6.2.0",
337 | "resolved": "https://registry.npm.taobao.org/less-loader/download/less-loader-6.2.0.tgz?cache=0&sync_timestamp=1593787670620&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fless-loader%2Fdownload%2Fless-loader-6.2.0.tgz",
338 | "integrity": "sha1-iyb2IcFVs0Lu/CT1vW6dxAxCpxk=",
339 | "requires": {
340 | "clone": "^2.1.2",
341 | "less": "^3.11.3",
342 | "loader-utils": "^2.0.0",
343 | "schema-utils": "^2.7.0"
344 | }
345 | },
346 | "loader-utils": {
347 | "version": "2.0.0",
348 | "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz",
349 | "integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=",
350 | "requires": {
351 | "big.js": "^5.2.2",
352 | "emojis-list": "^3.0.0",
353 | "json5": "^2.1.2"
354 | }
355 | },
356 | "lodash": {
357 | "version": "4.17.19",
358 | "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.19.tgz?cache=0&sync_timestamp=1594226931791&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.19.tgz",
359 | "integrity": "sha1-5I3e2+MLMyF4PFtDAfvTU7weSks="
360 | },
361 | "make-dir": {
362 | "version": "2.1.0",
363 | "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz",
364 | "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=",
365 | "optional": true,
366 | "requires": {
367 | "pify": "^4.0.1",
368 | "semver": "^5.6.0"
369 | }
370 | },
371 | "mime": {
372 | "version": "1.6.0",
373 | "resolved": "https://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz?cache=0&sync_timestamp=1590635592890&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-1.6.0.tgz",
374 | "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=",
375 | "optional": true
376 | },
377 | "minimatch": {
378 | "version": "3.0.4",
379 | "resolved": "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz",
380 | "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
381 | "requires": {
382 | "brace-expansion": "^1.1.7"
383 | }
384 | },
385 | "minimist": {
386 | "version": "1.2.5",
387 | "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1589682820731&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz",
388 | "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI="
389 | },
390 | "ms": {
391 | "version": "2.1.2",
392 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz",
393 | "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
394 | },
395 | "native-request": {
396 | "version": "1.0.7",
397 | "resolved": "https://registry.npm.taobao.org/native-request/download/native-request-1.0.7.tgz?cache=0&sync_timestamp=1595000106410&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnative-request%2Fdownload%2Fnative-request-1.0.7.tgz",
398 | "integrity": "sha1-/3QtxVW0yPLxwUtUhjm6F05XOFY=",
399 | "optional": true
400 | },
401 | "path": {
402 | "version": "0.12.7",
403 | "resolved": "https://registry.npm.taobao.org/path/download/path-0.12.7.tgz",
404 | "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=",
405 | "requires": {
406 | "process": "^0.11.1",
407 | "util": "^0.10.3"
408 | }
409 | },
410 | "pify": {
411 | "version": "4.0.1",
412 | "resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz",
413 | "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=",
414 | "optional": true
415 | },
416 | "process": {
417 | "version": "0.11.10",
418 | "resolved": "https://registry.npm.taobao.org/process/download/process-0.11.10.tgz",
419 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
420 | },
421 | "prr": {
422 | "version": "1.0.1",
423 | "resolved": "https://registry.npm.taobao.org/prr/download/prr-1.0.1.tgz",
424 | "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
425 | "optional": true
426 | },
427 | "punycode": {
428 | "version": "2.1.1",
429 | "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz",
430 | "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew="
431 | },
432 | "schema-utils": {
433 | "version": "2.7.0",
434 | "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.7.0.tgz?cache=0&sync_timestamp=1590789322916&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-2.7.0.tgz",
435 | "integrity": "sha1-FxUfdtjq5n+793lgwzxnatn078c=",
436 | "requires": {
437 | "@types/json-schema": "^7.0.4",
438 | "ajv": "^6.12.2",
439 | "ajv-keywords": "^3.4.1"
440 | }
441 | },
442 | "semver": {
443 | "version": "5.7.1",
444 | "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1589682805026&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz",
445 | "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=",
446 | "optional": true
447 | },
448 | "source-map": {
449 | "version": "0.5.7",
450 | "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz",
451 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
452 | },
453 | "supports-color": {
454 | "version": "5.5.0",
455 | "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-5.5.0.tgz",
456 | "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=",
457 | "requires": {
458 | "has-flag": "^3.0.0"
459 | }
460 | },
461 | "tapable": {
462 | "version": "1.1.3",
463 | "resolved": "https://registry.npm.taobao.org/tapable/download/tapable-1.1.3.tgz",
464 | "integrity": "sha1-ofzMBrWNth/XpF2i2kT186Pme6I="
465 | },
466 | "to-fast-properties": {
467 | "version": "2.0.0",
468 | "resolved": "https://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz?cache=0&sync_timestamp=1580550317222&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fto-fast-properties%2Fdownload%2Fto-fast-properties-2.0.0.tgz",
469 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
470 | },
471 | "tslib": {
472 | "version": "1.13.0",
473 | "resolved": "https://registry.npm.taobao.org/tslib/download/tslib-1.13.0.tgz",
474 | "integrity": "sha1-yIHhPMcBWJTtkUhi0nZDb6mkcEM="
475 | },
476 | "uri-js": {
477 | "version": "4.2.2",
478 | "resolved": "https://registry.npm.taobao.org/uri-js/download/uri-js-4.2.2.tgz",
479 | "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=",
480 | "requires": {
481 | "punycode": "^2.1.0"
482 | }
483 | },
484 | "util": {
485 | "version": "0.10.4",
486 | "resolved": "https://registry.npm.taobao.org/util/download/util-0.10.4.tgz",
487 | "integrity": "sha1-OqASW/5mikZy3liFfTrOJ+y3aQE=",
488 | "requires": {
489 | "inherits": "2.0.3"
490 | }
491 | }
492 | }
493 | }
494 |
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zwzpack",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "node ./bin/index.js"
7 | },
8 | "devDependencies": {},
9 | "dependencies": {
10 | "@babel/generator": "^7.10.5",
11 | "@babel/traverse": "^7.10.5",
12 | "babylon": "^6.18.0",
13 | "ejs": "^3.1.3",
14 | "less-loader": "^6.2.0",
15 | "path": "^0.12.7",
16 | "tapable": "^1.1.3"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 个人webpack
6 |
7 |
8 |
9 |
10 |
11 |
欢迎小伙子小姑凉!
12 |
13 |
14 |
15 |
16 |
19 |
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/src/index.js:
--------------------------------------------------------------------------------
1 |
2 | require("./test.less");
3 |
4 | const index2Obj = require("./index2.js");
5 | alert("index文件告诉你:小伙子很帅" );
6 | alert("index2文件告诉你:" + index2Obj.value );
7 |
8 |
9 | module.exports = {}
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/src/index2.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | module.exports = { value: '小姑凉也很赞!'}
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/src/test.css:
--------------------------------------------------------------------------------
1 | body{
2 | text-align: center;
3 | }
4 | .my_page{
5 | margin-top: 50px;
6 | line-height: 50px;
7 | }
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/src/test.less:
--------------------------------------------------------------------------------
1 | body{
2 | text-align: center;
3 | .my_page{
4 | margin-top: 50px;
5 | line-height: 50px;
6 | }
7 | }
--------------------------------------------------------------------------------
/(3) zWebpack(简版webpack源码)/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const {delFileFolderByName, delFileByName} = require('./lib/utils')
3 | var fs = require("fs");
4 |
5 |
6 | class InitPlugin {
7 | run(compiler) {
8 | // 将的在执行期放到刚开始解析入口前
9 | compiler.hooks.entryInit.tap('Init', function(res) {
10 | console.log(`前端小伙子,编译开始咯。`);
11 | })
12 | }
13 | }
14 |
15 | class CleanDistPlugins {
16 | run(compiler) {
17 | // 将自身方法订阅到hook以备使用
18 | //假设它的运行期在编译完成之后
19 | compiler.hooks.beforeCompile.tap('CleanDistPlugins', function(res) {
20 | delFileFolderByName('./dist/');
21 | })
22 | }
23 | }
24 |
25 |
26 | class JsCopyPlugins {
27 | run(compiler) {
28 | compiler.hooks.afteremit.tap('JsCopyPlugins', function(res) {
29 | const ranNum = parseInt( Math.random() * 100000000 );
30 | fs.copyFile('./dist/main.js',`./dist/main.${ranNum}.js`,function(err){
31 | if(err) console.log('获取文件失败');
32 | delFileByName('./dist/main.js');
33 | })
34 | console.log("重新生成js成功" );
35 | return ranNum;
36 | })
37 | }
38 | }
39 |
40 | class HtmlReloadPlugins {
41 | run(compiler) {
42 | compiler.hooks.afteremit.tap('HtmlReloadPlugins', function(res) {
43 | let content = fs.readFileSync('./public/index.html', 'utf8')
44 | content = content.replace('main.js', `main.${res}.js`);
45 | fs.writeFileSync( './dist/index.html', content)
46 | })
47 | }
48 | }
49 |
50 | module.exports = {
51 | mode: 'development',
52 | entry: './src/index.js',
53 | output: {
54 | filename: 'main.js',
55 | path: path.join(__dirname, './dist')
56 | },
57 | module: {
58 | rules: [{
59 | test: /\.less$/,
60 | use: [path.join(__dirname, './lib/loader/less-loader.js')]
61 | },{
62 | test: /\.css$/,
63 | use: [path.join(__dirname, './lib/loader/style-loader.js')]
64 | }]
65 | },
66 | plugins: [
67 | new InitPlugin(),
68 | new CleanDistPlugins(),
69 | new JsCopyPlugins(),
70 | new HtmlReloadPlugins()
71 | ]
72 | }
73 |
--------------------------------------------------------------------------------
/(4) zQuery(简版jquery源码)/zQuery.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | zQuery源码
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
点击我重新赋值
19 |
点击我变成红色
20 |
点击我变成隐藏
21 |
点击我触发ajax
22 |
23 | 点击我触发链式变化:
我是子内容
24 |
25 |
点击我改变样式选择器
26 |
样式选择器
27 |
样式选择器
28 |
样式选择器
29 |
样式选择器
30 |
31 |
32 |
33 |
34 |
35 |
69 |
70 |
106 |
107 |
108 |
109 |
欢迎访问主页
110 |
113 |
116 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/(4) zQuery(简版jquery源码)/zQuery.js:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | 本代码来自weizhan
4 | github链接:https://github.com/zhuangweizhan
5 | csdn链接:https://blog.csdn.net/zhuangweizhan/
6 | */
7 |
8 | (function (window) {
9 | var zQuery = function (selector) {
10 | return new zQuery.fn.init(selector);
11 | }
12 | zQuery.fn = {
13 | init: function (selector, myDocument) {
14 | this.dom = this.dom ? this.dom : [];
15 | this.myDocument = myDocument ? myDocument : document;
16 | const childNodes = this.myDocument.childNodes;
17 | var rs = null;
18 | if (typeof (selector) != 'undefined') {
19 | if (selector.substr(0, 1) == "#") {//id选择器
20 | rs = this.myDocument.getElementById(selector.slice(1));
21 | this.dom[0] = rs;
22 | console.log("rs===" + rs.innerText + rs.innerHTML);
23 | } else if (selector.substr(0, 1) == ".") { //样式选择器
24 | rs = this.myDocument.getElementsByClassName(selector.slice(1));
25 | for (var i = 0; i < rs.length; i++) {
26 | this.dom[i] = rs[i];
27 | }
28 | }
29 | }
30 | return this;
31 | },
32 | find: function (selector) {
33 | if (this.dom.length == 1) {
34 | this.init(selector, this.dom[0]);
35 | } else if (this.dom.length > 1) {
36 | for (var i = 0; i < this.dom.length; i++) {
37 | this.init(selector, this.dom[i]);
38 | }
39 | }
40 | return this;
41 | },
42 | html: function (value) {
43 | if (this.dom.length == 1) {
44 | this.dom[0].innerHTML = value;
45 | } else if (this.length > 1) {
46 | for (var i = 0; i < this.dom.length; i++) {
47 | this.dom[i].style[attr] = value;
48 | }
49 | }
50 | },
51 | css: function (attr, value) {
52 | if (this.dom.length == 1) {
53 | this.dom[0].style[attr] = value;
54 | } else if (this.dom.length > 1) {
55 | for (var i = 0; i < this.dom.length; i++) {
56 | this.dom[i].style[attr] = value;
57 | }
58 | }
59 | },
60 | show: function (attr, value) {
61 | if (this.dom.length == 1) {
62 | this.dom[0].style.display = 'block';
63 | } else if (this.dom.length > 1) {
64 | for (var i = 0; i < this.dom.length; i++) {
65 | this.dom[i].style.display = 'block';
66 | }
67 | }
68 | },
69 | hide: function (attr, value) {
70 | if (this.dom.length == 1) {
71 | this.dom[0].style.display = 'none';
72 | } else if (this.dom.length > 1) {
73 | for (var i = 0; i < this.dom.length; i++) {
74 | this.dom[i].style.display = 'none';
75 | }
76 | }
77 | },
78 | //异常请求
79 | ajax: function ({ url, dataType, success }) {
80 | var xhr = new XMLHttpRequest();
81 | xhr.open(dataType, url);
82 | xhr.send(null);
83 | xhr.onreadystatechange = function () {
84 | if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
85 | success(xhr.responseText);
86 | };
87 | }
88 | },
89 | }
90 |
91 | zQuery.fn.init.prototype = zQuery.fn;
92 | window.$ = zQuery;
93 | })(window);
94 |
95 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | pnpm-debug.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/README.md:
--------------------------------------------------------------------------------
1 | # my-vuex
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | npm run lint
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-vuex",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "core-js": "^3.6.5",
12 | "vue": "^2.6.11",
13 | "vuex": "^3.5.1"
14 | },
15 | "devDependencies": {
16 | "@vue/cli-plugin-babel": "~4.4.0",
17 | "@vue/cli-plugin-eslint": "~4.4.0",
18 | "@vue/cli-service": "~4.4.0",
19 | "babel-eslint": "^10.1.0",
20 | "eslint": "^6.7.2",
21 | "eslint-plugin-vue": "^6.2.2",
22 | "vue-template-compiler": "^2.6.11"
23 | },
24 | "eslintConfig": {
25 | "root": true,
26 | "env": {
27 | "node": true
28 | },
29 | "extends": [
30 | "plugin:vue/essential",
31 | "eslint:recommended"
32 | ],
33 | "parserOptions": {
34 | "parser": "babel-eslint"
35 | },
36 | "rules": {}
37 | },
38 | "browserslist": [
39 | "> 1%",
40 | "last 2 versions",
41 | "not dead"
42 | ]
43 | }
44 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhuangweizhan/codeShare/214562c9bd12341aa1b3d03f20ce785d3ecc9c31/(5)zVuex(简版vuex源码)/my-vuex/public/favicon.ico
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
欢迎访问主页
17 |
25 |
33 |
41 |
42 |
43 |
44 |
45 |
57 |
58 |
59 |
96 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhuangweizhan/codeShare/214562c9bd12341aa1b3d03f20ce785d3ecc9c31/(5)zVuex(简版vuex源码)/my-vuex/src/assets/logo.png
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/src/components/compA.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
21 |
22 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/src/components/compB.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
姓名:{{getName}}
4 |
博客:{{getUrl}}
5 |
备注:{{getStatus}}
6 |
点我更新数据
7 |
8 |
9 |
10 |
36 |
37 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import store from './vuex/store.js'
4 | import Vuex from 'vuex'
5 |
6 | Vue.use(Vuex);
7 |
8 | Vue.config.productionTip = false
9 |
10 | new Vue({
11 | render: h => h(App),
12 | store
13 | }).$mount('#app')
14 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/src/vuex/moduels/other-model.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | status: '欢迎小姑凉', //
3 | }
4 |
5 | const getters = {
6 | getStatus(state) {
7 | return state.status;
8 | }
9 | }
10 |
11 | const mutations = {
12 | changeStatus(state, status) {
13 | // alert("status=" + status);
14 | state.status = status;
15 | // console.log("changeStatus=" + JSON.stringify( state));
16 | }
17 | }
18 |
19 | const actions = {
20 | changeStatusActions({commit}, value) { // 参数解构,拿到上下文
21 | setTimeout(() => {
22 | commit('changeStatus', value);
23 | }, 1000);
24 | }
25 | }
26 |
27 | export default {
28 | state,
29 | getters,
30 | mutations,
31 | actions
32 | }
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/src/vuex/moduels/user-model.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | name: '前端小伙', //
3 | url: 'https://juejin.im/user/5e8fddc9e51d4546be39a558', //
4 | }
5 |
6 | const getters = {
7 | getName(state) {
8 | return state.name;
9 | },
10 | getUrl(state) {
11 | return state.url;
12 | }
13 | }
14 |
15 | const mutations = {
16 | setName( value ){
17 | this.state.name = value;
18 | }
19 | }
20 |
21 | const actions = {
22 | setNameActions({commit}, value){
23 | setTimeout(() => {
24 | commit('setName', value );
25 | }, 500 );
26 | }
27 | }
28 |
29 | export default {
30 | state,
31 | getters,
32 | mutations,
33 | actions
34 | }
35 |
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/src/vuex/myVuex.js:
--------------------------------------------------------------------------------
1 | let Vue;
2 |
3 | function install(_Vue, storeName = '$store') {
4 | Vue = _Vue;
5 | Vue.mixin({
6 | beforeCreate() {
7 | if (this.$options.store) {
8 | Vue.prototype[storeName] = this.$options.store;
9 | }
10 | }
11 | })
12 | }
13 |
14 | class Store {
15 | constructor(options) {
16 | let {
17 | state = {}, getters = {}, mutations = {}, actions = {}, modules = {}
18 | } = options;
19 | for (var key in modules) {
20 | state = {
21 | ...state,
22 | ...modules[key].state
23 | }
24 | mutations = Object.assign(mutations, modules[key].mutations);
25 | getters = {
26 | ...getters,
27 | ...modules[key].getters
28 | };
29 | actions = Object.assign(actions, modules[key].actions);
30 | }
31 | this.state = new Vue({
32 | data: state
33 | });
34 | this.actions = actions;
35 | this.mutations = mutations;
36 | this.allGetters = getters;
37 | this.observerGettersFunc(getters);
38 | }
39 |
40 | // 触发mutations,需要实现commit
41 | commit = (type, arg) => {
42 | const fn = this.mutations[type]
43 | fn(this.state, arg)
44 | }
45 |
46 | // 触发action,需要实现dispatch
47 | dispatch = (type, arg) => {
48 | const fn = this.actions[type]
49 | return fn({
50 | commit: this.commit,
51 | state: this.state
52 | }, arg)
53 | }
54 |
55 | //数据劫持getters
56 | observerGettersFunc(getters) {
57 | this.getters = {} // store实例上的getters
58 | Object.keys(getters).forEach(key => {
59 | Object.defineProperty(this.getters, key, {
60 | get: () => {
61 | console.log(`retrunValue:` + JSON.stringify(this.state.$data));
62 | return getters[key](this.state)
63 | }
64 | })
65 | })
66 | }
67 | }
68 |
69 | export default {
70 | Store,
71 | install
72 | }
--------------------------------------------------------------------------------
/(5)zVuex(简版vuex源码)/my-vuex/src/vuex/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | // import Vuex from 'vuex'
3 | import Vuex from './myVuex'
4 | import otherModel from './moduels/other-model'
5 | import userModel from './moduels/user-model'
6 |
7 | Vue.use(Vuex);
8 | var store = new Vuex.Store({
9 | modules: {
10 | userModel,
11 | otherModel
12 | },
13 | })
14 |
15 | export default store;
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-html-hash-router/zRouter.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | zRouter源码
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
23 |
24 | 这是首页
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
49 |
50 |
99 |
100 |
101 |
104 |
欢迎访问主页
105 |
113 |
121 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-html-hash-router/zRouter.js:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | 本代码来自weizhan
4 | github链接:https://github.com/zhuangweizhan
5 | csdn链接:https://blog.csdn.net/zhuangweizhan/
6 | */
7 |
8 | class zRouter{
9 | constructor(){
10 | this.routes = {};
11 | this.init();
12 | }
13 |
14 | refresh(){
15 | let path = location.hash;
16 | this.routes[ path]();
17 | }
18 |
19 | init(){
20 | window.addEventListener( 'load', this.refresh.bind( this ), false );
21 | window.addEventListener( 'hashchange', this.refresh.bind( this ), false );
22 | }
23 |
24 | route( path, cb ){
25 | this.routes["#" + path] = cb || function(){};
26 | }
27 |
28 | }
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-vue-jsx", "transform-runtime"]
12 | }
13 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/README.md:
--------------------------------------------------------------------------------
1 | # my-vue-router
2 |
3 | > A Vue.js project
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 |
17 | # build for production and view the bundle analyzer report
18 | npm run build --report
19 | ```
20 |
21 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
22 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhuangweizhan/codeShare/214562c9bd12341aa1b3d03f20ce785d3ecc9c31/(6)zVueRouter(简版vueRouter源码)/my-vue-router/build/logo.png
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader'
51 | })
52 | } else {
53 | return ['vue-style-loader'].concat(loaders)
54 | }
55 | }
56 |
57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
58 | return {
59 | css: generateLoaders(),
60 | postcss: generateLoaders(),
61 | less: generateLoaders('less'),
62 | sass: generateLoaders('sass', { indentedSyntax: true }),
63 | scss: generateLoaders('sass'),
64 | stylus: generateLoaders('stylus'),
65 | styl: generateLoaders('stylus')
66 | }
67 | }
68 |
69 | // Generate loaders for standalone style files (outside of .vue)
70 | exports.styleLoaders = function (options) {
71 | const output = []
72 | const loaders = exports.cssLoaders(options)
73 |
74 | for (const extension in loaders) {
75 | const loader = loaders[extension]
76 | output.push({
77 | test: new RegExp('\\.' + extension + '$'),
78 | use: loader
79 | })
80 | }
81 |
82 | return output
83 | }
84 |
85 | exports.createNotifierCallback = () => {
86 | const notifier = require('node-notifier')
87 |
88 | return (severity, errors) => {
89 | if (severity !== 'error') return
90 |
91 | const error = errors[0]
92 | const filename = error.file && error.file.split('!').pop()
93 |
94 | notifier.notify({
95 | title: packageConfig.name,
96 | message: severity + ': ' + error.name,
97 | subtitle: filename || '',
98 | icon: path.join(__dirname, 'logo.png')
99 | })
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 |
12 |
13 | module.exports = {
14 | context: path.resolve(__dirname, '../'),
15 | entry: {
16 | app: './src/main.js'
17 | },
18 | output: {
19 | path: config.build.assetsRoot,
20 | filename: '[name].js',
21 | publicPath: process.env.NODE_ENV === 'production'
22 | ? config.build.assetsPublicPath
23 | : config.dev.assetsPublicPath
24 | },
25 | resolve: {
26 | extensions: ['.js', '.vue', '.json'],
27 | alias: {
28 | 'vue$': 'vue/dist/vue.esm.js',
29 | '@': resolve('src'),
30 | }
31 | },
32 | module: {
33 | rules: [
34 | {
35 | test: /\.vue$/,
36 | loader: 'vue-loader',
37 | options: vueLoaderConfig
38 | },
39 | {
40 | test: /\.js$/,
41 | loader: 'babel-loader',
42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
43 | },
44 | {
45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
46 | loader: 'url-loader',
47 | options: {
48 | limit: 10000,
49 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
50 | }
51 | },
52 | {
53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
54 | loader: 'url-loader',
55 | options: {
56 | limit: 10000,
57 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
58 | }
59 | },
60 | {
61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
62 | loader: 'url-loader',
63 | options: {
64 | limit: 10000,
65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
66 | }
67 | }
68 | ]
69 | },
70 | node: {
71 | // prevent webpack from injecting useless setImmediate polyfill because Vue
72 | // source contains it (although only uses it if it's native).
73 | setImmediate: false,
74 | // prevent webpack from injecting mocks to Node native modules
75 | // that does not make sense for the client
76 | dgram: 'empty',
77 | fs: 'empty',
78 | net: 'empty',
79 | tls: 'empty',
80 | child_process: 'empty'
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | const devWebpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: config.dev.devtool,
22 |
23 | // these devServer options should be customized in /config/index.js
24 | devServer: {
25 | clientLogLevel: 'warning',
26 | historyApiFallback: {
27 | rewrites: [
28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
29 | ],
30 | },
31 | hot: true,
32 | contentBase: false, // since we use CopyWebpackPlugin.
33 | compress: true,
34 | host: HOST || config.dev.host,
35 | port: PORT || config.dev.port,
36 | open: config.dev.autoOpenBrowser,
37 | overlay: config.dev.errorOverlay
38 | ? { warnings: false, errors: true }
39 | : false,
40 | publicPath: config.dev.assetsPublicPath,
41 | proxy: config.dev.proxyTable,
42 | quiet: true, // necessary for FriendlyErrorsPlugin
43 | watchOptions: {
44 | poll: config.dev.poll,
45 | }
46 | },
47 | plugins: [
48 | new webpack.DefinePlugin({
49 | 'process.env': require('../config/dev.env')
50 | }),
51 | new webpack.HotModuleReplacementPlugin(),
52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53 | new webpack.NoEmitOnErrorsPlugin(),
54 | // https://github.com/ampedandwired/html-webpack-plugin
55 | new HtmlWebpackPlugin({
56 | filename: 'index.html',
57 | template: 'index.html',
58 | inject: true
59 | }),
60 | // copy custom static assets
61 | new CopyWebpackPlugin([
62 | {
63 | from: path.resolve(__dirname, '../static'),
64 | to: config.dev.assetsSubDirectory,
65 | ignore: ['.*']
66 | }
67 | ])
68 | ]
69 | })
70 |
71 | module.exports = new Promise((resolve, reject) => {
72 | portfinder.basePort = process.env.PORT || config.dev.port
73 | portfinder.getPort((err, port) => {
74 | if (err) {
75 | reject(err)
76 | } else {
77 | // publish the new Port, necessary for e2e tests
78 | process.env.PORT = port
79 | // add port to devServer config
80 | devWebpackConfig.devServer.port = port
81 |
82 | // Add FriendlyErrorsPlugin
83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
84 | compilationSuccessInfo: {
85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
86 | },
87 | onErrors: config.dev.notifyOnErrors
88 | ? utils.createNotifierCallback()
89 | : undefined
90 | }))
91 |
92 | resolve(devWebpackConfig)
93 | }
94 | })
95 | })
96 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = require('../config/prod.env')
15 |
16 | const webpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({
19 | sourceMap: config.build.productionSourceMap,
20 | extract: true,
21 | usePostCSS: true
22 | })
23 | },
24 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
25 | output: {
26 | path: config.build.assetsRoot,
27 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
28 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
29 | },
30 | plugins: [
31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
32 | new webpack.DefinePlugin({
33 | 'process.env': env
34 | }),
35 | new UglifyJsPlugin({
36 | uglifyOptions: {
37 | compress: {
38 | warnings: false
39 | }
40 | },
41 | sourceMap: config.build.productionSourceMap,
42 | parallel: true
43 | }),
44 | // extract css into its own file
45 | new ExtractTextPlugin({
46 | filename: utils.assetsPath('css/[name].[contenthash].css'),
47 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
48 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
49 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
50 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
51 | allChunks: true,
52 | }),
53 | // Compress extracted CSS. We are using this plugin so that possible
54 | // duplicated CSS from different components can be deduped.
55 | new OptimizeCSSPlugin({
56 | cssProcessorOptions: config.build.productionSourceMap
57 | ? { safe: true, map: { inline: false } }
58 | : { safe: true }
59 | }),
60 | // generate dist index.html with correct asset hash for caching.
61 | // you can customize output by editing /index.html
62 | // see https://github.com/ampedandwired/html-webpack-plugin
63 | new HtmlWebpackPlugin({
64 | filename: config.build.index,
65 | template: 'index.html',
66 | inject: true,
67 | minify: {
68 | removeComments: true,
69 | collapseWhitespace: true,
70 | removeAttributeQuotes: true
71 | // more options:
72 | // https://github.com/kangax/html-minifier#options-quick-reference
73 | },
74 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
75 | chunksSortMode: 'dependency'
76 | }),
77 | // keep module.id stable when vendor modules does not change
78 | new webpack.HashedModuleIdsPlugin(),
79 | // enable scope hoisting
80 | new webpack.optimize.ModuleConcatenationPlugin(),
81 | // split vendor js into its own file
82 | new webpack.optimize.CommonsChunkPlugin({
83 | name: 'vendor',
84 | minChunks (module) {
85 | // any required modules inside node_modules are extracted to vendor
86 | return (
87 | module.resource &&
88 | /\.js$/.test(module.resource) &&
89 | module.resource.indexOf(
90 | path.join(__dirname, '../node_modules')
91 | ) === 0
92 | )
93 | }
94 | }),
95 | // extract webpack runtime and module manifest to its own file in order to
96 | // prevent vendor hash from being updated whenever app bundle is updated
97 | new webpack.optimize.CommonsChunkPlugin({
98 | name: 'manifest',
99 | minChunks: Infinity
100 | }),
101 | // This instance extracts shared chunks from code splitted chunks and bundles them
102 | // in a separate chunk, similar to the vendor chunk
103 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
104 | new webpack.optimize.CommonsChunkPlugin({
105 | name: 'app',
106 | async: 'vendor-async',
107 | children: true,
108 | minChunks: 3
109 | }),
110 |
111 | // copy custom static assets
112 | new CopyWebpackPlugin([
113 | {
114 | from: path.resolve(__dirname, '../static'),
115 | to: config.build.assetsSubDirectory,
116 | ignore: ['.*']
117 | }
118 | ])
119 | ]
120 | })
121 |
122 | if (config.build.productionGzip) {
123 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
124 |
125 | webpackConfig.plugins.push(
126 | new CompressionWebpackPlugin({
127 | asset: '[path].gz[query]',
128 | algorithm: 'gzip',
129 | test: new RegExp(
130 | '\\.(' +
131 | config.build.productionGzipExtensions.join('|') +
132 | ')$'
133 | ),
134 | threshold: 10240,
135 | minRatio: 0.8
136 | })
137 | )
138 | }
139 |
140 | if (config.build.bundleAnalyzerReport) {
141 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
142 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
143 | }
144 |
145 | module.exports = webpackConfig
146 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: 'localhost', // can be overwritten by process.env.HOST
17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: false,
19 | errorOverlay: true,
20 | notifyOnErrors: true,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 |
24 | /**
25 | * Source Maps
26 | */
27 |
28 | // https://webpack.js.org/configuration/devtool/#development
29 | devtool: 'cheap-module-eval-source-map',
30 |
31 | // If you have problems debugging vue-files in devtools,
32 | // set this to false - it *may* help
33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
34 | cacheBusting: true,
35 |
36 | cssSourceMap: true
37 | },
38 |
39 | build: {
40 | // Template for index.html
41 | index: path.resolve(__dirname, '../dist/index.html'),
42 |
43 | // Paths
44 | assetsRoot: path.resolve(__dirname, '../dist'),
45 | assetsSubDirectory: 'static',
46 | assetsPublicPath: '/',
47 |
48 | /**
49 | * Source Maps
50 | */
51 |
52 | productionSourceMap: true,
53 | // https://webpack.js.org/configuration/devtool/#production
54 | devtool: '#source-map',
55 |
56 | // Gzip off by default as many popular static hosts such as
57 | // Surge or Netlify already gzip all static assets for you.
58 | // Before setting to `true`, make sure to:
59 | // npm install --save-dev compression-webpack-plugin
60 | productionGzip: false,
61 | productionGzipExtensions: ['js', 'css'],
62 |
63 | // Run the build command with an extra argument to
64 | // View the bundle analyzer report after build finishes:
65 | // `npm run build --report`
66 | // Set to `true` or `false` to always turn it on or off
67 | bundleAnalyzerReport: process.env.npm_config_report
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | my-vue-router
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-vue-router",
3 | "version": "1.0.0",
4 | "description": "A Vue.js project",
5 | "author": "zhuangweizhan <365638983@qq.com>",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "build": "node build/build.js"
11 | },
12 | "dependencies": {
13 | "vue": "^2.5.2",
14 | "vue-router": "^3.0.1"
15 | },
16 | "devDependencies": {
17 | "autoprefixer": "^7.1.2",
18 | "babel-core": "^6.22.1",
19 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
20 | "babel-loader": "^7.1.1",
21 | "babel-plugin-syntax-jsx": "^6.18.0",
22 | "babel-plugin-transform-runtime": "^6.22.0",
23 | "babel-plugin-transform-vue-jsx": "^3.5.0",
24 | "babel-preset-env": "^1.3.2",
25 | "babel-preset-stage-2": "^6.22.0",
26 | "chalk": "^2.0.1",
27 | "copy-webpack-plugin": "^4.0.1",
28 | "css-loader": "^0.28.0",
29 | "extract-text-webpack-plugin": "^3.0.0",
30 | "file-loader": "^1.1.4",
31 | "friendly-errors-webpack-plugin": "^1.6.1",
32 | "html-webpack-plugin": "^2.30.1",
33 | "node-notifier": "^5.1.2",
34 | "optimize-css-assets-webpack-plugin": "^3.2.0",
35 | "ora": "^1.2.0",
36 | "portfinder": "^1.0.13",
37 | "postcss-import": "^11.0.0",
38 | "postcss-loader": "^2.0.8",
39 | "postcss-url": "^7.2.1",
40 | "rimraf": "^2.6.0",
41 | "semver": "^5.3.0",
42 | "shelljs": "^0.7.6",
43 | "uglifyjs-webpack-plugin": "^1.1.1",
44 | "url-loader": "^0.5.8",
45 | "vue-loader": "^13.3.0",
46 | "vue-style-loader": "^3.0.1",
47 | "vue-template-compiler": "^2.5.2",
48 | "webpack": "^3.6.0",
49 | "webpack-bundle-analyzer": "^2.9.0",
50 | "webpack-dev-server": "^2.9.1",
51 | "webpack-merge": "^4.1.0"
52 | },
53 | "engines": {
54 | "node": ">= 6.0.0",
55 | "npm": ">= 3.0.0"
56 | },
57 | "browserslist": [
58 | "> 1%",
59 | "last 2 versions",
60 | "not ie <= 8"
61 | ]
62 | }
63 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
15 |
欢迎访问主页
16 |
24 |
32 |
40 |
41 |
42 |
43 |
44 |
49 |
50 |
87 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhuangweizhan/codeShare/214562c9bd12341aa1b3d03f20ce785d3ecc9c31/(6)zVueRouter(简版vueRouter源码)/my-vue-router/src/assets/logo.png
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/src/components/First.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/src/components/Second.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import App from './App'
5 | import router from './router'
6 |
7 | Vue.config.productionTip = false
8 |
9 | /* eslint-disable no-new */
10 | new Vue({
11 | el: '#app',
12 | router,
13 | components: { App },
14 | template: ''
15 | })
16 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | // import Router from 'vue-router'
3 | import Router from '../vue-router/index.js'
4 | import First from '@/components/First'
5 | import Second from '@/components/Second'
6 |
7 | Vue.use(Router)
8 |
9 | export default new Router({
10 | routes: [
11 | {
12 | path: '/',
13 | name: 'First',
14 | component: First
15 | },
16 | {
17 | path: '/Second',
18 | name: 'Second',
19 | component: Second
20 | }
21 | ]
22 | })
23 |
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/src/vue-router/index.js:
--------------------------------------------------------------------------------
1 | //渲染routerView组件
2 | const routerView = {
3 | name: 'RouterView',
4 | render(h) {
5 | const currentPath = this._self._routerRoot._router.currentObj.path;
6 | const routeMap = this._self._routerRoot._router.routesMap;
7 | return h(routeMap[currentPath])
8 | }
9 | }
10 |
11 | //渲染routerLink组件
12 | const routerLink = {
13 | name: 'RouterLink',
14 | props: {
15 | to: String
16 | },
17 | render(h) {
18 | const isHashMode = this._self._routerRoot._router.isHashMode;
19 | return h('a', {
20 | attrs: {
21 | href: ( isHashMode? "#" : "") + this.to
22 | }
23 | }, this.$slots.default)
24 | }
25 | }
26 |
27 | class VueRouter {
28 |
29 | constructor(options) {
30 | this.isHashMode = !( options.mode == "history" );//只要不是history模式,其他均为hash模式
31 | this.routes = options.routes || [];//存储路由地址
32 | this.routesMap = this.getRoutesMap(this.routes);
33 | this.currentObj = { path: '' };
34 | this.initListener()
35 | }
36 |
37 | initListener() {
38 | //hash模式以hash为准,history以pathname为准,且为空时默认为/
39 | const initPath = ( this.isHashMode ? location.hash.slice(1) : location.pathname ) || "/";
40 | const listName = this.isHashMode ? "hashchange": "popstate";//监听的对象名称,hash模式监听hashchange,history监听popstate
41 | window.addEventListener("load", () => {
42 | this.currentObj.path = initPath;
43 | })
44 | window.addEventListener( listName, () => {
45 | this.currentObj.path = ( this.isHashMode ? location.hash.slice(1) : location.pathname ) || "/";;
46 | })
47 | }
48 |
49 | getRoutesMap(routes) {
50 | return routes.reduce((pre, current) => {
51 | pre[current.path] = current.component
52 | return pre;
53 | }, {})
54 | }
55 |
56 | }
57 |
58 | VueRouter.install = function (v) {
59 | v.mixin({
60 | beforeCreate() {
61 | if (this.$options && this.$options.router) { // 如果是根组件
62 | this._routerRoot = this; //把当前实例挂载到_root上
63 | this._router = this.$options.router;
64 | v.util.defineReactive(this, '_route', this._router.currentObj); // 来实现双线绑定
65 | } else { //如果是子组件
66 | this._routerRoot = this.$parent && this.$parent._routerRoot
67 | }
68 |
69 | Object.defineProperty(this, '$router', {
70 | get() {
71 | return this._routerRoot._router;
72 | }
73 | });
74 |
75 | Object.defineProperty(this, '$route', {
76 | get() {
77 | return this._routerRoot._route;
78 | }
79 | })
80 | }
81 | });
82 |
83 | v.component('RouterLink', routerLink);
84 | v.component('RouterView', routerView);
85 |
86 | }
87 |
88 | export default VueRouter;
--------------------------------------------------------------------------------
/(6)zVueRouter(简版vueRouter源码)/my-vue-router/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhuangweizhan/codeShare/214562c9bd12341aa1b3d03f20ce785d3ecc9c31/(6)zVueRouter(简版vueRouter源码)/my-vue-router/static/.gitkeep
--------------------------------------------------------------------------------
/(7)zDiff(简版diff流程)/zDiff.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | virtualDom个人理解
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 1.点击获取虚拟dom对象
15 | 2.点击触发虚拟dom同步页面
16 | 请按步骤点击按钮
17 |
18 |
45 |
51 |
52 |
53 |
欢迎访问主页
54 |
57 |
60 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/(7)zDiff(简版diff流程)/zDiff.js:
--------------------------------------------------------------------------------
1 | /*
2 | 本代码来自weizhan
3 | github链接:https://github.com/zhuangweizhan
4 | csdn链接:https://blog.csdn.net/zhuangweizhan/
5 | */
6 |
7 | const stateType = {
8 | Change: 'Change',//表示元素有变化
9 | Move: 'Move',//表示移动了位置
10 | Add: 'Add',//表示元素是新增的
11 | Del: 'Del',//表示元素给删除了
12 | DiffPropsList: 'DiffPropsList',//表示元素对应的属性列表有变动
13 | DelProps: 'DelProps',//表示该属性给删除
14 | ChangeProps: 'ChangeProps',//表示该属性有变化
15 | AddProps: 'AddProps',//表示该属性是新增的
16 | };
17 |
18 | class zElement {
19 |
20 | /*
21 | tag('string'):标签的名称
22 | props('object'):属性与属性的值{ class: 'a', type: 'hidden'}
23 | children('array'):子属性
24 | key('string'):表示元素的唯一标识 'nowKeys'
25 | */
26 | constructor(tag, props, children, key) {
27 | this.tag = tag;
28 | this.props = props;
29 | this.children = children;
30 | this.key = key;
31 | }
32 |
33 | render() {
34 | //获取属性
35 | var root = this._createDom(
36 | this.tag,
37 | this.props,
38 | this.children,
39 | this.key,
40 | );
41 | document.body.appendChild(root);
42 | return root;
43 | }
44 |
45 | create(){
46 | return this._createDom(this.tag, this.props, this.children, this.key)
47 | }
48 |
49 | //创建dom
50 | _createDom(tag, props, children = [], key) {
51 | let dom = document.createElement(tag);
52 | for (let propKey in props) {
53 | dom.setAttribute(propKey, props[propKey]);
54 | }
55 | if (!key) {
56 | dom.setAttribute("key", key);
57 | }
58 | if (children.length > 0) {
59 | children.forEach(item => {
60 | if (item instanceof zElement) {//
61 | var root = this._createDom(
62 | item.tag,
63 | item.props,
64 | item.children,
65 | item.key
66 | )
67 | dom.appendChild( root );
68 | } else {
69 | var childNode = document.createTextNode(item);
70 | dom.appendChild(childNode);
71 | }
72 | });
73 | }
74 | return dom;
75 | }
76 |
77 | }
78 |
79 | //判断两个dom差异的地方
80 | // index 表示第几层的意思
81 | // patches 表示返回的数组
82 |
83 | function diff(oldElement, newElement) {
84 | var index = 0;
85 | var patches = {};
86 | dfs(oldElement, newElement, index, patches);
87 | return patches;
88 | }
89 |
90 | //判断当前对象
91 | function dfs(oldElement, newElement, index, patches) {
92 | //如果新的对象为空,无需要对比
93 | //如果新的对象,key跟tag都不同,说明元素变了,直接替换。
94 | //如果新的对象,key跟tag都相同,则遍历子集,观察子集是否不同,观察元素属性是否不同
95 | var curPatches = [];
96 | if (!newElement) {
97 | } else if (oldElement.key != newElement.key || oldElement.tag != newElement.tag) {
98 | curPatches.push({
99 | type: stateType.Change,
100 | node: newElement
101 | });
102 | } else {
103 | var propsDiff = diffProps(oldElement.props, newElement.props);
104 | if (propsDiff.length > 0) {
105 | curPatches.push({
106 | type: stateType.DiffPropsList,
107 | node: newElement
108 | });
109 | }
110 | diffChildren(oldElement.children, newElement.children,index, patches);//对比子集是否不同
111 | }
112 | if (curPatches.length > 0) {
113 | if (!patches[index]) {
114 | patches[index] = []
115 | }
116 | patches[index] = patches[index].concat(curPatches);
117 | }
118 | return patches;
119 | }
120 |
121 | //判断两个diff的算法
122 | function diffProps(oldProps, newProps) {
123 | //先判断是否有删除
124 | //再判断是否有修改,新增的
125 | let change = [];
126 | for (let key in oldProps) {
127 | if ( !newProps.hasOwnProperty(key) ) {//说明新的没有,则删除了
128 | change.push({
129 | key: key,
130 | type: stateType.DelProps
131 | });
132 | } else {
133 | }
134 | }
135 | for (let keys in newProps) {
136 | if ( !oldProps.hasOwnProperty(keys) ) {//说明旧的是没有,是新增的属性
137 | change.push({
138 | key: keys,
139 | type: stateType.AddProps,
140 | value: newProps[keys]
141 | });
142 | } else {
143 | if (oldProps[keys] != newProps[keys]) {
144 | change.push({
145 | key: keys,
146 | type: stateType.ChangeProps,
147 | value: newProps[keys]
148 | });
149 | }
150 | }
151 | }
152 | return change;
153 | }
154 |
155 | //获取数组的keys
156 | function getKeys(list) {
157 | var reuslt = [];
158 | list.forEach( item => {
159 | reuslt.push(item.key);
160 | })
161 | return reuslt;
162 | }
163 |
164 | //
165 | function diffChildren(oldChild, newChild, index, patches) {
166 | let { changeList, resultList } = listDiff(oldChild, newChild, index, patches);
167 | if (changeList.length > 0) {
168 | if (!patches[index]) {
169 | patches[index] = []
170 | }
171 | patches[index] = patches[index].concat(changeList);
172 | }
173 | let last = null;
174 | oldChild && oldChild.forEach((item, i) => {
175 | let child = item && item.children;
176 | if (child) {
177 | if ( last && last.children != null) {//有子节点
178 | index = index + last.children.length + 1;
179 | } else {
180 | index += 1;
181 | }
182 | let keyIndex = resultList.indexOf( item.key ) ;
183 | let node = newChild[keyIndex]
184 | //只遍历新旧中都存在的节点,其他新增或者删除的没必要遍历
185 | if ( node ) {
186 | dfs(item, node, index, patches)
187 | }
188 | } else {
189 | index += 1;
190 | }
191 | last = item
192 | });
193 | }
194 |
195 | function listDiff(oldList, newList, index, patches) {
196 | // 先算出删除,的数组
197 | // 再算出改动,或者插入的数据。
198 | let changeList = [];//改变的统计
199 | let resultList = [];//最后返回的顺序列表
200 | let oldKeys = getKeys(oldList);
201 | let newKeys = getKeys(newList);
202 | oldList && oldList.forEach((item, oIndex) => {
203 | if (newKeys.indexOf(item.key) == -1) {//说明新的数组没有。给删除了。
204 | changeList.push({
205 | type: stateType.Del,
206 | key: item.key,
207 | index: oIndex
208 | })
209 | } else {
210 | resultList.push(item.key);
211 | }
212 | })
213 | newList && newList.forEach((item, nIndex) => {
214 | if (resultList.indexOf(item.key) == -1) { //说明旧的没有,是新增的元素
215 | changeList.push({
216 | type: stateType.Add,
217 | key: item.key,
218 | node: item,
219 | index: index,
220 | })
221 | resultList.splice(nIndex, 0, item.key);
222 | } else {
223 | if (resultList.indexOf(item) == nIndex) {
224 | changeList.push({
225 | type: stateType.Change,//说明是修改的元素
226 | key: item.key,
227 | node: item,
228 | to: nIndex, //
229 | from: resultList.indexOf(item.key), //
230 | })
231 | }
232 | //交换resultList的顺序
233 | resultList = moveDom(resultList, nIndex, resultList.indexOf(item.key));
234 | }
235 | });
236 | return { changeList, resultList };
237 | }
238 |
239 | //交换resultList的顺序
240 | function moveDom(list, to, from) {
241 | var returnTag = list[to];
242 | list[to] = list[from];
243 | list[from] = returnTag;
244 | return list;
245 | }
246 |
247 |
248 | var num = 0;
249 | function reloadDom( node, patchs ){
250 | var changes = patchs[ num ];
251 | let childNodes = node && node.childNodes;
252 | if (!childNodes) num += 1
253 | if( changes != null ){
254 | changeDom( node, changes );
255 | }
256 | //保持更diff算法的num一直
257 | var last = null
258 | childNodes && childNodes.forEach(( item, i ) => {
259 | if( childNodes ){
260 | if ( last && last.children != null) {//有子节点
261 | num = num + last.children.length + 1;
262 | } else {
263 | num += 1;
264 | }
265 | }
266 | reloadDom( item, patchs );
267 | last = item;
268 | })
269 | }
270 |
271 | function changeDom( node, changes ){
272 | changes && changes.forEach( change => {
273 | let {type} = change;
274 | switch( type ){
275 | case stateType.Change:
276 | node.parentNode && node.parentNode.replaceChild( change.node.create() , node );
277 | break;
278 | case stateType.Move:
279 | let fromNode = node.childNodes[change.from];
280 | let toNode = node.childNodes[change.to];
281 | let formClone = fromNode.cloneNode(true);
282 | let toClone = toNode.cloneNode(true);
283 | node.replaceChild( fromNode, toClone ) ;
284 | node.replaceChild( toNode, formClone ) ;
285 | break;
286 | case stateType.Add:
287 | node.insertBefore( change.node.create(), node.childNodes[ change.index ] )
288 | break;
289 | case stateType.Del:
290 | node.childNodes[change.index ].remove();
291 | break;
292 | case stateType.DiffPropsList:
293 | let {props} = change.node;
294 | for( let key in props ){
295 | if( key == stateType.DelProps ){
296 | node.removeAttribute( );
297 | } else {
298 | node.setAttribute( key, props[key] );
299 | }
300 | }
301 | break;
302 | default:
303 | break;
304 | }
305 | });
306 | }
--------------------------------------------------------------------------------
/(7)zDiff(简版diff流程)/zVirtualDom.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | virtualDom个人理解
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 1.点击获取虚拟dom对象
15 | 2.点击触发虚拟dom同步页面
16 | 请按步骤点击按钮
17 |
18 |
45 |
51 |
52 |
53 |
欢迎访问主页
54 |
57 |
60 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/(8)zPromise(简版promise流程)/zPromise.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | zPromise源码
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
点击屏幕可执行等待promise
17 |
18 |
19 |
20 |
57 |
58 |
59 |
欢迎访问主页
60 |
63 |
66 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/(8)zPromise(简版promise流程)/zPromise.js:
--------------------------------------------------------------------------------
1 | /*
2 | 本代码来自weizhan
3 | github链接:https://github.com/zhuangweizhan
4 | 博客链接:https://juejin.im/user/4195392104696519
5 | */
6 |
7 | var PEDDING = "pedding";
8 | var REJECTED = "rejected";
9 | var REFULLED = "refulled";
10 |
11 | class MyPromise{
12 |
13 | constructor(handle){
14 |
15 | if( typeof("handle") == "function" ){
16 | throw new Error("MyPromise handle is not a function");
17 | }
18 | var self = this;
19 | self._param = null;//返回值
20 | self._status = PEDDING;//添加状态
21 | //then方法返回的promise对象的resovle和reject
22 | self.nextResolve = null;//
23 | self.nextReject = null;//
24 | //记录then的方法参数
25 | self.asynFulliled = null;
26 | self.asynRejected = null;
27 | handle( _resolve, _reject );
28 |
29 | self.then = function( onFulliled, onReject ){
30 | return new self.constructor( function( resovle, reject ){
31 | if( self._status == REFULLED ){
32 | doAsynFulliled( onFulliled, resovle, reject );
33 | } else if ( self._status == REFULLED ){
34 | doAsynRejected( onReject, resovle, reject );
35 | } else {//即pedding的时候 往上执行
36 | self.nextResolve = resovle;
37 | self.nextReject = reject;
38 | self.asynFulliled = onFulliled;
39 | self.asynRejected = onReject;
40 | }
41 | })
42 | }
43 |
44 | function _resolve( val ){
45 | self._status = REFULLED;
46 | self._param = val;
47 | if( self.nextResolve ){
48 | doAsynFulliled( self.asynFulliled, self.nextResolve, self.nextReject );
49 | }
50 | }
51 |
52 | function _reject( error ){
53 | _status = REJECTED;
54 | _param = error;
55 | if( nextReject ){
56 | doAsynRejected( asynRejected, nextResolve, nextReject );
57 | }
58 | }
59 |
60 | function doAsynFulliled( onFulliled, resolve, reject ){
61 | if( typeof onFulliled == 'function' ){
62 | let promise = onFulliled( self._param );
63 | if( promise == undefined ){//说明首次
64 | resolve( self._param );
65 | } else if ( promise.constructor == self.constructor ){
66 | promise.then( function(param){
67 | resolve( param );
68 | }, function( param ){
69 | reject( param );
70 | })
71 | } else {
72 | resolve( self._param );
73 | }
74 | } else {
75 | resolve( self._param );
76 | }
77 | }
78 |
79 | function doAsynRejected( onRejected, resolve, reject ){
80 | if( typeof onRejected == 'function' ){
81 | let promise = onFulliled( self._param );
82 | if( promise == undefined ){//说明首次
83 | reject( self._param );
84 | } else if ( promise.constructor == self.constructor ){
85 | promise.then( function(param){
86 | resolve( param );
87 | }, function( param ){
88 | reject( param );
89 | })
90 | } else {
91 | reject( self._param );
92 | }
93 | } else {
94 | reject( self._param );
95 | }
96 | }
97 |
98 |
99 | }
100 |
101 |
102 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 前端手写源码汇总
2 |
3 | 本目录对应个人掘金博客,框架在博客中有对应的讲解以及说明。欢迎查询:
4 |
5 | https://juejin.im/user/5e8fddc9e51d4546be39a558/posts
6 |
7 | 以下均为个人汇总,本人也是在线奋斗小青年,如有不对的地方,欢迎博客上留言指点。
8 |
9 |
10 |
11 | 喜欢请star。
12 |
13 |
14 |
15 | ### (1) zVue(简版vue源码)
16 |
17 | 基于vue2.0,模仿vue的解析过程,实现mvvn架构。根据**Object.defineProperty**模拟包括observer双向绑定,compile解析,watch监听。详情请进入看案例源码。
18 |
19 | 基于vue3.0,跟2.0不同的是,采用了proxy实现双向绑定。
20 |
21 | 博客链接: https://juejin.im/post/5f0326786fb9a07e976bd945
22 |
23 |
24 |
25 | ### (2) zReact(简版react源码)
26 |
27 | 模拟react思维,描述 react 跟 reactDom的执行过程,如何render到dom中,react的组件化是如何实现的。
28 |
29 | 博客链接: https://juejin.im/post/5f154c5f6fb9a07ec07b536b
30 |
31 |
32 |
33 | ### (3) zWebpack(简版webpack源码)
34 |
35 | 模拟webpack的打包过程,webpack是如何编译的,怎么输出到js中,webpack生命周期的模拟,以及loader跟plugins如何实现的
36 |
37 | 博客链接: https://juejin.im/post/5f1793716fb9a07e8b215a62
38 |
39 |
40 |
41 | ### (4) zQuery(简版jquery源码)
42 |
43 | 实现jquery链式 ,实现html, css, attr等dom操作 ,简版ajax请求。详情请进入看案例源码。
44 |
45 | 博客链接: https://juejin.im/post/5f1e3897e51d453495702fc4
46 |
47 |
48 |
49 | ### (5) zVuex(简版vuex源码)
50 |
51 | 基于vue,手写Vuex实现整过程。
52 |
53 | 博客链接: https://juejin.im/post/6855295553794736142
54 |
55 |
56 |
57 | ### (6) zVueRouter(简版vue-router源码)
58 |
59 | 基于vue,手写Vue-router实现整过程。
60 |
61 | 博客链接: https://juejin.im/post/6859565866552393741
62 |
63 |
64 |
65 | ### (7) zDiff(简版diff算法源码)
66 |
67 | 模拟diff实现过程
68 |
69 | 博客链接: https://juejin.im/post/6868818012401565709
70 |
71 |
72 |
73 | ### (8) zPromise(简版promise源码)
74 |
75 | 模拟promise/A+的过程
76 |
77 | 博客链接: https://juejin.im/post/6869202482644385806
78 |
79 |
80 |
81 | ### (9) 原生js源码(模拟js的实现)
82 |
83 | 后续持续更新
84 |
85 |
86 |
87 | ### (10) zRedux(简版reactRedux源码)
88 |
89 | 后续持续更新
90 |
91 |
92 |
93 | ### (11) zKoa2(简版koa2代码源码)
94 |
95 | 后续持续更新
--------------------------------------------------------------------------------