前端代码审查(Code Review)---具体实践规范会持续更新(新增Vite基础组件全局注册方式)

这篇具有很好参考价值的文章主要介绍了前端代码审查(Code Review)---具体实践规范会持续更新(新增Vite基础组件全局注册方式)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前端代码审查(Code Review)

针对目录结构、SCSS规范、JS规范、Vue规范

可参照官方给出的风格指南(Code Review)

具体实践规范

1、POST/PUT/DELETE 请求按钮需要添加 loading 状态,防止重复提交。

建议使用 Element UI 提供的button 组件的loading属性,或者自己封装一个 loading 状态的按钮组件。

<el-button type="primary" :loading="loading" @click="handleSubmit"> 提交 </el-button>

2、模板上超过两个的判断条件,写成方法或者computed

<!--bad-->
<template>
  <t-table v-if="satus==1&&orderStatus==2&&isShowTable"/>
</template>
<!--good-->
<template>
  <t-table v-if="isChangeAvailiable"/>
</template>
<script>
 computed: {
    isChangeAvailiable() {
      return (
        this.satus==1&&this.orderStatus==2&&this.isShowTable
      );
    },
  },
</script>

3、可选链访问数组/对象元素

//bad
cosnt obj = {}
cosnt b = obj.a && obj.a.b
console.log(b)	// undefined
//good
cosnt obj = {}
cosnt b = obj?.a?.b
console.log(b)	// undefined

4、定时器及时清理

mounted () {
  this.timer = setInterval(() => {
    ...
  }, 1000)
}
destroyed () {
  if (this.timer) {
    clearInterval(this.timer)
  }
}

5、window/body上的监听事件–需要解绑

mounted() {
  window.addEventListener('resize', this.fun)
}
beforeDestroy () {
  window.removeEventListener('resize', this.fun);
}

6、async await 结合使用(调用接口)

export default {
  created() {
    this.getOrderNo()
  },
  methods:{
    async getOrderNo() {
      const res = await this.$api.getOrderNo()
      if(res.success){
        // 成功处理
        }
    }
  }
}

7、使用try…catch…时–错误代码需要提示

try {
  // 成功处理
} catch (error) {
  // 处理异常的代码
  this.$message.error(error.message)
}

8、函数有很多参数,需要封装成一个对象

// bad--->这个方式参数就必须按顺序传递
const getUserInfo =(name,age,sex,mobile,hobby)=> {
  // 函数逻辑
}
// good
const getUserInfo =(userInfo)=> {
  // 函数逻辑
  const {name,age,sex,mobile,hobby} = userInfo
}

9、简化switch case判断

// bad
const counter =(state=0,action)=>{
  switch (action.type) {
    case 'ADD':
      return state + 1
    case 'MINUS':
      return state - 1
    default:
      return state
  }
}
// good
const counter =(state=0,action)=>{
  const step={
    'ADD':1,
    'MINUS':-1
  }
  return state + (step[action.type] ?? 0)
}

10、判断条件过多需要提取出来

// bad
const checkGameStatus =()=>{
  if(status===0||(satuas===1&&isEnd===1)||(isEnd===2)){
    // 调用
  }
}
// good
const isGaneOver =()=>{
  return (status===0||(satuas===1&&isEnd===1)||(isEnd===2))
}
const checkGameStatus =()=>{
  if(isGameOver()){
    // 调用
  }
}

11、if 判断嵌套—>错误前置

// bad
const publishPost =(post)=>{
  if(isLoggenIn){
    if(post){
      if(isPostValid()){
        doPublishPost(post)
      }else{
        throw new Error('文章不合法')
      }
    }else{
      throw new Error('文章不能为空')
    }
  }else{
    throw new Error('用户未登录')
  }
}
// good
const publishPost =(post)=>{
  if(!isLoggenIn){
    throw new Error('用户未登录')
  }
  if(!post){
    throw new Error('文章不能为空')
  }
  if(!isPostValid()){
    throw new Error('文章不合法')
  }
  doPublishPost(post)
}

// bad
const createElement =(item)=>{
  if(item.type==='ball'){
    cosnt div = document.createElement('div')
    div.className = 'ball'
    div.style.backgroundColor = item.color
    return div
  }else if(item.type==='block'){
    const div = document.createElement('div')
    div.className = 'block'
    div.style.backgroundColor = item.color
    return div
  }else if(item.type==='square'){
    const div = document.createElement('div')
    div.className = 'square'
    div.style.backgroundColor = item.color
    return div
  }else{
    throw new Error('未知元素类型')
  }
}

