前端代码优化

1. 代码格式

代码格式问题完全可以通过自动化工具来解决。标准的 eslint 规则( 如 Airbnb 或公司统一推出的 eslint 规则) + husky( 本地 pre-commit 校验 ) + 远端 CI 流水线 eslint 校验(开启 cache,增量校验)就可以解决。

2. 代码错误

2.1 是否存在会导致内存泄露的代码

对于 SPA 应用,用户无需刷新浏览器,所以要想确保垃圾回收生效,我们需要在组件对应生命周期里做主动销毁。

1)存在不必要的全局变量且未及时解除引用

全局变量,除非你关闭窗口或者刷新页面,才会被释放,如果缓存大量数据,很可能导致内存泄露。比如,我们之前就遇到过把 IM SDK 放在全局 window 上,但在页面卸载时却没有解除引用。

mounted () {
  window.im = TWebLive.createIM({ SDKAppID });
}

解决方案:在页面卸载时解除该全局引用。

destroyed () {
  window.im = null;
}

其实该 im 实例也不需要挂在 window 上,直接绑定在 vue 实例上即可,组件销毁时该实例也会销毁;但没有绑定在 vue 实例上的一定要主动销毁。

2)闭包内部变量未被销毁

来看一个容易忽视的闭包引发内存泄漏的例子。outer 函数内部定义了两个函数: unused 和 foo。虽然 inner 函数中并没有使用 outer 函数中的变量,但是由于 unsed 函数使用了 outer 函数的 bar 变量,bar 也不会被释放,所以 foo 相当于隐式持有了 bar。每次执行 outer,bar 都会指向上一次的 foo;而 foo 也会隐式持有 bar,这样的引用关系导致 bar 和 foo 都无法释放。

let foo = null;

function outer() {
  let bar = foo;

  // 该函数历史原因,调用方被注释掉。并无调用
  function unused () {
    doSomething();
    console.log(`unused ${bar}`)
  }

  // foo赋值
  foo = {
    bigData: new Array(10000),
    inner: function () {
       doSomething();
    }
  }
}

for (let i = 0; i < 1000; i++) {
  outer();
}

解决方案:在 outer 执行完毕时手动释放 bar。这样,隐式持有 bar 的 foo 也没有其他变量引用,也会被回收了。

let foo = null;

function outer() {
  let bar = foo;

  // 该函数历史原因,调用方被注释掉。并无调用
  function unused () {
    doSomething();
    console.log(`unused ${bar}`)
  }

  // foo赋值
  foo = {
    bigData: new Array(10000),
    inner: function () {
       doSomething();
    }
  }

  bar = null; // 手动释放bar
}

for (let i = 0; i < 1000; i++) {
  outer();
}
3)定时器是否及时清理

常见的情况是 mounted 设置了定时任务,但却没有及时清理。

mounted () {
  this.timer = setTimeout(() => {
    doSomething();
  }, 300)
}

参考写法,页面销毁时需清理定时器:

destroyed () {
  if (this.timer) {
    clearTimeout(this.timer)
  }
}
4)监听事件是否有解绑

window/body 等事件需要解绑:

mounted() {
  window.addEventListener(‘resize’, this.func)
}
beforeDestroy () {
  window.removeEventListener('resize', this.func);
}
5)第三方库的销毁函数,在页面卸载时也需要调用,比如 EventBus:
destroyed () {
  this.eventBus.off()
}
6)v-if 指令导致的内存泄露

拿 vue 官网避免内存泄漏 的例子来看下。

v-if 指令只是控制虚拟 DOM 的添加和移除,但是由 Choices.js 添加的 DOM 片段并没有被移除。

<template>
<div id="app">
<button v-if="showChoices" @click="hide">Hide</button>
<button v-if="!showChoices" @click="show">Show</button>
<div v-if="showChoices">
<select id="choices-single-default"></select>
</div>
</div>
</template>

