+  
+    
+    
+    
+      默认按钮
+      主要按钮
+      成功按钮
+      信息按钮
+      警告按钮
+      危险按钮
+    
+    
+    
+    
+      
+      
+      
+      
+      
+      
+    
+  
+
+
+
diff --git a/20_脚手架/vue_code/39.src_UI组件Element-ui/assets/logo.png b/20_脚手架/vue_code/39.src_UI组件Element-ui/assets/logo.png
new file mode 100644
index 0000000..f3d2503
Binary files /dev/null and b/20_脚手架/vue_code/39.src_UI组件Element-ui/assets/logo.png differ
diff --git a/20_脚手架/vue_code/39.src_UI组件Element-ui/main.js b/20_脚手架/vue_code/39.src_UI组件Element-ui/main.js
new file mode 100644
index 0000000..c2bb321
--- /dev/null
+++ b/20_脚手架/vue_code/39.src_UI组件Element-ui/main.js
@@ -0,0 +1,28 @@
+// 引入Vue
+import Vue from "vue";
+// 引入App
+import App from "./App";
+// 引入Element-ui组件库
+// import ElementUI from 'element-ui';
+// 引入ElementUI的全部样式
+// import 'element-ui/lib/theme-chalk/index.css';
+// 按需引入
+import {Button, Row, DatePicker} from "element-ui";
+
+// 设置Vue
+Vue.config.productionTip = false
+
+// 使用插件
+// Vue.use(ElementUI);  // 引入全部组件
+// 按需注册组件
+Vue.component(Button.name, Button);
+Vue.component(Row.name, Row);
+Vue.component(DatePicker.name, DatePicker);
+
+// 实例化Vue
+new Vue({
+    components: {
+        App
+    },
+    render: h => h(App),
+}).$mount('#app')
diff --git a/20_脚手架/vue_code/babel.config.js b/20_脚手架/vue_code/babel.config.js
index e955840..2767a27 100644
--- a/20_脚手架/vue_code/babel.config.js
+++ b/20_脚手架/vue_code/babel.config.js
@@ -1,5 +1,15 @@
 module.exports = {
-  presets: [
-    '@vue/cli-plugin-babel/preset'
-  ]
+    presets: [
+        '@vue/cli-plugin-babel/preset',
+        ["@babel/preset-env", {"modules": false}]
+    ],
+    plugins: [
+        [
+            "component",
+            {
+                "libraryName": "element-ui",
+                "styleLibraryName": "theme-chalk"
+            }
+        ]
+    ]
 }
diff --git a/20_脚手架/vue_code/package-lock.json b/20_脚手架/vue_code/package-lock.json
index 35f9e62..632dbcb 100644
--- a/20_脚手架/vue_code/package-lock.json
+++ b/20_脚手架/vue_code/package-lock.json
@@ -11,6 +11,7 @@
         "animate.css": "^4.1.1",
         "axios": "^1.3.2",
         "core-js": "^3.8.3",
+        "element-ui": "^2.15.13",
         "pubsub-js": "^1.9.4",
         "vue": "^2.6.14",
         "vue-resource": "^1.3.5",
@@ -24,6 +25,7 @@
         "@vue/cli-plugin-babel": "~5.0.0",
         "@vue/cli-plugin-eslint": "~5.0.0",
         "@vue/cli-service": "~5.0.0",
+        "babel-plugin-component": "^1.1.1",
         "eslint": "^7.32.0",
         "eslint-plugin-vue": "^8.0.3",
         "vue-template-compiler": "^2.6.14"
@@ -3299,6 +3301,14 @@
         "lodash": "^4.17.14"
       }
     },
+    "node_modules/async-validator": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-1.8.5.tgz",
+      "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
+      "dependencies": {
+        "babel-runtime": "6.x"
+      }
+    },
     "node_modules/asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
@@ -3346,6 +3356,11 @@
         "proxy-from-env": "^1.1.0"
       }
     },
+    "node_modules/babel-helper-vue-jsx-merge-props": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+      "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
+    },
     "node_modules/babel-loader": {
       "version": "8.3.0",
       "resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.3.0.tgz",
@@ -3379,6 +3394,36 @@
         "node": ">=8.9.0"
       }
     },
+    "node_modules/babel-plugin-component": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/babel-plugin-component/-/babel-plugin-component-1.1.1.tgz",
+      "integrity": "sha512-WUw887kJf2GH80Ng/ZMctKZ511iamHNqPhd9uKo14yzisvV7Wt1EckIrb8oq/uCz3B3PpAW7Xfl7AkTLDYT6ag==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-module-imports": "7.0.0-beta.35"
+      }
+    },
+    "node_modules/babel-plugin-component/node_modules/@babel/helper-module-imports": {
+      "version": "7.0.0-beta.35",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz",
+      "integrity": "sha512-vaC1KyIZSuyWb3Lj277fX0pxivyHwuDU4xZsofqgYAbkDxNieMg2vuhzP5AgMweMY7fCQUMTi+BgPqTLjkxXFg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "7.0.0-beta.35",
+        "lodash": "^4.2.0"
+      }
+    },
+    "node_modules/babel-plugin-component/node_modules/@babel/types": {
+      "version": "7.0.0-beta.35",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.0.0-beta.35.tgz",
+      "integrity": "sha512-y9XT11CozHDgjWcTdxmhSj13rJVXpa5ZXwjjOiTedjaM0ba5ItqdS02t31EhPl7HtOWxsZkYCCUNrSfrOisA6w==",
+      "dev": true,
+      "dependencies": {
+        "esutils": "^2.0.2",
+        "lodash": "^4.2.0",
+        "to-fast-properties": "^2.0.0"
+      }
+    },
     "node_modules/babel-plugin-dynamic-import-node": {
       "version": "2.3.3",
       "resolved": "https://registry.npmmirror.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
@@ -3427,6 +3472,27 @@
         "@babel/core": "^7.0.0-0"
       }
     },
+    "node_modules/babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmmirror.com/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+      "dependencies": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      }
+    },
+    "node_modules/babel-runtime/node_modules/core-js": {
+      "version": "2.6.12",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz",
+      "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+      "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+      "hasInstallScript": true
+    },
+    "node_modules/babel-runtime/node_modules/regenerator-runtime": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+    },
     "node_modules/balanced-match": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -4499,7 +4565,6 @@
       "version": "1.5.2",
       "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.5.2.tgz",
       "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==",
-      "dev": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -4837,6 +4902,22 @@
       "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
       "dev": true
     },
+    "node_modules/element-ui": {
+      "version": "2.15.13",
+      "resolved": "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.13.tgz",
+      "integrity": "sha512-LJoatEYX6WV74FqXBss8Xfho9fh9rjDSzrDrTyREdGb1h1R3uRvmLh5jqp2JU137aj4/BgqA3K06RQpQBX33Bg==",
+      "dependencies": {
+        "async-validator": "~1.8.1",
+        "babel-helper-vue-jsx-merge-props": "^2.0.0",
+        "deepmerge": "^1.2.0",
+        "normalize-wheel": "^1.0.1",
+        "resize-observer-polyfill": "^1.5.0",
+        "throttle-debounce": "^1.0.1"
+      },
+      "peerDependencies": {
+        "vue": "^2.5.17"
+      }
+    },
     "node_modules/emoji-regex": {
       "version": "8.0.0",
       "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -7627,6 +7708,11 @@
         "node": ">=10"
       }
     },
+    "node_modules/normalize-wheel": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
+      "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA=="
+    },
     "node_modules/npm-run-path": {
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -9059,6 +9145,11 @@
       "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
       "dev": true
     },
+    "node_modules/resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+    },
     "node_modules/resolve": {
       "version": "1.22.1",
       "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz",
@@ -9931,6 +10022,14 @@
         "node": ">= 10.13.0"
       }
     },
+    "node_modules/throttle-debounce": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
+      "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/thunky": {
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz",
@@ -13650,6 +13749,14 @@
         "lodash": "^4.17.14"
       }
     },
+    "async-validator": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-1.8.5.tgz",
+      "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
+      "requires": {
+        "babel-runtime": "6.x"
+      }
+    },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
@@ -13685,6 +13792,11 @@
         "proxy-from-env": "^1.1.0"
       }
     },
+    "babel-helper-vue-jsx-merge-props": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+      "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
+    },
     "babel-loader": {
       "version": "8.3.0",
       "resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.3.0.tgz",
@@ -13710,6 +13822,38 @@
         }
       }
     },