// good
cosnt createElement =(item)=>{
  const validTypes = ['ball', 'block', 'image']
  if(!validTypes.includes(item.type)){
    throw new Error('未知元素类型')
  }
  cosnt div = document.createElement('div')
  div.className = item.type
  div.style.backgroundColor = item.color
  return div
}
// bad
let commodity = {
  phone: '手机',
  computer: '电脑',
  television: '电视',
  gameBoy: '游戏机',
}
 
function price(name) {
  if (name === commodity.phone) {
    console.log(1999)
  } else if (name === commodity.computer) {
    console.log(9999)
  } else if (name === commodity.television) {
    console.log(2999)
  } else if (name === commodity.gameBoy) {
    console.log(3999)
  }
}
price('手机') // 1999
// good
const commodity = new Map([
  ['phone', 1999],
  ['computer', 9999],
  ['television', 2999],
  ['gameBoy', 3999],
])
 
const price = (name) => {
  return commodity.get(name)
}
price('phone') // 1999

12、判断非空(使用空值合并操作符——??)

// bad
if(value !==null && value !==undefined && value !==''){
 ....
}

// good
if((value??'') !==''){
 ...
}

补充常规的—>目录结构规范:

项目根目录下创建 src 目录,src 目录下创建 api 目录、assets 目录、components 目录、directive 目录、router 目录、store 目录、utils 目录、views 目录。

一、api 目录存放所有页面API。

建议将每个页面的API封装成一个单独的js文件,文件名与页面名称相同(防止增删查改接口命名重复),并且都放在api下的modules目录下。

import request from '@/utils/request'
export function afterSaleApplyRefund(data) {
  return request({
    url: `/web/refundApplyOrder/applyRefund`,
    method: 'put',
    data
  })
}
export function getStoreList(params) {
  return request({
    url: `/webWaterStore/getMarkStoreTree`,
    method: 'get',
    params
  })
}
....

建议API目录下新建index.js文件,用于统一导出所有API,在main.js引入并将api挂载到vue的原型上Vue.prototype.$api = api;在页面直接使用this.$api.xxx调用接口。

WebPack自动加载配置API(使用require.context)
// 自动加载api
const commonApiObj = {}
const finalObj = {}
const modulesApi = require.context('./modules', true, /\.js$/)
modulesApi.keys().forEach(key => {
  const newKey = key.replace(/(\.\/|\.js)/g, '')
  commonApiObj[newKey] = require(`./modules/${newKey}`)
})
Object.values(commonApiObj).map(x => Object.assign(finalObj, x))
// console.log('所有业务接口--', finalObj)
export default {
  ...finalObj
}
Vite自动加载配置API(使用import.meta.globEager)

(注册全局api方法 )instance.config.globalProperties.$api = api;

// 自动导入modules
const files: any = import.meta.globEager("./modules/*.ts");
let modules: any = {};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Object.entries(files).forEach(([k, v]) => {
  Object.assign(modules, v);
});
export default {
  ...modules
};
// useApi
import { ComponentInternalInstance, getCurrentInstance } from "vue";
export default function useApi() {
  const { appContext } = getCurrentInstance() as ComponentInternalInstance;
  const proxy = appContext.config.globalProperties;
  return {
    proxy
  };
}

//页面使用
<script setup lang="ts">
import useApi from "@/hooks/useApi";
const { proxy } = useApi();
const getData = async () => {
  const res = await proxy.$api.xxx(接口名);
  if (res.success) {
   ...
  }
}
</script>

二、assets 目录存放静态资源,如图片、字体、公共scss等。

三、components 目录存放公共组件(store也可以如下方式自动导入)。

建议将公共组件拆分为基础组件(baseComponents)和业务组件(pageComponents),基础组件存放一些通用的组件,如按钮、输入框、表格等,业务组件存放与具体业务相关的组件,如用户管理组件、权限管理组件等。

基础组件命名方式大驼峰,如:TTable;业务组件命名方式是小驼峰,如:importExcel。

组件文件夹下必须包含index.vue文件,index.vue文件中必须包含组件的name属性,name属性值必须与组件文件夹名一致。

基础组件复用性高,通常情况都是全局注册

components 基础组件全局注册---->Webpack方式
import Vue from 'vue'
// 全局自动注册baseComponents下的基础组件
const requireComponent = require.context('./baseComponents', true, /\.vue$/)
// 找到组件文件夹下以.vue命名的文件,如果文件名为index,那么取组件中的name作为注册的组件名
requireComponent.keys().forEach(filePath => {
  const componentConfig = requireComponent(filePath)
  const fileName = validateFileName(filePath)
  const componentName = fileName.toLowerCase() === 'index'
    ? capitalizeFirstLetter(componentConfig.default.name)
    : fileName
  Vue.component(componentName, componentConfig.default || componentConfig)
})
//首字母大写
function capitalizeFirstLetter (str) {
  return str && str.charAt(0).toUpperCase() + str.slice(1)
}
// 对符合'xx/xx.vue'组件格式的组件取组件名
function validateFileName (str) {
  return /^\S+\.vue$/.test(str) &&
    str.replace(/^\S+\/(\w+)\.vue$/, (rs, $1) => capitalizeFirstLetter($1))
}
全局注册main.js
import '@/components/index.js' // 全局基础组件注入
页面组件使用
<template>
  <div>
    <t-table></t-table>
  </div>
</template>
components 基础组件全局注册—Vite方式
1、在每个基础组件文件夹下引入index.ts(我的命名是:install.ts),代码如下

vue前端代码评审,vue专栏,Vue3专栏,代码复审,code review,代码审查,代码规范,Vue,前端,meta.globEager

import { App } from 'vue'
import Component from './index.vue'
export default {
  install(app: App) {
    app.component('TTable', Component)
  }
}
2、在baseComponents文件夹下引入index.ts(我的命名是:install.ts),代码如下

vue前端代码评审,vue专栏,Vue3专栏,代码复审,code review,代码审查,代码规范,Vue,前端,meta.globEager

/*  统一注册 baseComponents 目录下的全部组件 */
import { App } from 'vue'

export default {
  install: (app: App) => {
    // 引入所有组件下的安装模块
    const modules:any = import.meta.globEager('./**/install.ts')

    for (const path in modules) {
      app.use(modules[path].default)
    }
  }
}
3、全局注册main.ts,代码如下
import baseComponentsInstall from '@/components/baseComponents/install'
const instance = createApp(App)
instance.use(baseComponentsInstall)

四、utils 目录存放公共方法,如全局loading,axios封装,正则校验等。

axios封装(request.js)
import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'

export default function (config) {
    // 创建axios实例
    const service = axios.create({
        // baseURL: process.env.VUE_APP_BASE_API,
        baseURL: process.env.VUE_APP_BASE_API ,
        // 超时 b
        timeout: 50000
    })
    // request拦截器
    service.interceptors.request.use(
        config => {
            getToken() && (config.headers['Authorization'] = getToken())
            localStorage.getItem('store_id') && (config.headers['Store-Id'] = localStorage.getItem('store_id'))
            config.headers['Content-Type'] = config.headers['Content-Type'] || 'application/json'
            // 8080
            if (config.type == 'file') {
                config.headers['content-type'] = 'application/multipart/form-data'
            } else if (config.type == 'form') {
                config.headers['Content-type'] = 'application/x-www-form-urlencoded'
            }
            if (config.method.toLowerCase() === 'get') {
                config.data = true
            }
            return config
        },
        error => {
            console.log(error)
            Promise.reject(error)
        }
    )
    // 响应拦截器
    service.interceptors.response.use(res => {
        const code = res.data.code
        if (code === 401) {
            MessageBox.confirm(
                '登录状态已过期,您可以继续留在该页面,或者重新登录',
                '系统提示', {
                confirmButtonText: '重新登录',
                cancelButtonText: '取消',
                type: 'warning'
            }
            ).then(() => {
                store.dispatch('FedLogOut').then(() => {
                    if (!window.__POWERED_BY_QIANKUN__) {
                        // 为了重新实例化vue-router对象 避免bug
                        location.reload()
                    } else {
                        window.location.href = '/'
                    }
                })
            })
        } else if (code !== 200) {
            Notification.error({
                title: res.data.msg
            })
            return Promise.reject('error')
        } else {
            return res.data
        }
    },
        error => {
            console.log('err' + error)
            Message({
                message: error.message,
                type: 'error',
                duration: 5 * 1000
            })
            return Promise.reject(error)
        }
    )
    return service(config)
}

相关文章

基于ElementUi再次封装基础组件文档


基于ant-design-vue再次封装基础组件文档


vue3+ts基于Element-plus再次封装基础组件文档文章来源地址https://www.toymoban.com/news/detail-853892.html

到了这里,关于前端代码审查(Code Review)---具体实践规范会持续更新(新增Vite基础组件全局注册方式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【前端代码规范】

    3.2.47 5.0.4 4.3.9 8.43.0 全部采用小写形式方式,以划线分割 例如:my_project_name 参照项目命名规则; 全部采用小写形式方式,以划线分割 有复数结构时,要采用复数命名法。 例:images、 参照项目命名规则:全部采用小写形式方式,以划线分割 例:chat_model.js【chat.vue】 见名识意

    2024年02月10日
    浏览(38)
  • 前端开发代码规范工具

    规范化是前端工程化的一个重要部分。现在,有许多工具能够辅助我们实行代码的规范化,比如你一定知道的 ESLint 和 Prettier。 今天,来聊聊这些工具的工作原理和基本使用,了解它们是如何发挥作用的,以及如何更好地利用这些工具去规范项目的代码。 本文主要聊聊这些工

    2024年02月04日
    浏览(43)
  • Vue实战【Vue开发中的的前端代码风格规范】

    大家好,上一期的导航守卫篇不知大家在私底下是否进行了尝试?之前收到好多小伙伴的私信说什么时候能给大家出一期前段代码风格规范呀,有的同学觉得自己的代码编写的不是很漂亮,虽然自己知道是干啥,但是可读性一点也不高;今天博主也是根据自己多年的开发经验

    2023年04月09日
    浏览(42)
  • 使用VS Code运行前端代码

    提示:这里可以添加本文要记录的大概内容: 但是我在使用VS Code和Hbuilder的不同是: Hbuilder我记得是可以在菜单栏的“文件”→“新建”→“HTML5+项目”,填写项目名称、路径等信息后点击“完成”即可创建一个新项目 如何使用VS Code安装插件及VS Code上的常用插件点我查看

    2024年01月16日
    浏览(44)
  • 如何规范团队代码,小程序ESLint+Prettier+lint-staged+commit+changelog+standard-version自动规范实践

    }, globals: { // 小程序的全局变量 DEV : true, WECHAT : true, ALIPAY : true, __wxConfig: true, App: true, Page: true, Component: true, Behavior: true, wx: true, getApp: true, getCurrentPages: true, }, rules: { // 这是我的配置,大家可以参考官方团队的配置 ‘linebreak-style’: [‘error’, ‘unix’], //换行样式 quotes: [‘er

    2024年04月11日
    浏览(51)
  • Code Review、InLineChat、RAG能力全部独家提供,这波上新CodeGeeX平替Github Copilot稳了!

    智谱 AI 2024年度的技术开放日上,CodeGeeX重磅发布第三代模型。针对CodeGeeX插件产品的系列新功能,也同时上线发布,提供给用户免费使用。 一、第三代模型性能全面提升 CodeGeeX第三代模型正式发布,基础能力全面提升。 针对Python、Java、JavaScript、C++、Golang五种主流编程语言,

    2024年01月18日
    浏览(41)
  • iOS设计规范是什么?都有哪些具体规范

    iOS设计规范是苹果为移动设备操作系统iOS制定的设计指南。iOS设计规范的制定保证了苹果应用在外观和操作上的一致性和可用性,从而提高了苹果界面设计的用户体验和应用程序的成功性。本文将从七个方面全面分析iOS设计规范。 由「即时设计」团队整理的 Apple 官方 iOS 15

    2024年02月12日
    浏览(60)
  • 安卓手机,平板运行 vs code ,写前端代码

    介绍本文的重点 code Fa,大佬的文章如下 把 VS Code 带到安卓 - Code FA - 掘金 安装好了之后, 1.打开科技(不知道啥事科技的可以尝试直接下载,下载的比较慢) 2.安装中文等插件(不开科技下载不了)     安装后 根据介绍安装中文语言包, 并打以下代码     Configure Display Language     或

    2024年02月20日
    浏览(46)
  • 前端项目规范化:手把手教你使用prettier和pre-commit(git hook或者husky)优化规范项目代码

    最简单的两种方式: 使用 prettier + git pre-commit 使用 prettier + husky(原理和第一种一模一样哦) git hooks 下图为git hooks的官方示例,以.sample结尾。注意这些以.sample结尾的示例脚本是不会执行的,重命名后会生效 是一些自定义的脚本,用于控制git工作的流程,分为客户端钩子和服务

    2024年02月04日
    浏览(73)
  • 如何进行高效的代码审查

    代码审查是软件开发过程中至关重要的一环。它是指由开发团队中的其他成员对代码进行检查,以确保代码的质量和一致性。它可以帮助发现潜在的问题,例如内存泄漏、安全漏洞或性能问题。通过及早发现这些问题,可以避免它们在后期的软件开发过程中变得更加复杂和昂

    2024年02月15日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包