Skip to content

KenNaNa/elementui-code-learn

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

244 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

电商项目的总结

前端职业生涯规划

可视化低代码平台

给你七年时间,你会干什么?我想不出我会干什么耶,我只有确定的一件事情就是我会全国各地跑一遍

装饰器教程

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电商平台!

ionic-5 vue3 starter with pwa and tailwind setup

响应式编程入门指南 - 通俗易懂 RxJS

RxJS系列教程(四) Observable

Angular7入门辅助教程(五)——Observable(可观察对象)

RXJS教程

RxJS——给你如丝一般顺滑的编程体验(篇幅较长,建议收藏)

动画学习 rxjs

有人开源躺平

开源躺平

Angular 笔记

Angular In Depth

Echarts_learning_tutorials

  1. 登录跳转问题,不需要 vuex 存储状态了,因为刷新 vuex 数据丧失了,需要使用缓存机制
  2. tabbar 页面与非tabbar页跳转互动问题
  3. 订单页面,需要提示用户去登录的,
  4. 商品列表,单个列表项的删除功能,添加,减少,清空操作,用户操作,用户体验
  5. 商品规格不应该弄一个管理,而是应该让用户在添加商品的过程自己去添加
  6. 多测试

三种价格设置

<template>
  <div class="test">
    <a-radio-group name="radioGroup" :default-value="1" v-model="selected">
      <a-radio :value="1"> 零售价 </a-radio>
      <a-radio :value="2"> 批发价 </a-radio>
      <a-radio :value="3"> 团购价 </a-radio>
    </a-radio-group>
    <a-form-model ref="ruleForm" :model="ruleForm" layout="inline">
      <div v-show="selected === 1">
        <a-form-model-item label="销售价" prop="price">
          <a-input placeholder="请输入销售价" />
        </a-form-model-item>
        <a-form-model-item label="吊牌价" prop="priceTag">
          <a-input placeholder="请输入吊牌价" />
        </a-form-model-item>
        <a-form-model-item label="是否设置为默认价格">
          <input type="radio" name="radio" :value="value" />
        </a-form-model-item>
      </div>
      <div v-show="selected === 2">
        <a-form-model-item label="销售价" prop="price">
          <a-input placeholder="请输入销售价" />
        </a-form-model-item>
        <a-form-model-item label="吊牌价" prop="priceTag">
          <a-input placeholder="请输入吊牌价" />
        </a-form-model-item>
        <a-form-model-item label="是否设置为默认价格">
          <input type="radio" name="radio" :value="value" />
        </a-form-model-item>
      </div>
      <div v-show="selected === 3">
        <a-form-model-item label="销售价" prop="price">
          <a-input placeholder="请输入销售价" />
        </a-form-model-item>
        <a-form-model-item label="吊牌价" prop="priceTag">
          <a-input placeholder="请输入吊牌价" />
        </a-form-model-item>
        <a-form-model-item label="是否设置为默认价格">
          <input type="radio" name="radio" :value="value" />
        </a-form-model-item>
      </div>
    </a-form-model>
  </div>
</template>

<script>
export default {
  name: "test",
  data() {
    return {
      ruleForm: {},
      selected: 1,
      labelCol: { span: 4 },
      wrapperCol: { span: 14 },
      value: true,
    };
  },
};
</script>
function cartesianProductOf(...args) {
  return args.reduce(
    (total, current) => {
      let ret = [];
      total.forEach(a => {
        current.forEach(b => {
          ret.push(a.concat([b]));
        });
      });
      return ret;
    },
    [
      []
    ]
  );
}
// main.js
const components = require('./components/index')
for (let componentName in components) {
  Vue.component(componentName, components[componentName])
}
// vue.config.js
const path = require("path");

function resolve(dir) {
  return path.join(__dirname, dir);
}

