{"id":28428296,"url":"https://github.com/kennana/elementui-code-learn","last_synced_at":"2026-01-29T22:02:53.745Z","repository":{"id":124821447,"uuid":"362050909","full_name":"KenNaNa/elementui-code-learn","owner":"KenNaNa","description":"elementui 源码学习","archived":false,"fork":false,"pushed_at":"2021-12-03T02:48:23.000Z","size":43251,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-04T15:32:16.995Z","etag":null,"topics":["elementui"],"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/KenNaNa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-04-27T09:13:59.000Z","updated_at":"2022-08-19T17:19:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"2fe1d41d-401b-403e-9dff-5af11c19b800","html_url":"https://github.com/KenNaNa/elementui-code-learn","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/KenNaNa/elementui-code-learn","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenNaNa%2Felementui-code-learn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenNaNa%2Felementui-code-learn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenNaNa%2Felementui-code-learn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenNaNa%2Felementui-code-learn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KenNaNa","download_url":"https://codeload.github.com/KenNaNa/elementui-code-learn/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenNaNa%2Felementui-code-learn/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28886881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-29T21:06:44.224Z","status":"ssl_error","status_checked_at":"2026-01-29T21:06:42.160Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["elementui"],"created_at":"2025-06-05T12:37:59.479Z","updated_at":"2026-01-29T22:02:53.733Z","avatar_url":"https://github.com/KenNaNa.png","language":"Vue","readme":"# 电商项目的总结\n\n[前端职业生涯规划](https://github.com/f2e-journey/f2e-journey/blob/master/career-planning.md)\n\n[可视化低代码平台](https://github.com/zzcandor/lowcode-dashboard)\n\n给你七年时间，你会干什么？我想不出我会干什么耶，我只有确定的一件事情就是我会全国各地跑一遍\n\n[装饰器教程](https://www.cnblogs.com/dashnowords/p/10158537.html)\n\n[ Based on vue3.0.0, vant3.0.0, vue-router v4.0.0-0, vuex^4.0.0-0, vue-cli3, mockjs, imitating Jingdong Taobao, mobile H5 e-commerce platform! 基于vue3.0.0 ,vant3.0.0,vue-router v4.0.0-0, vuex^4.0.0-0,vue-cli3,mockjs,仿京东淘宝的,移动端H5电商平台!](https://github.com/GitHubGanKai/vue3-jd-h5)\n\n[ionic-5 vue3 starter with pwa and tailwind setup](https://github.com/Elvincth/ionic-5-vue-pwa)\n\n[响应式编程入门指南 - 通俗易懂 RxJS](https://hijiangtao.github.io/2020/01/13/RxJS-Introduction-and-Actions/)\n\n[RxJS系列教程(四) Observable](https://www.jianshu.com/p/721ce6870740)\n\n[Angular7入门辅助教程（五）——Observable（可观察对象）](https://blog.csdn.net/qq_34414916/article/details/85194098)\n\n[RXJS教程](https://limeii.github.io/2019/07/rxjs-subject/)\n\n[RxJS——给你如丝一般顺滑的编程体验（篇幅较长，建议收藏）](https://juejin.cn/post/6910943445569765384)\n\n[动画学习 rxjs](https://reactive.how/)\n\n有人开源躺平\n\n[开源躺平](https://github.com/phodal/tangping)\n\n[Angular 笔记](https://github.com/deepthan/blog-angular)\n\n[Angular In Depth](https://github.com/AngularID-CN/AngularID-CN)\n\n[Echarts_learning_tutorials](https://github.com/FelixZFB/Echarts_learning_tutorials)\n\n1. 登录跳转问题，不需要 vuex 存储状态了，因为刷新 vuex 数据丧失了，需要使用缓存机制\n2. tabbar 页面与非tabbar页跳转互动问题\n3. 订单页面，需要提示用户去登录的，\n4. 商品列表，单个列表项的删除功能，添加，减少，清空操作，用户操作，用户体验\n5. 商品规格不应该弄一个管理，而是应该让用户在添加商品的过程自己去添加\n6. 多测试\n\n- 登录或许可以写成一个公用的组件\n\n- 删除一些无用的代码\n\n- 重复点击菜单栏项，需要刷新页面\n- 资源共享的功能\n- 打印机打印的问题\n- 拖拽插件\n- 添加小标签问题\n- 小类，大类一般是怎么添加的\n- 研究三级联动组件\n- 环境配置问题，提取公共的 url\n- 上传组件需要添加loading状态\n- 图片需要懒加载\n- [vue中的图片加载与显示默认图片](https://www.cnblogs.com/xulei1992/p/6558294.html)\n- [vue项目设置img标签的默认图片](https://blog.csdn.net/xjun0812/article/details/104414838)\n- [基于阿里Ant Design of Vue的上传组件二次封装](https://blog.csdn.net/weixin_43056561/article/details/107834801)\n- 301 logout 重定向到登录页面\n- 提取 store 几个组件到一个 home/store 目录，方便管理\n- 402 非法类别\n- 写着，写着麻烦，要停下来想想有没有更好的方式\n- [基于阿里Ant Design of Vue的上传组件二次封装](https://blog.csdn.net/weixin_43056561/article/details/107834801?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_v2~rank_aggregation-1-107834801.pc_agg_rank_aggregation\u0026utm_term=ant+design+vue+%E4%B8%8A%E4%BC%A0%E7%BB%84%E4%BB%B6%E5%B0%81%E8%A3%85\u0026spm=1000.2123.3001.4430)\n- [Cookie、 session、localStorage 和sessionStorage的存储区别](https://blog.csdn.net/V8min/article/details/115794263?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_v2~rank_aggregation-8-115794263.pc_agg_rank_aggregation\u0026utm_term=%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%B3%E9%97%AD%E4%B9%8B%E5%90%8Ecookie%E6%B6%88%E5%A4%B1\u0026spm=1000.2123.3001.4430)\n- 添加店铺描述\n- 为什么要这么抽取，为什么要这么实现\n- 像产品思维那样转变\n- 领导是结果导向的，员工是过程导向的，我们应该像结果导向过渡，那么要怎么做\n- 为什么要抽丝剥茧，做到这一步的理由是什么，为什么要这么做\n- 提取公共的样式\n- 添加按钮组件修改宽高度文图\n- 提取公共的颜色，字体大小变量\n- 提取 js 中的常量，比如数字\n- 直接定义变量直接可以全局使用\n- [在vue中自动生成文件以及自动引入component，router、vuex按模块划分](https://blog.csdn.net/qq_42268364/article/details/106905870?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_v2~rank_aggregation-5-106905870.pc_agg_rank_aggregation\u0026utm_term=vue%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%E6%96%87%E4%BB%B6\u0026spm=1000.2123.3001.4430)\n- [瀑布流组件](https://github.com/AwesomeDevin/vue-waterfall2)\n- 将 StoreModal, StoreCard 抽取到 Store 目录\n- 商品模块使用卡片式模块，方便定位\n- 可增加，删除，编辑的树组件，数据在组件里面处理，只需要将处理之后的数据暴露出来就行了\n- 使用级联的方式去搜索对应的产品 级联的数据应该在里面处理，只需要将处理之后的数据暴露出来就行了\n- 商品列表组件，只需要将处理之后的数据暴露出来就行了\n- 滚动定位，https://www.cnblogs.com/haonanZhang/p/9517636.html\n- [低代码快速搭建完整商品列表页](https://blog.csdn.net/weixin_47095348/article/details/110670641)\n- [que-etc/resize-observer-polyfill](https://github.com/que-etc/resize-observer-polyfill)\n- [前端虚拟列表的实现原理](https://mp.weixin.qq.com/s/IC5yNkaOfvM9M-s3tj-jsg)\n- [ant-design-vue锚点](https://blog.csdn.net/weixin_47711357/article/details/114914953) \n- [多个数组笛卡尔积-js算法](https://blog.csdn.net/suprezheng/article/details/86558050)\n- [js 生成笛卡尔积](https://www.cnblogs.com/majiang/p/5988093.html)\n- [商品规格SKU笛卡尔积计算](https://blog.csdn.net/lihefei_coder/article/details/106668953)\n- [Erupt Framework   🚀   通用后台管理框架](https://github.com/erupts/erupt-web)\n- [国内低代码平台从业者交流](https://github.com/taowen/awesome-lowcode)\n- [低代码平台, 可视化编辑器，单手打代码，解放你的双手](https://github.com/LianjiaTech/hetu)\n- [登录详解(VUE前端) · 低代码开发平台文档 · 看云](https://www.kancloud.cn/frank258jun/sca_manual/2242081)\n- [微前端项目实战](https://github.com/hql7/wl-micro-frontends)\n- [Angular-HMR](https://github.com/GoogleSmileMMa/Angular-HMR)\n\n- 今天的目标是把查询页面搞出来，规格添加页面\n- 今天对接规格创建，添加，修改\n- 今晚把基本商品添加页，图片上传基本信息，搞完\n- 今晚处理，单规格，多规格问题\n- 多规格表格上传，删除处理要回现处理规格，单规格(6-8)\n- 分类也要点击弹框，可以修改添加，编辑\n- 树组件有个隐藏的风险，就是可能误添加上下级关系，给出添加，修改各个提示\n- \n\n\n三种价格设置\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv class=\"test\"\u003e\n    \u003ca-radio-group name=\"radioGroup\" :default-value=\"1\" v-model=\"selected\"\u003e\n      \u003ca-radio :value=\"1\"\u003e 零售价 \u003c/a-radio\u003e\n      \u003ca-radio :value=\"2\"\u003e 批发价 \u003c/a-radio\u003e\n      \u003ca-radio :value=\"3\"\u003e 团购价 \u003c/a-radio\u003e\n    \u003c/a-radio-group\u003e\n    \u003ca-form-model ref=\"ruleForm\" :model=\"ruleForm\" layout=\"inline\"\u003e\n      \u003cdiv v-show=\"selected === 1\"\u003e\n        \u003ca-form-model-item label=\"销售价\" prop=\"price\"\u003e\n          \u003ca-input placeholder=\"请输入销售价\" /\u003e\n        \u003c/a-form-model-item\u003e\n        \u003ca-form-model-item label=\"吊牌价\" prop=\"priceTag\"\u003e\n          \u003ca-input placeholder=\"请输入吊牌价\" /\u003e\n        \u003c/a-form-model-item\u003e\n        \u003ca-form-model-item label=\"是否设置为默认价格\"\u003e\n          \u003cinput type=\"radio\" name=\"radio\" :value=\"value\" /\u003e\n        \u003c/a-form-model-item\u003e\n      \u003c/div\u003e\n      \u003cdiv v-show=\"selected === 2\"\u003e\n        \u003ca-form-model-item label=\"销售价\" prop=\"price\"\u003e\n          \u003ca-input placeholder=\"请输入销售价\" /\u003e\n        \u003c/a-form-model-item\u003e\n        \u003ca-form-model-item label=\"吊牌价\" prop=\"priceTag\"\u003e\n          \u003ca-input placeholder=\"请输入吊牌价\" /\u003e\n        \u003c/a-form-model-item\u003e\n        \u003ca-form-model-item label=\"是否设置为默认价格\"\u003e\n          \u003cinput type=\"radio\" name=\"radio\" :value=\"value\" /\u003e\n        \u003c/a-form-model-item\u003e\n      \u003c/div\u003e\n      \u003cdiv v-show=\"selected === 3\"\u003e\n        \u003ca-form-model-item label=\"销售价\" prop=\"price\"\u003e\n          \u003ca-input placeholder=\"请输入销售价\" /\u003e\n        \u003c/a-form-model-item\u003e\n        \u003ca-form-model-item label=\"吊牌价\" prop=\"priceTag\"\u003e\n          \u003ca-input placeholder=\"请输入吊牌价\" /\u003e\n        \u003c/a-form-model-item\u003e\n        \u003ca-form-model-item label=\"是否设置为默认价格\"\u003e\n          \u003cinput type=\"radio\" name=\"radio\" :value=\"value\" /\u003e\n        \u003c/a-form-model-item\u003e\n      \u003c/div\u003e\n    \u003c/a-form-model\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nexport default {\n  name: \"test\",\n  data() {\n    return {\n      ruleForm: {},\n      selected: 1,\n      labelCol: { span: 4 },\n      wrapperCol: { span: 14 },\n      value: true,\n    };\n  },\n};\n\u003c/script\u003e\n```\n\n\n```js\nfunction cartesianProductOf(...args) {\n  return args.reduce(\n    (total, current) =\u003e {\n      let ret = [];\n      total.forEach(a =\u003e {\n        current.forEach(b =\u003e {\n          ret.push(a.concat([b]));\n        });\n      });\n      return ret;\n    },\n    [\n      []\n    ]\n  );\n}\n```\n\n```js\n// main.js\nconst components = require('./components/index')\nfor (let componentName in components) {\n  Vue.component(componentName, components[componentName])\n}\n```\n\n```js\n// vue.config.js\nconst path = require(\"path\");\n\nfunction resolve(dir) {\n  return path.join(__dirname, dir);\n}\n\nmodule.exports = {\n  chainWebpack: config =\u003e {\n    config.resolve.alias\n      .set('components', resolve('src/components/index.js'))\n  },\n}\n```\n\n```js\n// index.js\nconst componentFiles = require.context('./', true, /index.js$/)\nconst components = componentFiles.keys().reduce((files, filePath) =\u003e {\n  const fileName = filePath.replace(/^\\.\\/(.*)\\/index\\.\\w+$/, '$1')\n  const value = componentFiles(filePath)\n  if (value.default) {\n    const componentName = fileName.split('/')[0]\n    files[componentName] = value.default\n  } else {\n    for (let key in value) {\n      console.log(\"key===\u003e\", key, value[key])\n      files[key] = value[key]\n    }\n  }\n  return files\n}, {})\nmodule.exports = components\n```\n\n\n```js\n// entryTemplate.js\nmodule.exports = {\n  entryTemplate: (compoenntName) =\u003e {\n    return `\n      import ${compoenntName} from './src'\n      export default ${compoenntName}\n    `\n  }\n}\n```\n\n```js\n// genVueTpl.js\n// index.js\nconst chalk = require('chalk')\nconst path = require('path')\nconst fs = require('fs')\nconst resolve = (...file) =\u003e path.resolve(__dirname, ...file)\nconst log = message =\u003e console.log(chalk.green(`${message}`))\nconst successLog = message =\u003e console.log(chalk.blue(`${message}`))\nconst errorLog = error =\u003e console.log(chalk.red(`${error}`))\n// 导入模板\nconst {\n  vueTemplate\n  // entryTemplate\n} = require('./template')\n// 导入入口\nconst {\n  entryTemplate\n} = require('./entryTemplate')\n// 生成文件\nconst generateFile = (path, data) =\u003e {\n  if (fs.existsSync(path)) {\n    errorLog(`${path}文件已存在`)\n    return\n  }\n  return new Promise((resolve, reject) =\u003e {\n    fs.writeFile(path, data, 'utf8', err =\u003e {\n      if (err) {\n        errorLog(err.message)\n        reject(err)\n      } else {\n        resolve(true)\n      }\n    })\n  })\n}\nlog('请输入要生成的vue文件夹名称 views: xxx、comp: xxx、pageComp: xxx、 它们会生成在对应的文件目录下')\nlet componentName = ''\nprocess.stdin.on('data', async chunk =\u003e {\n  // 组件名称\n  const inputName = String(chunk).trim().toString().split(':')[1]\n  // 判断放在那个文件夹里面\n  let pathName = String(chunk).trim().toString().split(':')[0]\n\n  let componentPath = null\n  let entryFile = null\n  switch (pathName) {\n    case 'views':\n      pathName = 'views'\n      componentPath = resolve(`../src/${pathName}`, inputName)\n      break\n    case 'comp':\n      pathName = 'components'\n      componentPath = resolve(`../src/${pathName}`, inputName, 'src')\n      entryFile = resolve(`../src/${pathName}`, inputName, 'index.js')\n      break\n    case 'pageComp':\n      pathName = 'pageComponents'\n      componentPath = resolve(`../src/${pathName}`, inputName, 'src')\n      entryFile = resolve(`../src/${pathName}`, inputName, 'index.js')\n      break\n  }\n  // Vue页面组件路径\n\n  // vue文件\n  const vueFile = resolve(componentPath, 'index.vue')\n\n  // 入口文件\n\n  // 判断组件文件夹是否存在\n  const hasComponentExists = fs.existsSync(componentPath)\n  if (hasComponentExists) {\n    errorLog(`${inputName}页面组件已存在，请重新输入`)\n    return\n  } else {\n    log(`正在生成 ${inputName} 的目录 ${componentPath}`)\n    await dotExistDirectoryCreate(componentPath)\n    if (pathName === 'views') {\n      log(`正在生成页面子组件 components 的目录 ${componentPath}\\\\components`)\n      await fs.mkdir(`${componentPath}\\\\components`, err =\u003e {\n        log(err)\n      })\n    }\n  }\n  try {\n    // 获取组件名\n    if (inputName.includes('/')) {\n      const inputArr = inputName.split('/')\n      componentName = inputArr[inputArr.length - 1]\n    } else {\n      componentName = inputName\n    }\n    log(`正在生成 vue 文件 ${vueFile}`)\n    await generateFile(vueFile, vueTemplate(componentName))\n    log(`正在生成 entry 文件 ${entryFile}`)\n    if (entryFile) {\n      await generateFile(entryFile, entryTemplate(componentName))\n    }\n    successLog('生成成功')\n  } catch (e) {\n    errorLog(e.message)\n  }\n\n  process.stdin.emit('end')\n})\nprocess.stdin.on('end', () =\u003e {\n  log('exit')\n  process.exit()\n})\n\nfunction dotExistDirectoryCreate(directory) {\n  return new Promise((resolve) =\u003e {\n    mkdirs(directory, function () {\n      resolve(true)\n    })\n  })\n}\n// 递归创建目录\nfunction mkdirs(directory, callback) {\n  var exists = fs.existsSync(directory)\n  if (exists) {\n    callback()\n  } else {\n    mkdirs(path.dirname(directory), function () {\n      fs.mkdirSync(directory)\n      callback()\n    })\n  }\n}\n```\n\n```js\n// template.js\nmodule.exports = {\n  vueTemplate: compoenntName =\u003e {\n    return `\u003ctemplate\u003e\n  \u003cdiv class=\"${compoenntName}__wrapper\"\u003e\u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nexport default {\n  name: '${compoenntName}',\n\n  components: {},\n\n  mixins: [],\n\n  props: {},\n\n  data() {\n    return {}\n  },\n\n  computed: {},\n\n  watch: {},\n\n  created() {},\n\n  mounted() {},\n\n  destroyed() {},\n\n  methods: {}\n}\n\u003c/script\u003e\n\n\u003cstyle lang=\"scss\" scoped\u003e\n  .${compoenntName}__wrapper {\n\n  }\n\u003c/style\u003e\n`\n  }\n}\n```\n\n```js\n/*第一层if判断生产环境和开发环境*/\nif (process.env.NODE_ENV === 'production') {\n    /*第二层if，根据.env文件中的VUE_APP_FLAG判断是生产环境还是测试环境*/\n    if (process.env.VUE_APP_FLAG === 'pro') {\n        //production 生产环境\n        axios.defaults.baseURL = 'http://api.xinggeyun.com';//路径\n\n    } else {\n        //test 测试环境\n        axios.defaults.baseURL = 'http://192.168.0.152:8102';//路径\n   }\n} else { //dev 开发环境 \n   axios.defaults.baseURL = 'http://192.168.0.152:8102';//路径\n}\n```\n\n```html\n \u003ca-form-item label='地址' :colon=\"false\"\u003e\n  \u003ca-cascader\n    :allowClear=\"false\"\n    v-decorator=\"['area',{rules: [{ required: true, message: '请选择地址' }]}]\"\n    :options=\"areaList\"\n    placeholder=\"请选择地址\"\n    :loadData=\"loadAreaData\"\n    @change=\"onAreaChange\"\n    :getPopupContainer=\"(trigger) =\u003e {return trigger.parentElement}\"\n  \u003e\u003c/a-cascader\u003e\n\u003c/a-form-item\u003e\n```\n\n```js\ndata () {\n    return {\n      areaList: [], // 地区数据\n    }\n  },\n  async mounted () {\n   // 获取省数据\n    this.areaList = await this.getAreaList() || []\n  },\nmethods: {\n /**\n     * 获取区域\n     */\n    getAreaList (code) {\n      return new Promise((resolve, reject) =\u003e {\n        getAreaData({\n          code: code ? String(code) : ''\n        }).then(res =\u003e {\n          console.log('获取区域------', res)\n\n          if (res.code === '0') {\n            let arr = res.data.map(item =\u003e {\n              return {\n                value: item.code + '',\n                label: item.name,\n                isLeaf: item.level === '3'\n              }\n            })\n            return resolve(arr)\n          } else {\n            return resolve([])\n          }\n        }).catch((err) =\u003e {\n          return reject(err)\n        })\n      })\n    },\n// 获取下一级数据\n   async loadAreaData (selectedOptions) {\n      if (!this.areaList.length) {\n        this.areaList = await this.getAreaList() || []\n      } else {\n        const targetOption = selectedOptions[selectedOptions.length - 1]\n        targetOption.loading = true\n        let children = await this.getAreaList(targetOption.value) || []\n        if (children.length) {\n          targetOption.loading = false\n          targetOption.children = children\n        } else {\n          targetOption.loading = false\n          targetOption.isLeaf = true\n        }\n      }\n      this.areaList = cloneDeep(this.areaList)\n    },\n  // 选择区后 \n    onAreaChange (val, selectedOptions) {\n      this.provinceCode = selectedOptions[0] ? selectedOptions[0].value : ''\n      this.province = selectedOptions[0] ? selectedOptions[0].label : ''\n      this.cityCode = selectedOptions[1] ? selectedOptions[1].value : ''\n      this.city = selectedOptions[1] ? selectedOptions[1].label : ''\n      this.regionCode = selectedOptions[2] ? selectedOptions[2].value : ''\n      this.region = selectedOptions[2] ? selectedOptions[2].label : ''\n    },\n}\n```\n- 研究权限问题\n\n```js\nmounted () {\n  const userAgent = navigator.userAgent\n  if (userAgent.indexOf('Edge') \u003e -1) {\n    this.$nextTick(() =\u003e {\n      this.collapsed = !this.collapsed\n      setTimeout(() =\u003e {\n        this.collapsed = !this.collapsed\n      }, 16)\n    })\n  }\n  const oMenus = document.querySelector('.ant-menu.ant-menu-inline.ant-menu-root.ant-menu-dark')\n  oMenus.addEventListener('click', (e) =\u003e {\n    const url = e.target.getAttribute('href')\n    if (url) {\n      this.$router.push({\n        path: url + '?t=' + new Date().getTime()\n      })\n    }\n    setTimeout(() =\u003e {\n      this.$router.push(url)\n    }, 16)\n    console.log('url====\u003e', url)\n  })\n  // first update color\n  // TIPS: THEME COLOR HANDLER!! PLEASE CHECK THAT!!\n  if (process.env.NODE_ENV !== 'production' || process.env.VUE_APP_PREVIEW === 'true') {\n    updateTheme(this.settings.primaryColor)\n  }\n},\n```\n\n- 在 router-view 加上 key\n\n```html\n\u003crouter-view :key=\"getPath\"/\u003e\n```\n\n- 在computed\n\n```js\ncomputed: {\n  ...mapState({\n    // 动态主路由\n    mainMenu: state =\u003e state.permission.addRouters\n  }),\n  getPath () {\n    return this.$route.fullPath\n  }\n},\n```\n\n```ts\n  // 合并行\n  colspanMethod(dataList, key) {\n    const obj = {};\n    let data = [];\n    let temp = [];\n    for (let i = 0; i \u003c dataList.length; i++) {\n      const item = dataList[i];\n      if (!obj[item[key]]) {\n        obj[item[key]] = {\n          num: 1,\n          isFirst: false,\n          data: [item],\n        };\n      } else {\n        obj[item[key]].num++;\n        obj[item[key]].data.push(item);\n      }\n    }\n\n    for (let j = 0; j \u003c dataList.length; j++) {\n      for (let k in obj) {\n        if (k === dataList[j][key]) {\n          if (!obj[k].isFirst) {\n            dataList[j].rowspan = obj[k].num;\n            obj[k].isFirst = true;\n          }\n          break;\n        }\n      }\n    }\n\n    for (let ke in obj) {\n      data = data.concat(obj[ke].data);\n    }\n\n    console.log(\"obbject\", data, dataList, obj);\n    return data;\n  }\n```\n\n16 css 如何解决 flex 布局高度自动撑开\n\n```css\ndisplay: flex;\nalign-items: flex-start;\njustify-content: space-between;\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkennana%2Felementui-code-learn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkennana%2Felementui-code-learn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkennana%2Felementui-code-learn/lists"}