{"id":21541878,"url":"https://github.com/wxlvip/elementdec","last_synced_at":"2026-05-18T14:35:50.251Z","repository":{"id":57400524,"uuid":"430556959","full_name":"wxlvip/ElementDec","owner":"wxlvip","description":"Element UI Deconstruction 项目是为了学习 Element 而创建，在各文件中添加详细的注释，并对原有组件进行优化迭代，以便帮助新手理解源码，并可以按照自己项目需求进行增量开发。","archived":false,"fork":false,"pushed_at":"2022-01-11T03:15:22.000Z","size":2684,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-04T03:59:35.842Z","etag":null,"topics":["element-ui","vue","webpack"],"latest_commit_sha":null,"homepage":"","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wxlvip.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.en-US.md","contributing":".github/CONTRIBUTING.en-US.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-22T04:02:17.000Z","updated_at":"2022-01-11T03:15:24.000Z","dependencies_parsed_at":"2022-09-05T00:41:12.202Z","dependency_job_id":null,"html_url":"https://github.com/wxlvip/ElementDec","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wxlvip/ElementDec","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wxlvip%2FElementDec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wxlvip%2FElementDec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wxlvip%2FElementDec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wxlvip%2FElementDec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wxlvip","download_url":"https://codeload.github.com/wxlvip/ElementDec/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wxlvip%2FElementDec/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":282007156,"owners_count":26598240,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-31T02:00:07.401Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["element-ui","vue","webpack"],"created_at":"2024-11-24T05:07:54.857Z","updated_at":"2025-10-31T15:04:24.846Z","avatar_url":"https://github.com/wxlvip.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cdn.rawgit.com/ElemeFE/element/dev/element_logo.svg\" alt=\"\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://travis-ci.org/ElemeFE/element\"\u003e\n    \u003cimg src=\"https://travis-ci.org/ElemeFE/element.svg?branch=master\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://coveralls.io/github/ElemeFE/element?branch=master\"\u003e\n    \u003cimg src=\"https://coveralls.io/repos/github/ElemeFE/element/badge.svg?branch=master\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://cdnjs.com/libraries/element-ui\"\u003e\n    \u003cimg src=\"https://img.shields.io/cdnjs/v/element-ui.svg\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.org/package/element-ui\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/element-ui.svg\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://npmcharts.com/compare/element-ui?minimal=true\"\u003e\n    \u003cimg src=\"http://img.shields.io/npm/dm/element-ui.svg\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003cbr\u003e\n  \u003ca href=\"http://img.badgesize.io/https://unpkg.com/element-ui/lib/index.js?compression=gzip\u0026label=gzip%20size:%20JS\"\u003e\n    \u003cimg src=\"http://img.badgesize.io/https://unpkg.com/element-ui/lib/index.js?compression=gzip\u0026label=gzip%20size:%20JS\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"http://img.badgesize.io/https://unpkg.com/element-ui/lib/theme-chalk/index.css?compression=gzip\u0026label=gzip%20size:%20CSS\"\u003e\n    \u003cimg src=\"http://img.badgesize.io/https://unpkg.com/element-ui/lib/theme-chalk/index.css?compression=gzip\u0026label=gzip%20size:%20CSS\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"#backers\"\u003e\n    \u003cimg src=\"https://opencollective.com/element/backers/badge.svg\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"#sponsors\"\u003e\n    \u003cimg src=\"https://opencollective.com/element/sponsors/badge.svg\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" alt=\"\"/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003e A Vue.js 2.0 UI Toolkit for Web.\n\nElement will stay with Vue 2.x\n\nFor Vue 3.0, we recommend using [Element Plus](https://github.com/element-plus/element-plus) from the same team\n\n\n## 基本说明\n\nElement版本:element-2.15.7\n\n思想：健壮、可扩展、解耦、易维护\n\n官方文档：[https://element.eleme.cn/#/zh-CN](https://element.eleme.cn/#/zh-CN)\n\nGithub地址：[https://github.com/ElemeFE/element](https://github.com/ElemeFE/element)\n\n\u003e说明：Element UI Deconstruction 项目是为了学习 Element 而创建，新增 docs 文档目录，将解构的理解更新在该文件夹下，并会在各文件中添加详细的注释，以便帮助新手理解源码。\n\u003e\n\u003e除了新增的部分说明文件外，其他大部分为 `Element-2.15.7` 版本的源码，仅供学习之用。\n\u003e \n\u003e由于 element 官方也在维护组件库，代码可能会更新，因此该说明文档的代码难免会与最新源码有出入，所以我这里注明了版本号，大家注意下即可。\n\n## 目录  \n```\nElement-2.15.7\n├──.github：存放了Element UI贡献指南、issue和PR模板\n├──build：存放了打包相关的配置文件,项目构建命令的目录\n│   ├──bin\n│   │   ├──build-entry.js:根据components.json中组件的列表，结合字符串模板生成组件库的入口文件src/index.js\n│   │   ├──build-locale.js\n│   │   ├──gen-cssfile.js\n│   │   ├──gen-indices.js\n│   │   ├──i18n.js:为examples/pages中的模板文件生成不同语言的vue文件到examples/pages/[语言]/\n│   │   ├──iconInit.js:从packages/theme-chalk/src/icon.scss文件中提取字体图标的类名到examples/icon.json中\n│   │   ├──new.js\n│   │   ├──new-lang.js\n│   │   ├──template.js\n│   │   └──version.js:生成版本字符串数组到examples/version.json中，文档会使用\n│   └──webpack.test.js\n├──examples：文档目录，组件相关示例 demo,这是一个完整独立的Vue项目\\\n│   ├──components:主题及主题编辑器相关页面\n│   │   ├──theme // 主题页面相关\n│   │   │   ├──loader\n│   │   │   ├──color.js\n│   │   ├──theme-configurator // 主题编辑器相关\n│   │   │   ├──editor\n│   │   │   ├──utils\n│   │   │   ├──action.vue\n│   │   │   ├──index.vue\n│   │   │   ├──main.vue\n│   │   │   └──shortcut.vue\n│   │   ├──demo-block.vue\n│   │   ├──footer.vue\n│   │   ├──footer-nav.vue\n│   │   ├──header.vue\n│   │   ├──search.vue\n│   │   ├──side-nav.vue\n│   │   └──theme-picker.vue \n│   ├──docs:每一个md文档，分别对应着官网组件的展示页面 修改官网组件页面就在该目录下修改，通过项目组编写的 md-loader 进行转换成 vue 文件\n├──lib： 构建后生成的文件，发布到npm包\n├──packages：组件源码和组件样式文件\n│   ├── alert              // 具体组件源码包\n│   │   ├── src            // Vue组件包\n│   │   └── index.js       // 入口文件\n│   ├──theme-chalk：这里面存放的就是所有组件相关的样式，里面有index.scss（用于全局引入时导出所有组件样式）和其他每个组件对应的scss文件（用于按需引入时导出对应的组件样式）\n│   └── 89个文件夹 80种组件\n├──src：存放入口文件和一些工具辅助函数\\把所有的组件做一个统一处理，同时包含自定义指令、项目整体入口、组件国际化、组件 mixins、动画的封装和公共方法\n│   ├──directives:放置自定义指令，实现滚轮优化，鼠标点击优化\n│   │   ├──mousewheel.js:主要使用mousewheel.js（https://github.com/basilfx/normalize-wheel）来实现鼠标滚轮事件。应用在table组件中，如“固定表头”，“流体高度”中。\n│   │   └──repeat-click.js:就是“函数防抖”！主要用在InputNumber 计数器中，控制用户点击频率。请参考https://www.cnblogs.com/mengfangui/p/9515993.html。\n│   ├──locale：放置语言的配置文件，i18n国际化\n│   ├──mixins：Vue混合器，放置组件用的混合文件\n│   │   ├─emitter.js：广播和分发函数\n│   │   ├─focus.js：使dom元素获取焦点\n│   │   ├─locale.js：国际化输出\n│   │   └──migrating.js：主要目的是在浏览器控制台输出 element ui已经移除的一些属性\n│   ├──transitions：样式过渡效果，放置动画配置文件\n│   ├──utils：工具类包，放置用到工具函数文件\n│   │   ├─menu\n│   │   ├─popup\n│   │   ├─after-leave.js\n│   │   ├─aria-dialog.js\n│   │   ├─aria-utils.js\n│   │   ├─clickoutside.js:点击元素外面才会触发的事件\n│   │   ├─date.js:日期格式化js,修改自fecha：https://github.com/taylorhakes/fecha\n│   │   ├─date-util.js\n│   │   ├─dom.js:对dom元素进行操作，如hasClass，addClass，removeClass，getStyle，setStyle，on（绑定事件），off（解除事件）\n│   │   ├─merge.js\n│   │   ├─popper.js\n│   │   ├─resize-event.js\n│   │   ├─scroll-into-view.js\n│   │   ├─scrollbar-width.js\n│   │   ├─shared.js\n│   │   ├─types.js\n│   │   ├─util.js:定义一些常用函数：hasOwn，getValueByPath，valueEquals。\n│   │   ├─vdom.js:vnode判断，vodne获取\n│   │   └──vue-popper.js\n│   └──index.js :源码入口文件，组件注册入口，自动生成的。导入了 packages 下的所有组件;对外暴露了install方法，把所有的组件注册到Vue上面，并在Vue原型上挂载了一些全局变量和方法;最终将install方法、变量、方法导出\n├──test：单元测试相关文件，这也是一个优秀的开源项目必备的\n│   ├── ssr                //\n│   └── unit               // 单元测试目录\n│       ├── coverage       // 单元测试覆盖率包\n│       ├── mocks\n│       ├── specs          // 测试用例源码包\n│       ├── index.js       // 测试入口\n│       ├── karma.conf.js  // karma配置文件\n│       └── utils.js       // 工具类\n├──types：typescript文件包，类型声明文件\n│\n├──.babelrc: babel 配置文件\n├──.eslintignore：eslint忽略文件配置\n├──.eslintrc：eslint 配置文件\n├──.gitattributes：git 的隐藏文件\n├──.gitignore：git忽略文件配置\n├──.travis.yml：持续集成(CI)的配置文件\n├──CHANGELOG.en-US.md：更新日志，这里Element UI提供了四种不同语言的\n├──CHANGELOG.es.md：\n├──CHANGELOG.fr-FR.md：法语\n├──CHANGELOG.zh-CN.md：中文\n├──components.json：配置文件，标明了组件的文件路径，方便 webpack 打包时获取组件的文件路径。在自动化生成文件以及入口时会用到，该文件通过 `Makefile` 也是可以自动化生成的。\n├──element_logo.svg：ElementUI 的图标，使用了 svg 格式\n├──FAQ.md:ElementUI 开发者对常见问题的解答。\n├──LICENSE：开源许可证，Element UI使用的是MIT协议\n├──Makefile：Makefile 是一个适用于 C/C++ 的工具，在拥有 make 环境的目录下， 如果存在一个 Makefile 文件。 那么输入 make 命令将会执行 Makefile 文件中的某个目标命令。\n├──package.json：npm包核心文件，包管理\n├──README.md：说明文档\n└──yarn.lock：使用yarn进行包版本锁定\n```\n\n\u003e关于Makefile 文件：\\\nMakefile 是一个适用于 C/C++ 的工具，较早作为工程化工具出现在 UNIX 系统中， 通过 make 命令来执行一系列的编译和连接操作。在拥有 make 环境的目录下， 如果存在一个 Makefile 文件。 那么输入 make 命令将会执行 Makefile 文件中的某个目标命令。\n[前端入门-\u003emakefile](https://segmentfault.com/a/1190000004437816#articleHeader11)\n\u003e \n\u003e在 .github 文件夹下的贡献指南中提到过，组件开发规范中的第一条：通过 make new 创建组件目录结构，包含测试代码、入口文件、文档。其中 make new 就是 make 命令中的一种。make 命令是一个工程化编译工具，而 Makefile 定义了一系列的规则来制定文件变异操作，常常使用 Linux 的同学应该不会对 Makefile 感到陌生。\n\u003e \n\u003eTip:\\\nmake new \u003ccomponent-name\u003e [中文]\\\n1、将新建组件添加到components.json\\\n2、添加到index.scss\\\n3、添加到element-ui.d.ts\\\n4、创建package\\\n5、添加到nav.config.json\\\n\u003e \n\u003e这里我以make install为例简要说明下执行流程：\\\n1.执行 make 命令， 在该目录下找到 Makefile 文件。\\\n2.找到 Makefile 文件中对应命令行参数的 install 目标。这里的目标就是 npm install\n\n\n## 启动\n\n首先你需要 Node.js 4+，yarn 和 npm 3+。注意：我们使用 yarn 进行依赖版本的锁定，所以请不要使用 npm install 安装依赖。\n```shell\ngit clone git@github.com:wxlvip/ElementDec.git\nnpm run dev\n# or\nyarn dev\n\n// 启动调试\nyarn dev:play\n\n# open http://localhost:8085\n```\n\n\n\n```shell\nnpm run dist\n```\n运行`make new\u003ccomponent-name\u003e`为新组件创建项目目录。包括测试代码、入门文件和文档。代码样式,只需遵循ElemeFE的ESLint配置即可。\n\n\n## 创建组件\n\n1. 编写组件代码\n2. 为组件创建文档\n3. 为组件创建单元测试\n\n### 编写组件\n\n这里以一个hello-world组件为例。效果如下图，接收一个属性name，输出Hello, {undefined{ name }}\n\n1. 在packages下创建hello-world目录,文件结构如下\n\n```\n   packages\n   ├──hello-world(新增)\n   │    ├──src(新增)\n   │    │   └──main.vue(新增)\n   │    └──index.js(新增)\n   └──theme\n        └──chalk\n            └──src\n                └──hello-world.scss(新增)\n```\n\n3. 在hello-world中创建index.js和src/main.vue\n\nindex.js\n```js\n// index.js\nimport HelloWorld from './src/main';\n/* istanbul ignore next */\nHelloWorld.install = function(Vue) {\nVue.component(HelloWorld.name, HelloWorld);\n};\nexport default HelloWorld;\n```\nsrc/main.vue 真实项目中写组件一定要构思和确定好，要可以扩展和新增功能，因为后期改动的成本很大，所以 涉及的三大块 props、event 和 slot 要认真思考\n其中name跟使用组件有关如果name为 `ElHelloWorld` 则在页面中使用组件的方式为 `\u003cel-hello-world\u003e\u003c/el-hello-world\u003e`,如果name 为 `WxlHeader` 则使用组件时为`\u003cwxl-header\u003e\u003c/wxl-header\u003e`\n```vue\n\u003ctemplate\u003e\n  \u003cdiv class=\"el-hello-world\"\u003e\n    Hello, \u003ca :href=\"url\" target=\"_blank\"\u003e{{ name }}\u003c/a\u003e\n    \u003cspan\u003e\u003cslot\u003e\u003c/slot\u003e\u003c/span\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\u003cscript\u003e\nexport default {\n  name: 'ElHelloWorld',\n  props: ['name', 'url'],\n  // props: {\n  //   name: String,\n  //   url: String\n  // },\n  data() {\n    return {};\n  }\n};\n\u003c/script\u003e\n```\n\n3. 在packages/theme-chalk/src下添加 hello-world.scss,之后执行 `yarn build:file` 进行编译生成 css 文件\n```css\n@charset \"UTF-8\";\n@import \"common/var\";\n@import \"mixins/button\";\n@import \"mixins/mixins\";\n@import \"mixins/utils\";\n\n@include b(hello-world) {\n    display: inline-block;\n    line-height: 1;\n    white-space: nowrap;\n    cursor: pointer;\n}\n```\n写好 CSS 样式之后，要执行 `yarn build:file` 命令进行编译生成。注意：`el-`前缀是系统自动添加，无需在样式中添加\n\n4. 在components.json中注册hello-world组件\n```shell\n\"hello-world\": \"./packages/hello-world/index.js\"\n```\n\n### 添加文档\n在 examples/docs/zh-CN 下添加 hello-world.md\n在 examples/nav.config.json 中注册 对应的就是官方文档:组件/左侧列表 按照自上而下顺序存储，注册时要几种语言都要注册以便在不同语言下都能显示\n```\n// 页面中引入指令名称，同组件名称一致\n\u003cel-hello-world\u003e你好世界\u003c/el-hello-world\u003e\n```\n\n### 添加测试\n在test/unit/specs下创建hello-world.spec.js\n\n```js\nimport {createTest} from '../util';\nimport HelloWorld from 'packages/hello-world/index';\n\ndescribe.only('test HelloWorld', () =\u003e {\n    const name = '测试hello-world组件';\n    const vm = createTest(HelloWorld, {\n        name\n    }, true);\n    it('there should be .hello-world', () =\u003e {\n        expect(vm.$el.classList.contains('hello-world')).to.be.true;\n    });\n    it('should contains name', () =\u003e {\n        expect(vm.$el.textContent).to.contains(name);\n    });\n});\n```\n\n`npm run test:watch` 运行\n因为单元测试太多了，我们只想测试自己的组件，所以上面的测试我加了only，这样就只会跑这个测试了，等开发完组件，要把这个干掉的。\n\n\n## 测试\n\n### 在文档中进行测试\n\n1. 可以在文档中 examples/docs/zh-CN/hello-world.md 中添加代码段直接使用组件进行测试，如果样式没有出来或者没有被解析，可能是组件书写存在错误的地方\n    ```html\n    \u003cel-hello-world class=\"el-hello-world\" name=\"world\" url=\"https://www.baidu.com/\"\u003e\n        我是新组件 hello-world 插槽内容\n    \u003c/el-hello-world\u003e\n    \u003cscript\u003e\n        export default {\n            data() {\n                return {\n                }\n            },\n            methods: {\n                onSubmit() {\n                    console.log('submit!');\n                }\n            }\n        }\n    \u003c/script\u003e\n    ```\n2. 执行 `npm run dev` 命令，启动项目，过程较慢要有耐心\n3. 打开 `http://localhost:8085/#/zh-CN/` 文档主页，并切换到 `组件` 菜单，打开 `HelloWorld 你好世界` 组件页面，可观察到效果（完整路径为：http://localhost:8085/#/zh-CN/component/hello-world）\n\n### 管方提供测试方式\n\n在 `examples/play/index.vue` 中测试\n\u003e 修改 `examples/play/index.vue` 文件, 在页面中直接使用你自定义的组件, 然后运行`npm run dev:play`,访问 [http://localhost:8085](http://localhost:8085), 获取运行结果,这种方式启动更快更友好.\n\n```vue\n\u003ctemplate\u003e\n  \u003cdiv style=\"margin: 20px;\"\u003e\n    \u003cel-input v-model=\"input\" placeholder=\"请输入内容\"\u003e\u003c/el-input\u003e\n    \u003cel-hello-world class=\"el-hello-world\" name=\"world\" url=\"https://www.wxlvip.com/\"\u003e我是新组件 hello-world 插槽内容\u003c/el-hello-world\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\n  export default {\n    data() {\n      return {\n        input: 'Hello Element UI!'\n      };\n    }\n  };\n\u003c/script\u003e\n\n```\n\n### 本地环境测试\n\n将项目通过 `npm run dist` 命令进行打包，将在根目录生成的 lib 文件，替换掉项目中的 `node_modules\\element-ui\\lib` 文件，重启项目即可直接在项目中使用并调试新增组件。(本测试方法及 `npm run dist` 命令存在的问题，在下面打包环节有有介绍)\n\n\n## 样式\n\n### 基本说明\n- element 样式用的是 sass, 文件后缀为 `scss`,样式文件存放路径为 `packages/theme-chalk/src` 样式名称为各组件名称，例如：hello-world.scss\n- 公共样式配置是在 `packages/theme-chalk/src/common/var.scss` 文件中，包含色彩、背景色、边框以及其他组件的公共样式的配置。\n- mixins 变量配置文件：`packages/theme-chalk/src/mixins/config.scss`，其中，样式前缀 `el` 的配置也在其中\n- mixins 函数配置文件：`packages/theme-chalk/src/mixins/mixins.scss`，sass 的 mixin 函数可以在该文件中进行定义\n\nelement的样式：\n```scss\n@include when(disabled) {\n  .el-input__inner {\n      background-color: $--input-disabled-fill;\n      border-color: $--input-disabled-border;\n      color: $--input-disabled-color;\n      cursor: not-allowed;\n\n      \u0026::placeholder {\n        color: $--input-disabled-placeholder-color;\n      }\n    }\n \n    .el-input__icon {\n      cursor: not-allowed;\n    }\n}\n```\n在看下最后编译的class命名：\n```css\n.el-input--medium .el-input__inner {\n   height: 36px;\n   line-height: 36px;\n}\n.el-input--suffix .el-input__inner {\n    padding-right: 30px;\n}\n```\n可以看出命名规则是BEM 命名规范（ [了解更多](https://zhuanlan.zhihu.com/p/33188830) ）B(代表块)__E(代表元素)--M(代表修饰符)\n\n### 样式前缀\n\n`el-` 前缀所在配置文件路径 `packages/theme-chalk/src/mixins/config.scss` 部分样式是直接写在scss中写死的，部分是通过 `packages/theme-chalk/src/mixins/mixins.scss` 中的 b 函数更改的\n为了避免之前 Element 原有样式出问题，最好是新增一个函数和前缀配置，进行更改新增css代码部分的前缀。保证原有组件的写法与样式使用Element的规范，新增组件启用自己定义的规范，以便向前兼容。\n\n### 色调\n\n全局色调配置文件路径 `packages/theme-chalk/src/common/var.scss` 在该文件中可以配置包括但不限于：\n\n主要品牌色：primary\n\n背景色：white、black、primary-light-1...(1-9)...primary-light-9\n\n辅助功能场景色：success(成功)、warning(警告)、danger(危险)、info(信息)、success-light、warning-light、danger-light、info-light、success-lighter、warning-lighter、danger-lighter、info-lighter\n\n其他还有 文本色、边框色等，各组件基础样式也是在该文件中进行配置\n\n### 主题\n\n主题主页所在路径为：`examples/pages/zh-CN/theme.vue`，访问路径为 `http://localhost:8085/#/zh-CN/theme`\\\n单个主题编辑页面：`examples/pages/zh-CN/theme-preview.vue` 访问路径 `http://localhost:8085/#/zh-CN/theme/preview`，该页面由以下几部分组成：\n- `examples/components/theme/basic-tokens-preview.vue` 页面左侧区域 第一屏组件展示包括 Color \u0026\u0026 Typography\n- `examples/components/theme/components-preview.vue` 页面左侧区域 第二屏及更多组件展示\n- `examples/components/theme-configurator/index.vue` 页面右侧区域-属性配置器\n\n```\ncomponents:主题及主题编辑器相关页面\n├──theme // 主题页面相关\n│   ├──loader\n│   ├──basic-tokens-preview.vue 页面左侧区域 第一屏组件展示包括 Color \u0026\u0026 Typography\n│   ├──color.js\n│   ├──components-preview.vue 页面左侧区域 第二屏及更多组件展示\n│   ├──constant.js\n│   ├──localstorage.js\n│   ├──theme-card.vue 主题页面遍历的 主题card 模板，如:官方主题、我的主题\n│   ├──theme-list.js\n│   └──utils.js\n├──theme-configurator // 主题编辑器相关\n│   ├──editor\n│   ├──utils\n│   ├──action.vue 属性编辑器头部工具栏 包括撤销、重做、重置、下载、选择组件\n│   ├──index.vue 页面右侧区域-属性配置器\n│   ├──main.vue\n│   └──shortcut.vue\n├──demo-block.vue\n├──footer.vue\n├──footer-nav.vue\n├──header.vue\n├──search.vue\n├──side-nav.vue\n└──theme-picker.vue \n```\n\n通过分析该页面可知，主题页面遍历的主题card模板所在路径为：`examples/components/theme/theme-card.vue`，而页面展示的主题数据配置文件路径在 `examples/components/theme/theme-list.js`\n\n`examples/components/theme/loader/api.js` 配置主题 or 获取主题 同服务器交互文件\n`examples/components/theme/loader/ajax.js` 官方封装的 Ajax 用于主题的配置和获取\n\n因为主题配置，官网是通过服务器请求完成的，所以本地下载的源码是不能使用的，要自己建立服务器或者在前端增加这部分功能。\n\n页面编辑器\\\n`examples/components/theme-configurator/index.vue` 主题配置页面,默认配置也在该页面中，样式编辑器触发的方法为 userConfigChange 可以在该方法中获取到变动的数据的键值对，并 调用 updateVariable 接口方法\n\n`examples/components/theme-configurator/main.vue` 左侧区域\n\n`examples/components/theme-configurator/action.vue` 右侧编辑区域\n\n`examples/components/theme/loader/index.vue` updateVars 提交变更的配置值作为参数并请求返回改变后的css样式值(即新的主题)，用于改变页面样式\n\n`examples/components/theme/loader/index.vue` 下载调用的方法也在该页面\n\n\n服务器部分？\n\n- getVariable 方法\\\n   `https://element-api.ele.me/element/theme/getVariable?version=2.15.7` 获取默认主题样式\n- updateVars\\\n   `https://element-api.ele.me/element/theme/updateVariable?version=2.15.7` 传递参数为 global 返回结果为css,当初传\n\n```\n// 改变配置时参数 结果：返回css样式\n{\n  \"global\": {\n      \"$--color-primary\": \"#47CBC2\"\n  },\n  \"local\": {}\n}\n// 下载的时候的参数 \"download\": true 结果：下载文件\n{\n    \"global\": {\n        \"$--color-primary\": \"#0BE109\"\n    },\n    \"local\": {},\n    \"download\": true\n}\n```\n\n 通过访问以下链接 `//unpkg.com/element-ui@${version}/lib/theme-chalk/index.css` 可获得不同版本的主题样式，本项目使用的是 2.15.7 版本，`https://unpkg.com/element-ui@2.15.7/lib/theme-chalk/index.css`\n\n通过 theme-chalk-preview 将配置的css样式进行重新生成，并写入到文档页面的head中，以改变文档的主题样式，并提供下载功能，可供项目组下载直接在项目中引入，以改变主题颜色。通过该方法可切断同服务器的交互，使得主题配置服务全部由前端提供。\n\nhttp://github.com/ElementUI/theme-chalk-preview/archive/refs/heads/master.zip\nhttps://segmentfault.com/a/1190000009762198#articleHeader2\n思路：\\\n1. 先把默认主题文件中涉及到颜色的 CSS 值替换成关键词\n2. 根据用户选择的主题色生成一系列对应的颜色值\n3. 把关键词再换回刚刚生成的相应的颜色值\n4. 直接在页面上加 style 标签，把生成的样式填进去\n\n## 组件\n\n1. 修改组件安装前缀\n\n```\n\u003cel-hello-world\u003e我是新组件 hello-world 插槽内容\u003c/el-hello-world\u003e\n// 转换成\n\u003cmti-hello-world\u003e我是新组件 hello-world 插槽内容\u003c/mti-hello-world\u003e\n```\n```\n// 需要将 组件的 name 属性由 ElHelloWorld 改为 MtiHelloWorld\n\u003cscript\u003e\nexport default {\n  name: 'ElHelloWorld',\n  props: {\n     name: String,\n     url: String\n  },\n  data() {\n    return {};\n  }\n};\n\u003c/script\u003e\n// 修改后\n\u003cscript\u003e\nexport default {\n  name: 'MtiHelloWorld',\n  props: {\n     name: String,\n     url: String\n  },\n  data() {\n    return {};\n  }\n};\n\u003c/script\u003e\n```\n\n## 打包\n\n使用以下命令打包:\n```shell\n\"dist\": \"npm run clean \u0026\u0026 npm run build:file \u0026\u0026 npm run lint \u0026\u0026 webpack --config build/webpack.conf.js \u0026\u0026 webpack --config build/webpack.common.js \u0026\u0026 webpack --config build/webpack.component.js \u0026\u0026 npm run build:utils \u0026\u0026 npm run build:umd \u0026\u0026 npm run build:theme\"\n```\n\n直接执行 `npm run dist` 命令会卡在 webpack 打包这一步执行不下去，将命令拆分开，单独执行就可以。该命令生成的文件均在根目录下的 `lib` 文件夹下\n\n```shell\nnpm run clean \u0026\u0026 npm run build:file \u0026\u0026 npm run lint\n\nwebpack --config build/webpack.conf.js\n\nwebpack --config build/webpack.common.js\n\nwebpack --config build/webpack.component.js\n\nnpm run build:utils \u0026\u0026 npm run build:umd \u0026\u0026 npm run build:theme\n```\n\n- `npm run clean` 清空 lib 文件夹\n- `npm run build:file`\n- `npm run lint` 使用 Eslint 检查代码\n- `webpack --config build/webpack.conf.js` 打包生成入口文件 `index.js`\n- `webpack --config build/webpack.common.js` 打包生成 `element-ui.common.js` 文件\n- `webpack --config build/webpack.component.js` 打包生成各组件单独的文件，便于按需加载使用\n- `npm run build:utils` 生成 lib 下的 directives、locale、mixins、theme-chalk、transitions、utils\n- `npm run build:umd` 生成 lib 下的 umd 文件夹。\n- `npm run build:theme` 生成 lib 下的 theme-chalk\n\n对已打包文件进行测试，可以将打包好的文件，替换掉项目中的 `node_modules\\element-ui\\lib` 文件，重启项目即可直接在项目中使用并调试新增组件。\n\n发布的包（即项目中下载的 node_modules\\element-ui 目录下的文件）的目录结构如下：\n\n```\nwxl-ui\n├──lib // 通过 dist 命令打包生成的文件夹\n├──packages // 组件源码包\n├──src // 入口文件和一些工具辅助函数\n├──types // TS 类型声明文件\n├──CHANGELOG.en-US.md\n├──CHANGELOG.es.md\n├──CHANGELOG.fr-FR.md\n├──CHANGELOG.zh-CN.md\n├──LICENSE // 开源许可证\n├──package.json // npm 核心包管理文件\n└──README.md // 说明文档\n```\n\n### 打包流程\n\n![](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/23/172df2c6a4ca6dd8~tplv-t2oaga2asx-watermark.awebp)\n\n\n## 发布\n\n1. 注册 npm 账号\n2. 打包文件，将打包文件上传\n\n[comment]: \u003c\u003e (1.打包之后的 lib/element-ui.common.js 文件中 引用的 element-ui路径跟新，创建的npm包名不一致，需要替换更改)\n\n[comment]: \u003c\u003e (2. 组件 cascader-panel.js 中引入的其他包的路径 也为 element-ui)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/cascader-panel.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/checkbox' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (3.组件 select.js 同上16处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/select.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/input' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (4.组件 input-number.js 同上5处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/input-number.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/input' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (8.lib/input.js 同上8处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/input.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/mixins/emitter' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (9.lib/checkbox.js 同上2处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/checkbox.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/mixins/emitter' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (10.lib/checkbox-group.js 同上2处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/checkbox-group.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/mixins/emitter' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (11.lib/option.js 同上4处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/option.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/mixins/emitter' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (12.lib/radio.js  同上2处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/radio.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/mixins/emitter' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (13.lib/scrollbar.js 同上8处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/scrollbar.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/dom' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (14.lib/tooltip.js 同上6处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/tooltip.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/dom' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n[comment]: \u003c\u003e (15.lib/popover.js 同上6处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/popover.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/dom' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib')\n\n\n\n[comment]: \u003c\u003e (5.lib/mixins/locale.js 同上1处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/mixins/locale.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/locale' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\mixins')\n\n[comment]: \u003c\u003e (23.lib/mixins/migrating.js 同上2处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/mixins/migrating.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/util' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\mixins')\n\n\n[comment]: \u003c\u003e (6.lib/utils/date-util.js 同上2处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/date-util.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/locale' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\utils')\n\n[comment]: \u003c\u003e (17.lib/utils/clickoutside.js 同上1处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/clickoutside.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/dom' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\utils')\n\n[comment]: \u003c\u003e (18.lib/utils/popup/index.js 同上2处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/popup/index.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/merge' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\utils\\popup')\n\n[comment]: \u003c\u003e (19.lib/utils/popup/popup-manager.js 同上1处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/popup/popup-manager.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/dom' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\utils\\popup')\n\n[comment]: \u003c\u003e (20.lib/utils/vue-popper.js 同上1处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/vue-popper.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/popup' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\utils')\n\n[comment]: \u003c\u003e (21.lib/utils/util.js 同上1处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/util.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/types' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\utils')\n\n[comment]: \u003c\u003e (24.lib/utils/vdom.js 同上1处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/vdom.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/util' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\utils')\n\n\n[comment]: \u003c\u003e (7.lib/locale/index.js 同上1处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/locale/index.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/locale/lang/zh-CN' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\locale')\n\n[comment]: \u003c\u003e (22.lib/locale/format.js 同上1处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/locale/format.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/util' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\locale')\n\n\n[comment]: \u003c\u003e (16.lib/transitions/collapse-transition.js 同上1处)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/transitions/collapse-transition.js)\n\n[comment]: \u003c\u003e (Module not found: Error: Can't resolve 'element-ui/lib/utils/dom' in 'D:\\www\\wxl\\node_modules\\wxl-ui\\lib\\transitions')\n\n[comment]: \u003c\u003e (在打包的时候修改配置文件 config 中的路径目录)\n\n[comment]: \u003c\u003e (原本就是require 无需转换的无法直接替换 )\n\n[comment]: \u003c\u003e (wxl-ui\\lib\\mixins\\locale.js)\n\n[comment]: \u003c\u003e (/wxl-ui/lib/utils/date-util.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/locale/index.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/transitions/collapse-transition.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/clickoutside.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/popup/index.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/popup/popup-manager.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/vue-popper.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/util.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/locale/format.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/mixins/migrating.js)\n\n[comment]: \u003c\u003e (./node_modules/wxl-ui/lib/utils/vdom.js)\n\n关于打包后 npm 包目录与打包不一致问题，可通过以下三步进行解决：\\\n这里我设置的 npm 包名为 `wxl-ui`\\\n1. 更改 webpack 别名映射目录\n```\nexports.alias = {\n  main: path.resolve(__dirname, '../src'),\n  packages: path.resolve(__dirname, '../packages'),\n  examples: path.resolve(__dirname, '../examples'),\n  'element-ui': path.resolve(__dirname, '../'),\n  'mti-ui': path.resolve(__dirname, '../')\n};\n```\n2. 更改打包引入路径为含有包名称的路径\n```\nObject.keys(Components).forEach(function(key) {\n  externals[`element-ui/packages/${key}`] = `wxl-ui/lib/${key}`;\n});\n\nexternals['element-ui/src/locale'] = 'wxl-ui/lib/locale';\nutilsList.forEach(function(file) {\n  file = path.basename(file, '.js');\n  externals[`element-ui/src/utils/${file}`] = `wxl-ui/lib/utils/${file}`;\n});\nmixinsList.forEach(function(file) {\n  file = path.basename(file, '.js');\n  externals[`element-ui/src/mixins/${file}`] = `wxl-ui/lib/mixins/${file}`;\n});\ntransitionList.forEach(function(file) {\n  file = path.basename(file, '.js');\n  externals[`element-ui/src/transitions/${file}`] = `wxl-ui/lib/transitions/${file}`;\n});\n```\n3. 将根目录 src 下的以下文件中 require 路径中的`element-ui` 目录 更改成与你的npm包名一致的目录\n\n```\nsrc/locale/format.js\nsrc/locale/index.js\nsrc/mixins/locale.js\nsrc/mixins/migrating.js\nsrc/transitions/collapse-transition.js\nsrc/utils/popup/index.js\nsrc/utils/popup/popup-manager.js\nsrc/utils/clickoutside.js\nsrc/utils/date-util.js\nsrc/utils/util.js\nsrc/utils/vdom.js\nsrc/utils/vue-popper.js\n```\n\n4. 如果不进行第三步的话则每次都需要更改打包后的文件,将打包好的lib下的以下文件中 require 路径中的`element-ui` 目录 更改成与你的npm包名一致的目录\n\n```\nlib/mixins/locale.js\nlib/utils/date-util.js\nlib/locale/index.js\nlib/transitions/collapse-transition.js\nlib/utils/clickoutside.js\nlib/utils/popup/index.js\nlib/utils/popup/popup-manager.js\nlib/utils/vue-popper.js\nlib/utils/util.js\nlib/locale/format.js\nlib/mixins/migrating.js\nlib/utils/vdom.js\n```\n\n打包好文件后，按照上面目录将文件复制到 npm 发布文件夹下即可\n\n## 部署文档\n使用 `yarn deploy:build` 命令进行编译文档\n`\"deploy:build\": \"npm run build:file \u0026\u0026 cross-env NODE_ENV=production webpack --config build/webpack.demo.js \u0026\u0026 echo element.eleme.io\u003e\u003eexamples/element-ui/CNAME\"`\n编译成功后可以部署在 Nginx 服务器上进行访问，生成的文档涉及到一些网络资源可以下载到本地进行部署 https://blog.csdn.net/txyzqc/article/details/109700596\n- `npm run build:file` 该指令主要用来自动化生成一些文件,详情见上面说明\n- `cross-env NODE_ENV=production webpack --config build/webpack.demo.js` 标准的webpack配置文件。这个其实是文档构建的webpack配置\n- `echo element.eleme.io\u003e\u003eexamples/element-ui/CNAME` ？不明白想做什么？输出目录是examples/element-ui\n\n16.13.0 (Currently using 64-bit executable)\n14.17.6\nhttps://github.com/coreybutler/nvm-windows/releases/\nGit-2.34.1-64-bit\nhttps://git-scm.com/download/win\n## 其他\n- Element UI是面向开发人员、设计人员和产品经理的基于Vue 2.0的组件库。\\\n- 需要node.js4+，因为使用yarn锁定以来版本，所以这里官方推荐使用yarn进行包管理，而不是npm\n- 出于兼容性和文件大小的考虑，我们的巴别塔配置只导入了preset-2015，所以不推荐使用ES2015中的Array.Prototype.find和Object.Assign这样的接口。\\\n- http://localhost:8085\n- Element-Plus：[https://github.com/element-plus/element-plus](https://github.com/element-plus/element-plus)\n- vue-element-admin：[https://github.com/PanJiaChen/vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwxlvip%2Felementdec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwxlvip%2Felementdec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwxlvip%2Felementdec/lists"}