module.exports = {
  chainWebpack: config => {
    config.resolve.alias
      .set('components', resolve('src/components/index.js'))
  },
}
// index.js
const componentFiles = require.context('./', true, /index.js$/)
const components = componentFiles.keys().reduce((files, filePath) => {
  const fileName = filePath.replace(/^\.\/(.*)\/index\.\w+$/, '$1')
  const value = componentFiles(filePath)
  if (value.default) {
    const componentName = fileName.split('/')[0]
    files[componentName] = value.default
  } else {
    for (let key in value) {
      console.log("key===>", key, value[key])
      files[key] = value[key]
    }
  }
  return files
}, {})
module.exports = components
// entryTemplate.js
module.exports = {
  entryTemplate: (compoenntName) => {
    return `
      import ${compoenntName} from './src'
      export default ${compoenntName}
    `
  }
}
// genVueTpl.js
// index.js
const chalk = require('chalk')
const path = require('path')
const fs = require('fs')
const resolve = (...file) => path.resolve(__dirname, ...file)
const log = message => console.log(chalk.green(`${message}`))
const successLog = message => console.log(chalk.blue(`${message}`))
const errorLog = error => console.log(chalk.red(`${error}`))
// 导入模板
const {
  vueTemplate
  // entryTemplate
} = require('./template')
// 导入入口
const {
  entryTemplate
} = require('./entryTemplate')
// 生成文件
const generateFile = (path, data) => {
  if (fs.existsSync(path)) {
    errorLog(`${path}文件已存在`)
    return
  }
  return new Promise((resolve, reject) => {
    fs.writeFile(path, data, 'utf8', err => {
      if (err) {
        errorLog(err.message)
        reject(err)
      } else {
        resolve(true)
      }
    })
  })
}
log('请输入要生成的vue文件夹名称 views: xxx、comp: xxx、pageComp: xxx、 它们会生成在对应的文件目录下')
let componentName = ''
process.stdin.on('data', async chunk => {
  // 组件名称
  const inputName = String(chunk).trim().toString().split(':')[1]
  // 判断放在那个文件夹里面
  let pathName = String(chunk).trim().toString().split(':')[0]

  let componentPath = null
  let entryFile = null
  switch (pathName) {
    case 'views':
      pathName = 'views'
      componentPath = resolve(`../src/${pathName}`, inputName)
      break
    case 'comp':
      pathName = 'components'
      componentPath = resolve(`../src/${pathName}`, inputName, 'src')
      entryFile = resolve(`../src/${pathName}`, inputName, 'index.js')
      break
    case 'pageComp':
      pathName = 'pageComponents'
      componentPath = resolve(`../src/${pathName}`, inputName, 'src')
      entryFile = resolve(`../src/${pathName}`, inputName, 'index.js')
      break
  }
  // Vue页面组件路径

  // vue文件
  const vueFile = resolve(componentPath, 'index.vue')

  // 入口文件

  // 判断组件文件夹是否存在
  const hasComponentExists = fs.existsSync(componentPath)
  if (hasComponentExists) {
    errorLog(`${inputName}页面组件已存在,请重新输入`)
    return
  } else {
    log(`正在生成 ${inputName} 的目录 ${componentPath}`)
    await dotExistDirectoryCreate(componentPath)
    if (pathName === 'views') {
      log(`正在生成页面子组件 components 的目录 ${componentPath}\\components`)
      await fs.mkdir(`${componentPath}\\components`, err => {
        log(err)
      })
    }
  }
  try {
    // 获取组件名
    if (inputName.includes('/')) {
      const inputArr = inputName.split('/')
      componentName = inputArr[inputArr.length - 1]
    } else {
      componentName = inputName
    }
    log(`正在生成 vue 文件 ${vueFile}`)
    await generateFile(vueFile, vueTemplate(componentName))
    log(`正在生成 entry 文件 ${entryFile}`)
    if (entryFile) {
      await generateFile(entryFile, entryTemplate(componentName))
    }
    successLog('生成成功')
  } catch (e) {
    errorLog(e.message)
  }

  process.stdin.emit('end')
})
process.stdin.on('end', () => {
  log('exit')
  process.exit()
})

function dotExistDirectoryCreate(directory) {
  return new Promise((resolve) => {
    mkdirs(directory, function () {
      resolve(true)
    })
  })
}
// 递归创建目录
function mkdirs(directory, callback) {
  var exists = fs.existsSync(directory)
  if (exists) {
    callback()
  } else {
    mkdirs(path.dirname(directory), function () {
      fs.mkdirSync(directory)
      callback()
    })
  }
}
// template.js
module.exports = {
  vueTemplate: compoenntName => {
    return `<template>
  <div class="${compoenntName}__wrapper"></div>
</template>

<script>
export default {
  name: '${compoenntName}',

  components: {},

  mixins: [],

  props: {},

  data() {
    return {}
  },

  computed: {},

  watch: {},

  created() {},

  mounted() {},

  destroyed() {},

  methods: {}
}
</script>

<style lang="scss" scoped>
  .${compoenntName}__wrapper {

  }
</style>
`
  }
}
/*第一层if判断生产环境和开发环境*/
if (process.env.NODE_ENV === 'production') {
    /*第二层if,根据.env文件中的VUE_APP_FLAG判断是生产环境还是测试环境*/
    if (process.env.VUE_APP_FLAG === 'pro') {
        //production 生产环境
        axios.defaults.baseURL = 'http://api.xinggeyun.com';//路径

    } else {
        //test 测试环境
        axios.defaults.baseURL = 'http://192.168.0.152:8102';//路径
   }
} else { //dev 开发环境 
   axios.defaults.baseURL = 'http://192.168.0.152:8102';//路径
}
 <a-form-item label='地址' :colon="false">
  <a-cascader
    :allowClear="false"
    v-decorator="['area',{rules: [{ required: true, message: '请选择地址' }]}]"
    :options="areaList"
    placeholder="请选择地址"
    :loadData="loadAreaData"
    @change="onAreaChange"
    :getPopupContainer="(trigger) => {return trigger.parentElement}"
  ></a-cascader>