+    "babel-plugin-component": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/babel-plugin-component/-/babel-plugin-component-1.1.1.tgz",
+      "integrity": "sha512-WUw887kJf2GH80Ng/ZMctKZ511iamHNqPhd9uKo14yzisvV7Wt1EckIrb8oq/uCz3B3PpAW7Xfl7AkTLDYT6ag==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-module-imports": "7.0.0-beta.35"
+      },
+      "dependencies": {
+        "@babel/helper-module-imports": {
+          "version": "7.0.0-beta.35",
+          "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz",
+          "integrity": "sha512-vaC1KyIZSuyWb3Lj277fX0pxivyHwuDU4xZsofqgYAbkDxNieMg2vuhzP5AgMweMY7fCQUMTi+BgPqTLjkxXFg==",
+          "dev": true,
+          "requires": {
+            "@babel/types": "7.0.0-beta.35",
+            "lodash": "^4.2.0"
+          }
+        },
+        "@babel/types": {
+          "version": "7.0.0-beta.35",
+          "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.0.0-beta.35.tgz",
+          "integrity": "sha512-y9XT11CozHDgjWcTdxmhSj13rJVXpa5ZXwjjOiTedjaM0ba5ItqdS02t31EhPl7HtOWxsZkYCCUNrSfrOisA6w==",
+          "dev": true,
+          "requires": {
+            "esutils": "^2.0.2",
+            "lodash": "^4.2.0",
+            "to-fast-properties": "^2.0.0"
+          }
+        }
+      }
+    },
     "babel-plugin-dynamic-import-node": {
       "version": "2.3.3",
       "resolved": "https://registry.npmmirror.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
@@ -13749,6 +13893,27 @@
         "@babel/helper-define-polyfill-provider": "^0.3.3"
       }
     },
+    "babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmmirror.com/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+      "requires": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      },
+      "dependencies": {
+        "core-js": {
+          "version": "2.6.12",
+          "resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz",
+          "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
+        },
+        "regenerator-runtime": {
+          "version": "0.11.1",
+          "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+          "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+        }
+      }
+    },
     "balanced-match": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -14613,8 +14778,7 @@
     "deepmerge": {
       "version": "1.5.2",
       "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.5.2.tgz",
-      "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==",
-      "dev": true
+      "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ=="
     },
     "default-gateway": {
       "version": "6.0.3",
@@ -14884,6 +15048,19 @@
       "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
       "dev": true
     },
+    "element-ui": {
+      "version": "2.15.13",
+      "resolved": "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.13.tgz",
+      "integrity": "sha512-LJoatEYX6WV74FqXBss8Xfho9fh9rjDSzrDrTyREdGb1h1R3uRvmLh5jqp2JU137aj4/BgqA3K06RQpQBX33Bg==",
+      "requires": {
+        "async-validator": "~1.8.1",
+        "babel-helper-vue-jsx-merge-props": "^2.0.0",
+        "deepmerge": "^1.2.0",
+        "normalize-wheel": "^1.0.1",
+        "resize-observer-polyfill": "^1.5.0",
+        "throttle-debounce": "^1.0.1"
+      }
+    },
     "emoji-regex": {
       "version": "8.0.0",
       "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -17099,6 +17276,11 @@
       "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
       "dev": true
     },
+    "normalize-wheel": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
+      "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA=="
+    },
     "npm-run-path": {
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -18170,6 +18352,11 @@
       "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
       "dev": true
     },
+    "resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+    },
     "resolve": {
       "version": "1.22.1",
       "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz",
@@ -18888,6 +19075,11 @@
         }
       }
     },
+    "throttle-debounce": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
+      "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg=="
+    },
     "thunky": {
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz",
diff --git a/20_脚手架/vue_code/package.json b/20_脚手架/vue_code/package.json
index 94c96bc..3c55000 100644
--- a/20_脚手架/vue_code/package.json
+++ b/20_脚手架/vue_code/package.json
@@ -11,6 +11,7 @@
     "animate.css": "^4.1.1",
     "axios": "^1.3.2",
     "core-js": "^3.8.3",
+    "element-ui": "^2.15.13",
     "pubsub-js": "^1.9.4",
     "vue": "^2.6.14",
     "vue-resource": "^1.3.5",
@@ -24,6 +25,7 @@
     "@vue/cli-plugin-babel": "~5.0.0",
     "@vue/cli-plugin-eslint": "~5.0.0",
     "@vue/cli-service": "~5.0.0",
+    "babel-plugin-component": "^1.1.1",
     "eslint": "^7.32.0",
     "eslint-plugin-vue": "^8.0.3",
     "vue-template-compiler": "^2.6.14"
diff --git a/20_脚手架/vue_code/src/App.vue b/20_脚手架/vue_code/src/App.vue
index 14872a9..ee75bfa 100644
--- a/20_脚手架/vue_code/src/App.vue
+++ b/20_脚手架/vue_code/src/App.vue
@@ -1,34 +1,39 @@