<script>
new Vue({
el: "#app",
data: function () {
return {
showChoices: true
}
},
mounted: function () {
this.initializeChoices()
},
methods: {
initializeChoices: function () {
let list = []
for (let i = 0; i < 1000; i++) {
list.push({
label: "Item " + i,
value: i
})
}
new Choices("#choices-single-default", {
searchEnabled: true,
removeItemButton: true,
choices: list
})
},
show: function () {
this.showChoices = true
this.$nextTick(() => {
this.initializeChoices()
})
},
hide: function () {
this.showChoices = false
}
}
})
</script>

解决办法是在 hide 方法里调用 Choices.js 的 API 来清理 DOM 片段:

hide: function() {
  this.choicesSelect.destroy();
}

以下是优化前、后的 JS Heap 对比图:

2.2 异步操作是否有异常处理

异步操作拿接口请求来说,大家都知道的是,使用 promise 时要有.catch 处理。但使用 async/await 时,有.catch 处理的,也有 try...catch 处理的使用方法。这里推荐使用.catch。原因在于:

  • 可以控制接口请求出错后,是否要阻塞后续业务逻辑执行
  • .catch里的 error 能明确知道是接口请求导致的错误,而不需要再对 error 进行分类判断,是接口 200 返回后的业务逻辑处理报错还是接口报错。
// CASE 1: 接口报错,阻塞业务逻辑执行
async fetchList() {
  const res = await someApi().catch(error => {
  // error处理逻辑
  })
  if (res) {
    doA();
  }
 }

 // CASE 2: 接口报错,不阻塞业务逻辑执行
 async fetchList() {
  const res = await someApi().catch(error => {
  // error处理逻辑
  })
  doA();
 }

 // CASE 3:使用try...catch的情况
 async fetchList() {
  try {
  const res = await someApi()
     doA();
  } catch (error) {
    // 接口请求出错 + 接口响应成功后业务逻辑处理出错都会进入catch block。需要进一步区分错误类型
    if (error.bizcode !== 0 || error.retcode !== 0) {
      reportApiError(error)
    } else {
      reportBusinessError(error)
    }
  }
 }
2.3 取值时是否进行了空判断、调用函数时是否进行了类型判断

拿医典 3 月中下旬的错误日志来说,这类错误在错误日志中占了 1/3。

如果项目里已经全量使用了 Typescript,这类错误应该都可以避免。但如果项目里还存在 js 代码,可以使用lodash.get来做空判断,在调用函数之前要对函数做类型判断。

2.4 存在无意义的 if else 代码块或考虑漏的条件

无意义的 if else 代码块,指的不仅是空的 if else 代码块,还有只写了 console.log 的情况。另外,也存在条件判断过于复杂,else 情况考虑不全,导致逻辑没有正常处理的情况。

//  else 代码块里只写了console.log
if (a) {
} else {
  console.log('something')
}

// 条件判断过于复杂,else情况考虑不全,导致逻辑不能正常处理
if ((a && (b || c)) || d || (e && (f || g))) {
} else {
  doSomething()
}

解决办法:开启 eslint no-empty 规则,不允许有空的 block。但这个插件的问题在于,如果是无效的代码块,比如在 else 代码块只做了 console.log 操作,并不会检测出来。另外,较为复杂的条件判断尽量拆成单独的变量,并分别配上注释说明,这样可以防止逻辑处理漏。

2.5 存在无意义的 catch 代码块

和无意义的 else 代码块一样,也存在空 catch 代码块、只有 console.log 的 catch 代码块的情况。

// bad case
try {
  doSomething();
} catch (e) {
}

// bad case
try {
  doSomething();
} catch (e) {
  console.log(e);
}

// bad case
somePromise().then(() => {
  doSomething()
}).catch(() => {
})

somePromise().then(() => {
  doSomething()
}).catch((e) => {
  console.log(e)
})

为了解决这个问题,医典这边做了一个 eslint 插件@tencent/eslint-plugin-medical,能够检查 try catch 里的 catch 代码块、promise 的 catch 代码块,是否为空,是否只有 console 调用。当然,有些时候,并不需要对异常逻辑进行额外业务逻辑处理,catch 里可以加一个上报。

2.6 是否含有安全风险的代码