</a-form-item>
data () {
    return {
      areaList: [], // 地区数据
    }
  },
  async mounted () {
   // 获取省数据
    this.areaList = await this.getAreaList() || []
  },
methods: {
 /**
     * 获取区域
     */
    getAreaList (code) {
      return new Promise((resolve, reject) => {
        getAreaData({
          code: code ? String(code) : ''
        }).then(res => {
          console.log('获取区域------', res)

          if (res.code === '0') {
            let arr = res.data.map(item => {
              return {
                value: item.code + '',
                label: item.name,
                isLeaf: item.level === '3'
              }
            })
            return resolve(arr)
          } else {
            return resolve([])
          }
        }).catch((err) => {
          return reject(err)
        })
      })
    },
// 获取下一级数据
   async loadAreaData (selectedOptions) {
      if (!this.areaList.length) {
        this.areaList = await this.getAreaList() || []
      } else {
        const targetOption = selectedOptions[selectedOptions.length - 1]
        targetOption.loading = true
        let children = await this.getAreaList(targetOption.value) || []
        if (children.length) {
          targetOption.loading = false
          targetOption.children = children
        } else {
          targetOption.loading = false
          targetOption.isLeaf = true
        }
      }
      this.areaList = cloneDeep(this.areaList)
    },
  // 选择区后 
    onAreaChange (val, selectedOptions) {
      this.provinceCode = selectedOptions[0] ? selectedOptions[0].value : ''
      this.province = selectedOptions[0] ? selectedOptions[0].label : ''
      this.cityCode = selectedOptions[1] ? selectedOptions[1].value : ''
      this.city = selectedOptions[1] ? selectedOptions[1].label : ''
      this.regionCode = selectedOptions[2] ? selectedOptions[2].value : ''
      this.region = selectedOptions[2] ? selectedOptions[2].label : ''
    },
}
  • 研究权限问题
mounted () {
  const userAgent = navigator.userAgent
  if (userAgent.indexOf('Edge') > -1) {
    this.$nextTick(() => {
      this.collapsed = !this.collapsed
      setTimeout(() => {
        this.collapsed = !this.collapsed
      }, 16)
    })
  }
  const oMenus = document.querySelector('.ant-menu.ant-menu-inline.ant-menu-root.ant-menu-dark')
  oMenus.addEventListener('click', (e) => {
    const url = e.target.getAttribute('href')
    if (url) {
      this.$router.push({
        path: url + '?t=' + new Date().getTime()
      })
    }
    setTimeout(() => {
      this.$router.push(url)
    }, 16)
    console.log('url====>', url)
  })
  // first update color
  // TIPS: THEME COLOR HANDLER!! PLEASE CHECK THAT!!
  if (process.env.NODE_ENV !== 'production' || process.env.VUE_APP_PREVIEW === 'true') {
    updateTheme(this.settings.primaryColor)
  }
},
  • 在 router-view 加上 key
<router-view :key="getPath"/>
  • 在computed
computed: {
  ...mapState({
    // 动态主路由
    mainMenu: state => state.permission.addRouters
  }),
  getPath () {
    return this.$route.fullPath
  }
},
  // 合并行
  colspanMethod(dataList, key) {
    const obj = {};
    let data = [];
    let temp = [];
    for (let i = 0; i < dataList.length; i++) {
      const item = dataList[i];
      if (!obj[item[key]]) {
        obj[item[key]] = {
          num: 1,
          isFirst: false,
          data: [item],
        };
      } else {
        obj[item[key]].num++;
        obj[item[key]].data.push(item);
      }
    }

    for (let j = 0; j < dataList.length; j++) {
      for (let k in obj) {
        if (k === dataList[j][key]) {
          if (!obj[k].isFirst) {
            dataList[j].rowspan = obj[k].num;
            obj[k].isFirst = true;
          }
          break;
        }
      }
    }

    for (let ke in obj) {
      data = data.concat(obj[ke].data);
    }

    console.log("obbject", data, dataList, obj);
    return data;
  }

16 css 如何解决 flex 布局高度自动撑开

display: flex;
align-items: flex-start;
justify-content: space-between;

About

elementui 源码学习

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages