N 个值得一看的前端代码片段!

公众号:程序员白特,欢迎一起交流学习~

原文:https://juejin.cn/post/7371312967781777418?share_token=3a57c02e-638d-4a6c-aea7-a2def21d30a9

在日常的开发过程中,我们都会有一些常用的代码片段,这些代码片段可以直接复制到各个项目中使用,非常方便。如果你有接手过别人的项目,就可以很明显感受到几个项目一般都会有一些相同的工具类方法,这些方法就是之前开发者的常用代码片段。

现在前端社区相当完善,有许多好用质量又有保证的库,如 lodashdayjsclassnamesjs-cookie 等,这些库基本能满足你开发中对数组、日期、类名、cookie 等的处理。

所以本文会尽量不重复介绍那些很常见的代码片段。

1. 检测元素之外的点击

在实现隐藏弹窗或收起下拉框时,如果你还在一层层判断是否点击了某个元素之外的区域,赶紧试试使用 contains 方法来实现。

document.addEventListener('click', function (evt) {
 // isClickedOutside 为 true 如果点击的元素在 ele 之外
 const isClickedOutside = !ele.contains(evt.target);
});

2. 快速打开官网

当你想查看第三方库的主页和代码仓库时,你可以使用一下命令快速打开:

// 打开主页
npm home PACKAGE_NAME
npm home react
// 打开代码仓库
npm repo PACKAGE_NAME
npm repo react

3. 一次性的事件监听

除了在监听的事件函数中移除当前的监听外,也可以使用 once 参数。

const handler = function (e) {};
ele.addEventListener('event-name', handler, { once: true });

4. 格式化时分秒

在展示音视频时长之类的场景时,需要把时长秒数格式为 HH:mm:ss 的格式。

const formatSeconds = (s) =>
 [parseInt(s / 60 / 60), parseInt((s / 60) % 60), parseInt(s % 60)]
 .join(':')
 .replace(/\b(\d)\b/g, '0$1')

如果你想显示“刚刚”、“5分钟前”之类的内容,可以尝试 timeago.js 库。

5. URL 参数转化为对象

获取 url 参数有个热门的库 query-string,如果不想使用的话,可以通过 URLSearchParams API 实现。

const getUrlParams = (query) =>
  Array.from(new URLSearchParams(query)).reduce(
    (p, [k, v]) =>
      Object.assign({}, p, { [k]: p[k] ? (Array.isArray(p[k]) ? p[k] : [p[k]]).concat(v) : v }),
    {}
  )
  
// 获取 query 参数
getUrlParams(location.query)
// { a: ['1', '4'], b: '2', c: '3' }
getUrlParams('?a=1&b=2&c=3&a=4')

// 获取 hash 参数
getUrlParams(location.hash.split('?')[1])

6. 打开新页签

看似平平无奇的打开页签,但是需要关注下 rel,如果要打开外链,建议设置为 noopener noreferrer,避免一些恶意网站通过 window.opener.location 重定向你的网站地址。window.open 方法同理。

// 高版本浏览器 rel 默认为 noopener,不过建议显示设置,兼容低版本。
<a target="_blank" rel="noopener noreferrer">...</a>

// window.open rel 默认为 opener,需要自己设置
window.open('https://baidu.com', 'baidu', 'noopener,noreferrer')

// 以下有安全漏洞,打开的新页签可以通过 window.opener.location 重定向你的网站
<a target="_blank" rel="opener">...</a>
window.opener.location = 'http://fake.website.here';

7. 显示上传的图片

通过 fileReader API 的 readAsDataURL 方法来显示上传图片

function readImage() {
  const fileReader = new FileReader()
  const file = document.getElementById('uploaded-file').files[0]

  if (file) {
    fileReader.readAsDataURL(file)
  }

  fileReader.addEventListener(
    'load',
    () => {
      const result = fileReader.result
      const resultContainer = document.getElementById('result')
      const img = document.createElement('img')
      img.src = result
      resultContainer.append(img)
    },
    { once: true }
  )
}

8. 文件下载

使用 a 标签的 download 属性,同源才能触发下载,IE 不支持,移动端兼容性也不太好。

<a href="/path/to/file" download>Download</a>

// 或者 js 临时生成 a
function download(url) {
  const link = document.createElement('a')
  link.download = 'file name'
  link.href = 'url'

  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

静态资源服务器设置响应头也能触发浏览器下载。

Content-Disposition: attachment; filename="filename.jpg"

除了在线文件下载,你还可以创建一个 text 或 json 文件,并下载,主要用到了 Blob 对象和 createObjectURL 方法。

const data = JSON.stringify({ 'message': 'Hello Word' });
const blob = new Blob([data], { type: 'application/json' });
// 创建一个 URL
const url = window.URL.createObjectURL(blob);
// 用上面的 download 方法下载这个 url
...
// 释放创建的 URL
window.URL.revokeObjectURL(url);

9. 缓存结果

缓存函数的结果,当计算比较复杂时可以使用。

const memoize = (fn) =>
  (
    (cache = Object.create(null)) =>
    (arg) =>
      cache[arg] || (cache[arg] = fn(arg))
  )()

10. 多行省略号

单行或多行截断显示省略号,很常用的 CSS 片段。

.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.truncate {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

11. 选中最后几个元素

// 前三个
li:nth-child(-n + 3) {
  text-decoration: underline;
}

// 选中 2-5 的列表项
li:nth-child(n + 2):nth-child(-n + 5) {
  color: #2563eb;
}

// 倒数两个
li:nth-last-child(-n + 2) {
  text-decoration-line: line-through;
}

12. 滚动条样式

自定义滚动条样式也是很常见的需求,除了通过样式,也可以通过第三方库(如 better-scroll 等)来实现自定义滚动条样式。

/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar {
 width: 8px;
 height: 8px;
}
/*定义滚动条轨道 内阴影+圆角*/
::-webkit-scrollbar-track {
 border-radius: 10px;
 background-color: #fafafa;
}
/*定义滑块 内阴影+圆角*/
::-webkit-scrollbar-thumb {
 border-radius: 10px;
 background: rgb(191, 191, 191);
}
// 较新的 API
body {
 scrollbar-width: thin;
 scrollbar-color: #718096 #edf2f7;
}

13. 百分比计算 - 最大余额法

计算百分比时,由于四舍五入,各个比例相加可能不等于 1,通过最大余额法可以保证总数为 1。

// 输出 ['32.56%', '6.97%', '27.91%', '32.56%']
getPercentWithPrecision([56, 12, 48, 56], 2)

// 具体最大余额法算法可以网上搜索查看
function getPercentWithPrecision(valueList, precision) {
  // 根据保留的小数位做对应的放大
  const digits = Math.pow(10, precision)
  const sum = valueList.reduce((total, cur) => total + cur, 0)
  
  // 计算每项占比,并做放大,保证整数部分就是当前获得的席位,小数部分就是余额
  const votesPerQuota = valueList.map((val) => {
      return val / sum * 100 * digits
  })
  // 整数部分就是每项首次分配的席位
  const seats = votesPerQuota.map((val) => {
    return Math.floor(val);
  });
  // 计算各项的余额
  const remainder = votesPerQuota.map((val) => {
    return val - Math.floor(val)
  })
    
  // 总席位
  const totalSeats = 100 * digits
  // 当前已经分配出去的席位总数
  let currentSeats = votesPerQuota.reduce((total, cur) => total + Math.floor(cur), 0)
    
  // 按最大余额法分配
  while(totalSeats - currentSeats > 0) {
    let maxIdx = -1 // 余数最大的 id
    let maxValue = Number.NEGATIVE_INFINITY // 最大余额, 初始重置为无穷小

    // 选出这组余额数据中最大值
    for(var i = 0; i < remainder.length; i++) {
      if (maxValue < remainder[i]) {
        maxValue = remainder[i]
        maxIdx = i
      }
    }
        
    // 对应的项席位加 1,余额清零,当前分配席位加 1
    seats[maxIdx]++
    remainder[maxIdx] = 0
    currentSeats++
  }
    
  return seats.map((val) => `${val / totalSeats * 100}%`)
}

14. 限制并发

当有大量请求需要发起时,往往需求限制并发数量保证其他请求能优先返回。

async function asyncPool(poolLimit, iterable, iteratorFn) {
  // 用于保存所有异步请求
  const ret = [];
  // 用户保存正在进行的请求
  const executing = new Set();
  for (const item of iterable) {
    // 构造出请求 Promise
    const p = Promise.resolve().then(() => iteratorFn(item, iterable));
    ret.push(p);
    executing.add(p);
    // 请求执行结束后从正在进行的数组中移除
    const clean = () => executing.delete(p);
    p.then(clean).catch(clean);
    // 如果正在执行的请求数大于并发数,就使用 Promise.race 等待一个最快执行完的请求
    if (executing.size >= poolLimit) {
      await Promise.race(executing);
    }
  }
  // 返回所有结果
  return Promise.all(ret);
}

// 使用方法
const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i));
asyncPool(2, [1000, 5000, 3000, 2000], timeout).then(results => {
  console.log(results)
})

15. uuid

生成 uuid 的代码片段

const uuid = (a) =>
  a
    ? (a ^ ((Math.random() * 16) >> (a / 4))).toString(16)
    : ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid)

16. 打开 Modal 时禁止 body 滚动

打开弹窗的时候,会发现背后的内容还是可以滚动,我们需要在弹窗出现时禁用滚动,在弹窗消失时恢复。

// 打开 Modal 时,禁止 body 滚动
document.body.style.overflow = 'hidden';
// 恢复滚动
document.body.style.removeProperty('overflow');
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 写一个游戏网络的前端代码,需要添加的网络功能很多,比如:创建网络会话,发送数据和接收数据,管理连接状态,实现网络消息的发送与接收,网络安全等等。具体的代码实现可以根据实际情况而定,可以使用不同的语言或者框架来实现。 ### 回答2: 游戏网络前端代码是指用于构建游戏网站或应用的用户界面的代码。下面我将用300字以中文回答如何编写一个游戏网络的前端代码。 首先,我们需要使用HTML来构建网页的骨架。我们可以创建一个包含游戏标题和主要内容的顶部导航栏,以及游戏的主要区域。在游戏区域中,我们可以放置游戏的界面元素,如游戏地图、操作按钮等。 接下来,我们可以使用CSS来为网页添加样式。通过定义选择器和属性,我们可以设置字体、颜色、背景和布局等,以使游戏界面更加美观和用户友好。 然后,我们可以使用JavaScript来实现一些交互功能。通过监听用户的操作事件,我们可以实现按钮点击、键盘输入等操作的响应。例如,当用户点击“开始游戏”按钮时,我们可以触发游戏的启动函数并开始游戏逻辑。 在游戏网络前端代码中,我们还可以使用AJAX技术与服务器进行交互。通过发送异步请求,我们可以获取游戏数据、存储玩家信息等。这将为游戏带来更多的功能和互动性。 此外,我们可以使用前端框架和库来简化开发工作。例如,使用React或Vue.js可以更高效地构建用户界面,使用Bootstrap可以更方便地添加响应式布局和组件。 最后,我们应该考虑对游戏网页进行优化。这包括减少代码的大小和复杂性,以提高加载速度和响应性。同时,我们还可以进行跨浏览器和设备的兼容性测试,以确保游戏在不同环境下都能正常运行。 总结起来,编写游戏网络前端代码需要使用HTML、CSS、JavaScript和AJAX等技术,结合前端框架和库,以及对代码的优化和测试。这样才能实现一个功能完善、界面友好的游戏网络应用。 ### 回答3: 游戏网络前端代码的编写可以使用多种语言和技术,我将以JavaScript为例,简单介绍一个游戏网络的前端代码。 首先,我们需要创建一个HTML文件作为游戏的页面框架。在HTML中,我们可以使用 `<canvas>` 元素作为游戏画布,利用其提供的API进行绘图操作。 通过JavaScript,我们可以编写游戏逻辑和交互的代码。可以使用面向对象的方式创建游戏对象,例如玩家角色、敌人角色、障碍物等等。每个角色可以有自己的属性和方法,比如移动、碰撞检测等。 在游戏逻辑中,我们可以使用事件监听器来响应用户的操作,比如按下键盘、点击鼠标等。通过相应事件的处理函数,我们可以更新游戏状态,比如玩家移动、敌人生成等。 为了提高用户体验,我们可以在游戏中加入动画效果。利用JavaScript的定时器函数,可以定时执行一段代码,从而实现帧动画效果。每帧的绘制时可以使用 `<canvas>` 的API进行绘制。 为了使游戏更具交互性,我们可以引入一些游戏外部资源,比如声音、图片等。通过JavaScript的 `Audio` 对象和 `Image` 对象,可以加载并使用这些资源。 最后,我们还可以使用一些前端框架,如Phaser.js,来简化游戏的开发过程。这个库提供了很多游戏开发的常见功能和工具,可以大大提高开发效率。 总结起来,游戏网络前端代码的编写包括创建HTML页面框架、使用JavaScript编写游戏逻辑和交互、添加动画效果、引入游戏资源等,通过这些步骤来实现一个简单的游戏网络前端代码

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值