这一步可以在流水线里接入安全风险检测插件进行处理。以下是医典接入后的一个示例分析。

确实存在一些误判,比如会把mixin关键字当做泄露人名来进行告警,开发人员可以对照分析是否需要处理。

前端常见的硬编码场景有:

  • 请求参数和返回对象 比如之前就遇到过,开发同学把 mock 的请求参数 id,放到了线上的情况。(因为该接口是根据医生 id,拉取评论,评论也是后端灌的假数据,所以在测试阶段都没发现)
// 请求参数硬编码
getCommentsApi({ doctorId: 1 }).then((res) => {
  doSomething()
}).catch(() => {
  handleError();
})

也出现过 ABtest 接口,开发同学本地模拟返回对象,忘记删除硬编码的情况

fetchABTestApi().then((res) => {
  // res.data
  const obj = {
    imgSrc: 'xxx',
    name: 'qinmu'
  }
})

接口 mock 的硬编码,完全可以通过使用 mock 平台来解决。推荐使用专业的接口管理平台来进行接口管理、mock 等,这里我们使用的是腾讯内部接口管理平台 tolstoy。该产品还未正式开源,欢迎提前关注。

  • 路由参数
// bad case 硬编码1001
const isActive = this.$route.query.id === '1001'

// good case 写到配置信息中。这样,id和状态的对应关系一目了然,便于管理和维护。
const idConfig = {
  1001: STATUS.ACTIVE
}
const isActive = idConfig[this.$route.query.id] === STATUS.ACTIVE
2.7 格式校验

输入框的校验规则除了满足产品需求,比如多少字符以内、允许哪些字符,还有一个点:前后端需要校验规则保持一致。最好用统一的正则表达式,不然容易造成前端校验通过、后端校验不通过的情况。

上传文件,前后端需求校验文件格式、文件大小。尤其是后端,需要对 content-type 为 text/html 的加以限制,防止出现安全问题。我们已经有过此类安全问题的工单了。

3. 代码习惯

3.1 if-else 嵌套不能超过 4 层

拒绝面条代码,减少代码中各种结构的嵌套,例如 if-else、try-catch、循环等。尽量控制在三层以内,增加可读性、降低圈层复杂度。你肯定不愿意维护这样辣眼睛的代码:

async getConfig(id, type = '', isReset = false) {
  try {
    if (liveid) {
       const res = await someApi(id);
       if (res && res.info) {
         const { status } = res.info
         status === 2 && doA({id, type});
         if (status === 1 || status === 2 || status === 4) {
           this.setData({
             info: res.info,
             status,
           })
           if (isReset) {
             this.setData({
               current: 0,
               index: 0
             })
             status === 2 && doB();
           }
           return { code: 0};
         }
         return doC();
       } else if (isReset) {
         resetSomething();
       } else if (isReset && type === someType) {
         handleType();
       }
       return wx.showModal({ //... })
    }
  } catch (error) {
    if (error.code === 1001) {
      reportA();
    } else {
      reportB();
      doD();
    }
  }
}
3.2 Don't repeat yourself

逻辑相同或相似的代码,应封装为函数进行调用。

// bad case 都有展示modal的逻辑,开发同学直接复制粘贴
function handleA(msg) {
  wx.showModal({
    title: '提示',
    content: msg,
    showCancel: false,
    confirmText: '确定',
    confirmColor: '#02BACC',
    success: (res) => {
      if (res.confirm) {
        doA();
       }
     },
  });
}

function handleB(msg) {
  wx.showModal({
    title: '提示',
    content: msg,
    showCancel: false,
    confirmText: '确定',
    confirmColor: '#02BACC',
    success: (res) => {
      if (res.confirm) {
        doB();
       }
     },
  });
}

function handleC(msg) {
  wx.showModal({
    title: '提示',
    content: msg,
    showCancel: false,
    confirmText: '确定',
    confirmColor: '#02BACC',
    success: (res) => {
      if (res.confirm) {
        doC();
       }
     },
  });
}

解决方案,封装 showModal 函数。

function showModal (msg) {
  return new Promise((resolve, reject) => {
    wx.showModal({
      title: '提示',
      content: msg,
      showCancel: false,
      confirmText: '确定',
      confirmColor: '#02BACC',
      success: (res) => {
        if (res.confirm) resolve()
      },
      fail: (err) => {
        reject(err)
      }
    })
  })
}

funtion handleA(msg) {
  showModal(msg).then(
    doA();
  ).catch(() => { catchHandler();})
}

funtion handleB(msg) {
  showModal(msg).then(
    doB();
  ).catch(() => { catchHandler();})
}

funtion handleC(msg) {
  showModal(msg).then(
    doC();
  ).catch(() => { catchHandler();})
}
3.3 不建议直接修改 Object 原型(或者 Function, Array 原型等)

在 Object.prototype 上定义方法就相当于 C++里定义宏, 而且还是 #define private public 这种。从可靠性来说,多人协作很容易出现冲突。从兼容性来说,你不能保证后续推出的原生方法实现和你现有的一致,也不能保证多个库之间对该方法的实现一致。比较有名的故事是 prototype 库的 getElementsByClassName。在还没有这个原生方法之前,prototype 这个库实现的是返回 Array,并且加了“each”方法:document.getElementsByClassName('myclass').each(doSomething);但原生方法出来后,返回的是 NodeList,并没有 each 方法;所以就悲剧了。

详细说明可以看:Nicholas C. Zakas 的 Maintainable JavaScript: Don’t modify objects you don’t own

3.4 回调嵌套不建议超过 3 层回调嵌套

减少回调的嵌套,避免产生callback hell:

fs.readdir(source, function (err, files) {
  if (err) {
    console.log('Error finding files: ' + err)
  } else {
    files.forEach(function (filename, fileIndex) {
      console.log(filename)
      gm(source + filename).size(function (err, values) {
        if (err) {
          console.log('Error identifying file size: ' + err)
        } else {
          console.log(filename + ' : ' + values)
          aspect = (values.width / values.height)
          widths.forEach(function (width, widthIndex) {
            height = Math.round(width / aspect)
            console.log('resizing ' + filename + 'to ' + height + 'x' + height)
            this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
              if (err) console.log('Error writing file: ' + err)
            })
          }.bind(this))
        }
      })
    })
  }
})

建议使用 promise、async/await 的方式让代码更为清晰可读;也可以将 callback 要做的事拆成独立的 function,并分别对 err 进行处理。

3.5 函数不超过 80 行

函数尽量精简在 80 行以内,并且以小 function 进行组织,方便维护、复用。

3.6 缺少注释及注释规范化

除了知道下面的逻辑是在绘制 canvas,其他逻辑你能看懂吗?

function doSomething() {
      let count;
      if ((count = width * height / 1000000) > 1) {
        count = ~~(Math.sqrt(count) + 1);
        const nw = ~~(width / count);
        const nh = ~~(height / count);
        const tCanvas = document.createElement('canvas');
        const tctx = tCanvas.getContext('2d');
        tCanvas.width = nw;
        tCanvas.height = nh;

        for (let i = 0; i < count; i++) {
          for (let j = 0; j < count; j++) {
            tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
            ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
          }
        }
      } else {
        ctx.drawImage(img, 0, 0, width, height);
      }
}

常用的注释分类有这些,建议参考 JSDoc:1)文件注释 2)变量注释 3)常量注释 4)函数注释 5)枚举注释 6)类的注释

  1. 类的属性注释
3.7 注释与实现功能不符

这一条在团队里是出现过现网 bug 的。

故事背景是开发 M 在重构代码时,设置底部栏状态这一逻辑已经封装出来,所以根据注释,下面几行代码做的事情也是设置底部栏状态,开发 M 就把这几行代码都删掉了。但是注释下面的代码,除了做设置底部栏状态的事情,还有一个 setBanner 函数,是为了设置 banner 位的,也被连同删掉,进而导致了 bug。

追溯原因,设置底部栏状态是 A 同学做的,设置 banner 位是 B 同学做的,B 同学在没有看注释的情况下,直接把 setBanner 放在了错误的位置上。

function fetchData() {
  // ...
  doManythings();

  // 设置底部栏状态
  setBanner();
  fetchStatusApi().then(res => {
    // ...
  }).catch(() => {
    // ...
  })
}
3.8 避免存在大量注释掉的无用代码

git 的版本管理能帮我们回溯之前的代码。如果项目里存在大量注释掉的代码,会降低可读性。

3.9 避免遗留大量多余的 console.log 调试日志

虽然 console.log 调试日志在生产环境构建时不会输出,但就本地开发环境来说,代码里惨杂过多 console.log 调试日志,控制台满屏的调试日志,对于每个接手的开发都是噩梦。另外,就像上面说的一样,catch 处理或 else 分支里存在只打 console.log 而不做任何处理的情况。尽量避免少使用 console.log,也可以减少这类意外的发生。

所以,日常开发调试建议使用浏览器 sources tab 的断点调试;另外,就算要输出调试日志,也不止有 console.log 可以使用,参考这篇文章。你可以使用 console.table 等来格式化输出

 

3.10 存在很多 eslint-disable 注释

我能想到的允许 eslint-disable 的场景只有一种,那就是解构后端返回对象。后端返回对象属性名是下划线,这个时候可能需要 // eslint-disable-next-line camelcase。其他情况我都不建议使用 eslint-disable,尤其是整个文件全局 eslint-disable。

之前遇到过某文件全局禁用"no-undef"规则,结果代码里使用了未定义的变量,导致现网 bug。如果你有全局定义的变量,建议写在 eslintrc.js 的 globals 字段里。当然,就正如上文代码错误-内存泄露提到的一样,非必要情况,不建议使用全局变量。

3.11 没有使用空行对代码分组

为了增强可读性,建议使用空行对代码分组。

3.12 命名规范

常见的不规范命名有这些,会让之后维护的同学很懵逼:

  • 单词拼写错误,比如 submitForm,写成 submitFrom。
  • 中英文混用。比如 gotoZaihai。你能知道这是什么意思吗?其实是跳到灾害专区活动页。goToDisasterZone 是不是要好一点,同学?
  • 以 1-9、a-z 命名 在项目里我曾经见过不知道怎么命名,就 type1、type2、type3 直接上了,也不写注释。非常让人抓狂。
  • 混用命名格式 就评论列表,代码里有 comments、commentList、也有 commentData、commentsData。???能规范统一一下吗。
  • 单复数不分 明明是一个列表数据,非要用单数表示,比如 disease。建议区分下单复数,如果是数组就用List 来表示。
  • 动词、名词、形容词不分 比如,一个函数名,命名为名词“doctor”;而一个 Vue computed 属性,又命名为 getUserInfo;表示关闭状态,命名为“close”;真是让人非常头疼。
// bad case 1
function doctor () {}

// bad case 2
computed: {
  getUserInfo() {}
}

// bad case 3
close = false;

同学,就不能好好写代码吗?

// good case 1
function getDoctorInfo() {}

// good case 2
computed: {
  userInfo() {}
}

// good case 3
closed = false
3.13 过多的非业务逻辑相关代码(如超过 10 行的上报, 参杂在业务逻辑里)

如果在业务逻辑里掺杂太多的上报,后续理解业务逻辑时需要看上报逻辑,查上报逻辑的时候也需要理解大量的业务代码。点击埋点和曝光埋点都可以以属性的形式挂在元素上,通过冒泡,统一进行处理。

<button
data-exposurename="test-exposure"
:data-exposureval="{event:'bottom.btn'} | jsonStringify"
data-eventname="button.click"
:data-eventval="{id: buttonId} | jsonStringify"
/>

如果你上报的参数需要根据不同渠道来配置,建议封装出来,不要和业务逻辑耦合了。

3.14 没有 README 文档、或者 README 太简单、太作用有限

除了项目的 READMD,每个模块都应该有各自的 README,说明这个模块的功能点、技术实现方案等。看个人习惯,你也可以写在 iwiki 里,在 README 放一个 iwiki 的链接。

3.15 尽量使用 export 而 不是 export default 来导出

export default 有两个问题:1)不利于 tree shaking 2)如果使用了一个导出对象上不存在的属性,要运行时才能发现。

4.代码优化【持续更新中】

4.1 避免大量直接操作 dom 节点

直接操作 DOM 的性能损耗至少有两个地方:进行 DOM 操作的时候上下文切换 + DOM 操作引起的页面重绘

4.2 避免使用 delete

delete 操作符并不会释放内存,而且会使得附加到对象上的 hidden class 失效,让对象变成 slow object。(hidden class 是 V8 为了优化属性访问时间而创建的隐藏类)来看一下执行速度对比:undefined > delete > omit 。

4.3 是否引用了不必要的 npm 包

比如做一个简单图表的需求,不选轻量的库,非要整一个 echarts;或者实现一个简单的代码编辑器,monaco-editor 有 min 版本不使用,非要引用一整个 monaco-editor。还有,lodash 没法做 tree-shaking,要么引用一个具体的子包lodash.get,要么引用lodash-es,非要引用一整个 lodash。

4.4 尽量使用 CDN 地址的图片

如果代码里引用的是本地图片,构建打包会有耗时。可以在引用之前就把图片传到 cdn 上,代码里直接使用 cdn 地址。

hello芳芳
关注 关注
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端性能优化方案
少女心の程序媛
02-27 9294
一、使用CDN【内容分发网络】加速1、CDN CDN【Content Delivery Network】,即内容分发网络。属于http缓存技术中的一种。 2、原理:其基本思路是尽可能避开网络上可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。CDN管理分布在多个地理位置上的服务器,其系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请
前端优化代码的方法
weixin_35755823的博客
12-19 1125
前端代码优化的方法有很多,下面列举一些常见的方法: 使用 CDN 加速资源加载:将静态资源(如 JavaScript 库、字体文件、图片等)放到 CDN 上,能够有效加快资源加载速度。 减少 HTTP 请求数:可以将多个文件合并成一个文件,或者使用 CSS Sprites 技术将多张小图合并成一张大图,以减少 HTTP 请求数。 使用缓存:设置缓存头可以让浏览器缓存页面中的资源,在用户下次访...
优化冗余代码:提升前端项目开发效率的实用方法
最新发布
软贱开发攻城狮
07-27 1万+
前端开发中,我们常常会遇到代码冗余的问题,这不仅增加了代码量,还影响了项目的可维护性和开发效率。还有就是有时候会接到紧急业务需求,要求立马完成上线,这时候多人协作开发,代码质量不会很高,很多都是复制粘贴;亦或是接手的代码比较老旧,公共组件里面写了大量冗余代码,这种情况下时间越久,开发起来就越难受。那么本文将结合实际项目案例,分享一些优化冗余代码的实用方法,帮助大家缓解技术债的问题,并提升前端项目的开发效率,欢迎在评论区留言交流。
前端代码优化
inggni的博客
08-03 2085
1、后端返回的数据是对象形式,但是前端页面用数组渲染是最方便的。这个时候就需要处理一下;主要思想就是在于利用vue的computed(计算属性),因为后端给的是object形式,而我们想要的是数组,这个时候就需要我们自己模拟数据,自己写一个数组,数据就是根据页面展示内容来,但是还需要多传入一个prop值(这个值就是需要跟后端的字段一一对应),这个值就是在计算属性中需要用到的,其实接下来大家都能想到了,就是当prop的值和后端的字段对应上时,就展示当前数据。 formList[item.prop]
前端优化代码
高先生的猫
07-21 593
if 判断的优化 JavaScript条件语句在我们平时的开发中是不可避免要用到的,但是很多时候我们的代码写的并不好,一连串的if-else或者多重嵌套判断都会使得代码很臃肿,下面举例进行优化。 需求:现在有 4 个产品,分别是手机、电脑、电视机、游戏机,当然每个产品显示的价格不一样。 1、最简单的方法:if 判断 let commodity = { phone: '手机', computer: '电脑', television: '电视', gameBoy: '游戏机', ...
前端代码(HTML5、CSS3、JS)优化
不想学习的打工人的博客
01-01 1217
JS 开销在哪,除了必要的加载外,还有解析编译以及代码的执行
前端如何优化代码?
weixin_33719619的博客
09-08 474
1、避免全局查找 为避免全局查找,一般的做法,都是在函数中将全局对象存储为局部变量来处理,加快访问速度。 2、减少循环次数 3、条件分支使用 将条件分支,按可能性顺序从高到低排列,以减少解释器对条件的探测次数。 在同一条件 &gt;2条件分支时:使用switch优于if:switch分支选择的效率高于if,在IE下尤为明显。4条分支的测试,IE下switch的执行时间约为if的一半。 使用三...
断点续传以及秒传前端代码优化后代码可以直接启动;已把model的代码也打包
03-29
断点续传以及秒传前端代码实现,可直接启动使用,已经把model的代码全部打包进去,开箱即用,npm的版本用的是9.6的,md5和uploader的包不需要执行导入,以及main.js和实例代码都已经修改好了,直接用就行
前端优化方法大全
daxi玫瑰的博客
07-13 6564
前端优化方法大全
前端-代码走查模板.docx
12-23
前端项目管理中,代码走查是一个至关重要的环节,它有助于规范开发行为,...在遇到问题时,及时与代码审核人员沟通,共同优化解决方案。通过这种集体智慧的结晶,我们能够打造出更加健壮、高效、易于维护的前端应用。
前端代码优化(持续整理)
m0_38038767的博客
11-29 327
会有这个问题,是因为一些良好的代码风格不仅可以让自己舒服,也可以让后继者容易查看,不会揉成一坨或者是长短不一,极奇难查看。 如果有刚入门的小伙伴,下面的内容可以做一个参考。如果有不妥的地方欢迎指出。 1、变量名 变量名是很重要的一部分。所以我们一般要尽可能地让我们的变量名有意义,比如名字,一般会是name,自我感觉是想这种简短的单词就不用再缩写了,也就是不用写成n; 多个单词组成的变量名,可以使用驼峰的方式,比如userName。 常量变量可以是USER_NAME这样的写法 最为重要的是,请不要一段代码下来
怎么优化前端代码
心中有侠
07-30 270
ajax.url 配置文件  /** * */ var baseurl = "http://localhost:8080/"; ajax配置文件  /** * */ var getsetajax = { "getMehtod":function(data,url){ var resData; $.ajax({ type: "get"...
前端代码优化小技巧
CeshirenTester的博客
06-09 522
导读今天分享一下开测前端代码的一些优化,及使用的一些小技巧,来优化我们的网站,前端开发中最常见的问题就是很少使用ES6方法导致代码冗余,不够清晰,定时器和闭包导致内存溢出及泄露,网站中css导致排版错乱,请求图片过多,导致网站加载缓慢,网站中兼容各种浏览器的问题。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u57yIv70-1654767478136)(https://ceshiren.com/uploads/default/original/3X/f/7/f752d317
前端代码性能优化
azun31128的博客
07-13 126
1.display:none;优于visibility:hidden;前者隐藏不占用物理空间,后者会占用。2.合并margin,padding,border的-top,-left,-right,-bottom的设置,简短简洁。3.选择器在满足效果的基础上,尽量简单,减少嵌套,查询的消耗。4.如若值为0,则去掉单位,如border-right:0px;可以写为border-right:0...
前端代码优化方法
Calamus
09-21 650
一、减少HTTP请求 1.合并CSS、js:每次调用js、css都要发送一次http请求,所以并不是分开写好几个文件比较好   js、css压缩。js压缩可以用grunt HTML优化: 使用语义化标签 减少iframe:iframe是SEO的大忌,iframe有好处也有弊端 避免重定向 CSS优化: 删除空样式 不滥用浮动,字体,需要加载的网络字体根据网站...
前端开发】代码结构及性能优化大总结
go
06-08 5479
1、前端结构组织与文件命名规范 前端结构组织具有如下原则: 同一项目中代码的组织结构要清晰 同类型文件归类到相同的文件夹中 文件命名规则须统一并且命名要有意义 HTML 命名规范 HTML 代码所有的标签名和属性应该都为小写 属性值应该用引号括起来 元素的 id 与 class 按照特定规范命名 代码缩进 4 个空格 给 HTML 代码块添加必要注释 CSS 命名规范 尽量使用 class 选择器进行样式设定 类命名时取父元素的 class 名作为前缀,使用-连接 类名与样式之间以空格进行分割 添
前端性能优化-Vue代码层面
weixin_30345055的博客
08-16 195
1、v-if 和 v-show 区分使用场景  v-if 是 真正 的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。  v-show就简单得多, 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display 属性进行切换...
前端代码优化与规范实践
"该文档是关于前端开发中的代码规范和注意事项的总结,主要涉及如何避免在界面中直接编写样式以及优化HTML...遵循这些最佳实践,可以显著提高前端代码的可读性、可维护性和性能,从而创建出更加专业和高质量的Web应用。
写文章

热门文章

  • Uncaught DONException: Failed to execute ‘atob‘ on “window ‘: The string to be decoded is not carrec... 11059
  • vue 在线预览word、excel、pdf、txt、图片 6797
  • Vue数据更新页面却没有更新的几种情况以及解决方法 6512
  • Lodash 两个数组合并-排重 5088
  • npm安装yarn报npm ERR Unexpected token ‘.‘错误的解决办法 4768

分类专栏

  • vue 3篇

最新评论

  • vue图标不显示

    普通网友: 文章构思巧妙,结构紧凑,既有深度又有广度,读后让人受益匪浅,确实是一篇值得一读的佳作。【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】

  • el-table vxe-table 表格宽度拖拽

    CSDN-Ada助手: Vue入门 技能树或许可以帮到你:https://edu.csdn.net/skill/vue?utm_source=AI_act_vue

  • vxe-table表头字段的显示隐藏 vxe-toolbar使用

    大憨憨憨憨憨憨憨~~~: 刚解决https://blog.csdn.net/qq_39689605/article/details/108339567?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-108339567-blog-124636732.235%5Ev43%5Epc_blog_bottom_relevance_base9&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-108339567-blog-124636732.235%5Ev43%5Epc_blog_bottom_relevance_base9&utm_relevant_index=2

  • vxe-table表头字段的显示隐藏 vxe-toolbar使用

    GOT水獭: 大佬,动态设置表头列的底部 确认、还原 按钮绑定的事件在哪找?

  • Uncaught SyntaxError: Unexpected token '.'

    Re.237: 我的是谷歌报错,IE和其他浏览器都没事儿

最新文章

  • slot插槽灵活应变显示表单的顺序,多少
  • 非常有用的 48 个 JavaScript 代码片段,值得收藏!
  • vue自写组件可输入,可下拉选择,因为el-autocomplete数据多了会卡
2024
09月 1篇
08月 1篇
07月 11篇
06月 4篇
05月 9篇
04月 5篇
03月 4篇
02月 7篇
01月 1篇
2023年25篇
2022年15篇
2021年35篇
2020年44篇
2019年29篇
2018年26篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

深圳SEO优化公司天河seo网站排名优化太原企业网站优化推广有哪些怎么优化网站排名网站排名优化软件联系方式顺义区互联网网站优化记录德宏网站优化外包青铜峡怎么做网站优化黑龙江网站优化方法兰州网站优化排名怎么做好名海安网站优化怎么做行业网站优化怎么做三都县网站优化营销网站优化方向宣城网站搜索优化哪家有名商丘网站搜索引擎优化哪家好淘宝里的网站优化靠的住吗网站内部优化教程电影中如何优化网站响应式网站对优化有帮助吗电商网站该如何优化朔州网站的优化山东网站优化学校认识网站转化率优化的方法龙岗网站优化巩义网站关键词优化服务怎么选深圳网站关键字优化网站建设与优化up宀云速捷柳州专业网站优化资阳网站优化方案北京网站优化推广收集歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化