收集js小技巧

4 个月前

20231206

1、判断内容是否超出元素范围

在一个设置了超出显示省略号的元素中,如何判断是否显示了省略号从而添加提示框

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

可根据元素的 scrollWidth 和 offsetWidth 来判断

// 获取所有使用了ellipsis样式的元素
var elements = document.querySelectorAll('.ellipsis');
// 遍历这些元素
for (var i = 0; i < elements.length; i++) {
    var el = elements[i];
    // 如果元素的内容超出了其容器的宽度
    if (el.scrollWidth > el.offsetWidth) {
        // 添加title属性
        el.title = el.textContent;

同时监听元素的尺寸变化来动态调整,使用 ResizeObserver

const ro = new ResizeObserver(entries => {
  for (let entry of entries) {
    const {width, height} = entry.contentRect;
    console.log('Element:', entry.target);
    console.log(`Element size: ${width}px x ${height}px`);
// 观察一个具体的 DOM 节点
const el = document.querySelector('.ellipsis')
ro.observe(el );
// 取消监听
ro.unobserve(el)
// 取消所有监听
ro.disconnect()

20230821

1、验证图片格式和大小

checkImg(file) {
  const isJPG = file.type === 'image/jpeg'
  const isLt2M = file.size / 1024 / 1024 < 2
  if (!isJPG) {
    this.$message.error('上传头像图片只能是 JPG 格式!')
  if (!isLt2M) {
    this.$message.error('上传头像图片大小不能超过 2MB!')
  return isJPG && isLt2M

20230628

1、可插入内容的编辑框:可插入标签、可选择部分文本进行添加链接

<div class="container">
  <div contenteditable id="editDiv"></div>
  <span class="tag add-btn">添加标签</span>
</div>
<div class="add-link">
  <input type="text" class="input">
  <span class="link-btn confirm"></span>
  <span class="link-btn remove">×</span>
</div>
<script>
  const editDiv = document.querySelector('#editDiv')
  // 纯文本粘贴
  editDiv.addEventListener('paste', function(e) {
    e.preventDefault()
    const text = (event.clipboardData || window.clipboardData).getData('text/plain');
    const selection = document.getSelection();
    if (selection.rangeCount) {
      const range = selection.getRangeAt(0);
      range.deleteContents();
      const textNode = document.createTextNode(text);
      range.insertNode(textNode);
      range.setStartAfter(textNode);
      selection.removeAllRanges();
      selection.addRange(range);
  // 显示输入链接框
  editDiv.addEventListener('mouseup', showAddLink)
  editDiv.addEventListener('keyup', showAddLink)
  const addBtn = document.querySelector('.add-btn')
  // 插入标签
  addBtn.addEventListener('click', function() {
    editDiv.focus()
    const tag = '<span contenteditable="false" class="tag">添加标签</span>'
    const el = document.createElement('div')
    el.innerHTML = tag
    const tagNode = el.firstChild
    const selection = window.getSelection()
    if (selection.rangeCount) {
      const range = selection.getRangeAt(0)
      range.insertNode(tagNode)
      range.setStartAfter(tagNode)
      range.setEndAfter(tagNode)
      selection.removeAllRanges()
      selection.addRange(range)
  const addLink = document.querySelector('.add-link')
  let globalRange = null
  function showAddLink() {
    const selection = window.getSelection()
    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0)
      if (range.toString().length > 0) {
        globalRange = range
        addLink.style.display = 'block'
        positionAddLink()
      } else {
        addLink.style.display = 'none'
  function positionAddLink() {
    if (!globalRange) return
    const rect = globalRange.getBoundingClientRect()
    addLink.style.top = rect.top - addLink.offsetHeight - 15 + "px"
    addLink.style.left = rect.left - (addLink.offsetWidth - rect.width) / 2 + "px"
  const confirmEl = document.querySelector('.confirm')
  const inputEl = document.querySelector('.input')
  // 添加链接
  confirmEl.addEventListener('click', function() {
    const selection = window.getSelection()
    selection.removeAllRanges()
    selection.addRange(globalRange)
    const link = document.createElement("a")
    link.textContent = globalRange.toString()
    link.href = inputEl.value
    globalRange.deleteContents()
    globalRange.insertNode(link)
    addLink.style.display = 'none'
    inputEl.value = ""
    globalRange = null
  const removeEl = document.querySelector('.remove')
  // 去掉链接
  removeEl.addEventListener('click', function() {
    if (!globalRange) return
    const selection = window.getSelection()
    const anchorNode = globalRange.startContainer.parentNode
    if (anchorNode.tagName === "A") {
      const textNode = document.createTextNode(anchorNode.textContent)
      anchorNode.replaceWith(textNode)
      selection.removeAllRanges()
      globalRange.selectNode(textNode)
      selection.addRange(globalRange)
      addLink.style.display = 'none'
</script>
<style>
    margin: 0;
    padding: 0;
  .container {
    width: 500px;
    margin: 30vh auto 0;
  #editDiv {
    width: 100%;
    min-height: 120px;
    border: 1px solid #dcdfe6;
    padding: 5px 15px;
    line-height: 1.5;
    color: #606266;
    border-radius: 4px;
    outline: none;
    margin-bottom: 15px;
    font-size: 14px;
  #editDiv:hover {
    border-color: #c0c4cc;
  #editDiv:focus {
    border-color: #1890ff;
  #editDiv a {
    color: #409eff;
  .tag {
    padding: 2px 5px;
    font-size: 12px;
    background: #e8f4ff;
    border: 1px solid #d1e9ff;
    border-radius: 4px;
    color: #1890ff;
    user-select: none;
    margin: 0 4px;
  .add-btn {
    padding: 5px 10px;
    font-size: 14px;
    cursor: pointer;
  .add-btn:hover {
    background: #409eff;
    border-color: #409eff;
    color: #fff;
  .add-btn+.add-btn {
    margin-right: 4px;
  .add-link {
    background: #fff;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    padding: 15px;
    position: fixed;
    display: none;
  .add-link::after {
    content:"";
    display:block;
    position: absolute;
    bottom:-20px;
    left:50%;
    transform:translateX(-50%);
    width: 0;
    height:0;
    border: 10px solid transparent;
    border-top-color: rgba(0, 0, 0, 0.1);
  .add-link::before {
    content:"";
    display:block;
    position: absolute;
    bottom:-19px;
    left:50%;
    transform:translateX(-50%);
    width: 0;
    height:0;
    border: 10px solid transparent;
    border-top-color: #fff;
    z-index:2;
  .input {
    width: 200px;
    height: 36px;
    font-size: 14px;
    color: #606266;
    border: 1px solid #dcdfe6;
    outline: none;
    border-radius: 4px;
    padding: 0 10px;
  .input:hover {
    border-color: #c0c4cc;
  .input:focus {
    border-color: #1890ff;
  .link-btn {
    font-size: 16px;
    color: #409eff;
    padding: 5px;
    cursor:pointer;
</style>

2、插入带“&nbsp;”的方法

function insertHtmlAtCursor(html) {
  var sel, range;
  if (window.getSelection) {
    // IE9 and non-IE
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
      range = sel.getRangeAt(0);
      range.deleteContents();
      // Range.createContextualFragment() would be useful here but is
      // non-standard and not supported in all browsers (IE9, for one)
      var el = document.createElement("div");
      el.innerHTML = html;
      var frag = document.createDocumentFragment(),
        node, lastNode;
      while ((node = el.firstChild)) {
        lastNode = frag.appendChild(node);
      range.insertNode(frag);
      // Preserve the selection
      if (lastNode) {
        range = range.cloneRange();
        range.setStartAfter(lastNode);
        range.collapse(true);
        sel.removeAllRanges();
        sel.addRange(range);
  } else if (document.selection && document.selection.type != "Control") {
    // IE < 9
    document.selection.createRange().pasteHTML(html);
insertHtmlAtCursor('&nbsp;&nbsp;<span contenteditable="false" class="tag">添加标签</span>&nbsp;&nbsp;');

20230627

1、验证 url

function validURL (url) {
  const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
  return reg.test(url)

2、获取本地文件的 url

URL.createObjectURL(file)

3、获取音频文件的时长

let duration = 0
const audioEl = document.createElement('audio')
audioEl.src = URL.createObjectURL(file)
audioEl.addEventListener('loadedmetadata', function() {
  duration = audioEl.duration

在视频/音频(audio/video)加载过程中,触发事件的顺序如下:

onloadstart=>onduratuionchange=>onloadedmetadata=>onloadeddata=>onprogress=>oncanplay=>oncanplaythrough

4、中断 forEach 循环

(1)通过抛出错误

const arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
try {
  arr.forEach(i => {
    console.log(i)
    if (i === 'd') throw new Error('中断 forEach 循环')
} catch (e) {
  console.log(e.message)

(2)使用 some() 或 every() 来终止循环,some 返回 true 可退出循环,every 返回 false 可退出循环

const arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
arr.some(i => {
  console.log(i)
  return i === 'd'
arr.every(i => {
  console.log(i)
  return i !== 'd'

5、匹配所有 span 标签并获取其内容

const regSpan = /<span[^>]*>(.*?)<\/span>/g
const title = this.$refs.imageTitle.innerHTML.replace(regSpan, (match, innerContent) => innerContent)

6、匹配所有 class 为 className 的 span 元素

const regSpan = /<span[^>]*class\s*=\s*["'](?:\s*|.*\s)?className(?:\s*|.*\s)?["'][^>]*>(.*?)<\/span>/g

7、匹配所有块级元素并替换为换行符号 \n

function matchBlockEleToWrap(htmlString, replaceStr) {
  const blockElementRegex = /<(div|p|h[1-6]|ul|ol|li|table|thead|tbody|tfoot|tr|td|th|blockquote|pre|figure|figcaption|address|fieldset|legend|section|article|aside|nav|header|footer|main|figure|figcaption|canvas|audio|video|details|summary|menu|menuitem|colgroup|caption|datalist|optgroup|option|form|label|textarea|input|button|select|progress|meter|output)\b[^>]*>([\s\S]*?)<\/\1>/gi
  const regBr = /<br\s*\/?>/g
  while (blockElementRegex.test(htmlString)) {
    htmlString = htmlString.replace(blockElementRegex, (match, tag, content) => {
      const val = content.trim().replace(regBr, '')
      return replaceStr + val
  return htmlString

8、匹配所有空格转换为 &nbsp;,并且 a 标签中空格不变

export function switchSp(val) {
  const regA = /<a[^>]*>|<\/a>/gi
  const regSp = / /g
  return val.replace(regSp, '&nbsp;').replace(regA, (match) => match.replace('&nbsp;', ' '))

9、 String.prototype.replace()

10、粘贴为纯文本

// 监听编辑框的 paste 事件
handlepaste(e) {
  // 阻止默认粘贴事件
  e.preventDefault()
  // 获取粘贴的文本
  const text = e.clipboardData.getData('text/plain')
  // 将纯文本插入到可编辑的div中
  document.execCommand('insertText', false, text)

由于 document.execCommand 方法已弃用,可使用 Selection API 来实现

const editableDiv = document.getElementById('editDiv');
editableDiv.addEventListener('paste', (event) => {
  // 阻止默认粘贴行为
  event.preventDefault();
  // 获取剪贴板中的纯文本数据
  const text = (event.clipboardData || window.clipboardData).getData('text/plain');
  // 使用Selection API将纯文本插入到可编辑div的当前光标位置
  const selection = document.getSelection();
  if (selection.rangeCount) {
    const range = selection.getRangeAt(0);
    range.deleteContents();
    const textNode = document.createTextNode(text);
    range.insertNode(textNode);
    range.setStartAfter(textNode);
    selection.removeAllRanges();
    selection.addRange(range);

11、向 input 框插入表情

insertEmoji(emoji) {
  const inputElement = this.$refs['menuName'].$el.querySelector('input')
  const startPos = inputElement.selectionStart
  const endPos = inputElement.selectionEnd
  this.name = this.name.substring(0, startPos) + emoji + this.name.substring(endPos)
  // 更新光标位置
  this.$nextTick(() => {
    inputElement.focus()
    inputElement.selectionStart = startPos + emoji.length
    inputElement.selectionEnd = startPos + emoji.length

12、计算带有表情符号的字符串长度

由于表情符号是占两个长度(length)的,如果要算作一个长度,可用 for...of 来计算

const val = 'JFK大师傅14323  '
let len = 0
let name = ''
for (let i of val) {
  name += i
  len++
console.log(len) // 13

13、创建唯一性的字符串

function createUniqueString () {
  const timestamp = +new Date() + ''
  const randomNum = parseInt((1 + Math.random()) * 65536) + ''
  return (+(randomNum + timestamp)).toString(32)

20230620

1、windows 常用命令

(1)登陆服务器:ssh root@xxx.xxx.xxx

(2)退出登陆:ctrl+d


20230417

1、JavaScript 注释规范

(1)单行注释:使用双斜杠创建一个单行注释

// 注释内容

(2)多行注释

/** 方法说明
 * @method 方法名
 * @for 所属类名
 * @param {参数类型} 参数名 参数说明
 * @return {返回值类型} 返回值说明

(3)模块注释

/** 模块说明
 * @module 模块名

(4)类注释

/** 类说明
 * @class 类名
 * @constructor
 */

2、数组随机排序

const arraySort = <T>(arr: T[]): T[] => {
  const len = arr.length
  if (!Array.isArray(arr) || len <= 1) return arr
  for (let i = 0; i < len - 1; i++) {
    let randomIndex = Math.floor(Math.random() * (len - i)) + i
    const tem = arr[i]
    arr[i] = arr[randomIndex]
    arr[randomIndex] = tem
  return arr

3、数组拆分:将一个数组按固定长度拆分为多个数组

const arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
let idx = 0
let newArr = []
while (idx < arr.length) {
  newArr.push(arr.slice(idx, idx += 3))

20230224

1、日期格式化

// 对Date的扩展,将 Date 转化为指定格式的String
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
// 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
// 例子:
// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
// (new Date()).Format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18
Date.prototype.Format = function (fmt) {
  var o = {
    "M+": this.getMonth() + 1, //月份
    "d+": this.getDate(), //日
    "h+": this.getHours(), //小时
    "m+": this.getMinutes(), //分
    "s+": this.getSeconds(), //秒
    "q+": Math.floor((this.getMonth() + 3) / 3), //季度
    "S": this.getMilliseconds() //毫秒
  if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length))
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)))
  return fmt
// 调用: var time1 = new Date().Format("yyyy-MM-dd");var time2 = new Date().Format("yyyy-MM-dd hh:mm:ss");

2、js复制文字

火狐浏览器在非安全域时,会禁用 navigator.clipboard 对象,连 document.execCommand 也用不了(网上说能用,但下面方法还是不生效)。

function clipboardText(text) {
  return new Promise((resolve, reject) => {
    if (navigator.clipboard && window.isSecureContext) {
      navigator.clipboard.writeText(text).then(res => {
        resolve(true)
      }).catch(e => {
        reject(e)
    } else {
      const textarea = document.createElement('textarea')
      document.body.appendChild(textarea)
      // 隐藏此输入框
      textarea.style.position = 'fixed'
      textarea.style.clip = 'rect(0 0 0 0)'
      textarea.style.top = '10px'
      // 赋值
      textarea.value = text
      // 选中
      textarea.select()
      // 复制
      document.execCommand('copy', true)
      // 移除输入框
      document.body.removeChild(textarea)
      resolve(true)

20221129

1、生成指定长度的随机整数数组并排序

const arr = new Array(5).fill(1).map(item => item * parseInt(Math.random() * 100)).sort((a, b) => b - a)

2、获取数组最大/最小值

const min = Math.min(...arr.map(item => item.value))
const max = Math.max(...arr.map(item => item.value))

20220315

1、非空判断

// 非空判断,不是null 或 空字符串
export function notNullandEmpty(value) {
  return value !== null && trim(value) !== ''
// 非空判断,除0外的falsely
export function notEmpty(value) {
  return !!value || value === 0

20211229

1、格式化金额

/**
 * 格式化金额,如:9876.54 =》 9,876.54
 * @param sum
 * @returns Array:[0]=格式化的整数部分,[1]=小数部分
formatSum(sum) {
  let arr: Array < string > = []
  if (!sum && sum != 0) return arr
  const sumArr = (+sum).toString().split('.')
  const intFormat: string = sumArr[0].replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
  arr.push(intFormat)
  if (sumArr[1]) arr.push(sumArr[1])
  return arr

页面效果如下:

2、数字格式化: toLocaleString()

该属性可用于数字、金额、百分比等格式化,具体使用见 MDN。

const num = 11111.011187
console.log(num.toLocaleString('zh-CN', { style: 'currency', currency: 'CNY' }))
// ¥11,111.01

20211122

1、匹配手机号和固定电话,并替换

let phoneRep = /(((\+?86)|(\(\+86\)))?([1][3,4,5,7,8,9]\d{9}))/g; // 手机号匹配
let fixNum = /(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}/g; // 固定号码匹配
let replaceStr = '<span class="logistics-phone">$&</span>';
str = str.replace(phoneRep, replaceStr).replace(fixNum, replaceStr)
  • $$ 直接量符号(就是当做 '$$' 字符用)
  • $& 与正则相匹配的字符串
  • $` 匹配字符串左边的字符
  • $’匹配字符串右边的字符
  • $1,$2,$,3,…,$n 匹配结果中对应的分组匹配结果

2、处理物流信息

描述:后端查到的物流信息通常放在一个 list 中,需要根据信息内容来分类物流阶段状态:已签收、已代收、待取件、派送中、运输中、已揽件、已发货、已下单,list数据如下:

分析:根据 status 中的关键词,来判断处在哪个状态,在页面中加上相应的状态和对应的图标

const deliveryMsg = [
  { status: ['已签收'], class: 'logistics-sign', text: '已签收' },
  { status: ['代收'], class: 'logistics-sign', text: '已代收' },
  { status: ['待取件'], class: 'logistics-takeparts', text: '待取件' },
  { status: ['派送中', '派件中', '派件'], class: 'logistics-delivery', text: '派送中' },
  // { status: ['运输中', '已发出', '已收入', '已发往', '已经到达'], class: 'logistics-transport', text: '运输中', ref: 'transfer' },
  { status: ['已揽件', '已揽收'], class: 'logistics-solicitation', text: '已揽件' },
  { status: ['已发货'], class: 'logistics-degoods', text: '已发货' },
  { status: ['已下单'], class: 'logistics-place', text: '已下单' },
// 格式化运输信息
const getStatus = (status) => {
  let curStatus: any = {}
  deliveryMsg.forEach((item) => {
    item.status.forEach((text) => {
      if (status.indexOf(text) !== -1) {
        curStatus = item
  return curStatus

根据上面方法问题有,所有运输阶段的信息都会加上对应的状态及图标,而只需要最近一条添加即可,如

解决思路,运输中状态单独处理,循环 list,在运输中的信息中添加区分值:

let index = 0
res.list.forEach((list) => {
  let isTransfer = ['运输中', '已发出', '已收入', '已发往', '已经到达']
  isTransfer.forEach((tran) => {
    if (list.status.indexOf(tran) > -1) list.trans = index++

再根据 trans 字段来判断即可


20211111

1、Javascript 判断对象中是否有某属性

(1)使用点(.)或方括号([])取值,若为undefined,则为空。局限性是若属性值为undefined,无法判断

(2)使用 in 运算符,若属性在指定对象或原型链中,则返回 true。局限性是无法区分自身属性还是原型链上的属性。

(3)使用 hasOwnProperty(),存在并且为自身属性返回 true


20211109

1、如何让同步代码休眠多少秒后再执行,实现 sleep() 函数

const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))
const sleepLog = async () => {
	await sleep(2000)
	console.log(1)
	await sleep(2000)
	console.log(2)
	await sleep(2000)
	console.log(3)
sleepLog()

20211109前

1、根据 name 值获取表单中输入框的值,表单如下:

<form method='get' action='' target='_blank' name='qForm'>
  <input name='q' type='text' />
</form>
<script>
  var val = document.qForm.q.value
</script>

2、jquery 获取包括当前元素在内的 html :

$("#test").prop("outerHTML");

3、获取 url

/* https://test.com:8080/test/index.html#test?name=test */
var url;
url = window.location.href; /* 获取完整 URL */
url = window.location.pathname; /* 获取文件路径(文件地址)---> /test/index.html */
url = window.location.protocol; /* 获取协议 ---> https */
url = window.location.host; /* 获取主机地址和端口号 ---> test.com:8080 */
url = window.location.hostname; /* 获取主机地址 --> test.com */
url = window.location.port; /* 获取端口号 ---> 8080 */
url = window.location.hash; /* 获取锚点(“#”后面的分段)---> #test?name=test */
url = window.location.search; /* 获取属性(“?”后面的分段)---> name=test */

4、判断 a 链接是否是外链

  var domainName = window.location.hostname
  $(className).find('a').map(function () {
    var href = $(this).attr('href')
    if (href.indexOf('http') !== -1 && href.indexOf(domainName) == -1) {
      $(this).attr('target', '_blank')

5、图片在父元素里居中

$('.parentEle').find('img').each(function () {
  var parentH = $(this).parent().height()
  var parentW = $(this).parent().width()
  var parentR = parentW / parentH
  var imgH = $(this).height()
  var imgW = $(this).width()
  var imgR = imgW / imgH
  if (parentR > imgR) {
    if (imgH > parentH) {
      $(this).height(parentH)
      $(this).width(parentH * imgR)
    } else {
      $(this).css('margin-top', (parentH - imgH) / 2)
  } else {
    if (imgW > parentW)  {
      $(this).width(parentW)
      $(this).height(parentW / imgR)
      $(this).css('margin-top', (parentH - (parentW / imgR)) / 2)
    } else {
      $(this).css('margin-top', (parentH - imgH) / 2)

6、信息列表添加“...”

<style>
  .s3lm-lists {height: 216px;overflow: hidden;}
  .s3lm-item {position: relative;}
  .s3lm-item li {line-height: 36px;padding-left: 10px;background: url(icon_dotted.png) 0 16px no-repeat;}
  .s3lm-item li a {display: block;width: 100%;position: relative;}
  .s3lm-item li span {margin-left: 2em;}
  .s3lm-item li ins {width: 30px;height: 36px;background-color: #fff;position: absolute;right: 0;}
</style>
<div class="s3lm-lists">
  <ul class="s3lm-item">
    <li><a href="">这是多行信息超出固定高度后添加“...”的示例<span>2020-09-07</span></a></li>
    <li><a href="">这是多行信息超出固定高度后添加“...”的示例<span>2020-09-07</span></a></li>
    <li><a href="">这是多行信息超出固定高度后添加“...”的示例<span>2020-09-07</span></a></li>
    <li><a href="">这是多行信息超出固定高度后添加“...”的示例这是多行信息超出固定高度后添加“...”的示例这是多行信息超出固定高度后添加“...”的示例<span>2020-09-07</span></a></li>
    <li><a href="">这是多行信息超出固定高度后添加“...”的示例<span>2020-09-07</span></a></li>
    <li><a href="">这是多行信息超出固定高度后添加“...”的示例<span>2020-09-07</span></a></li>
</div>
<script>
   * 信息列表加“...”
   * @param {ele}  要处理ul的class名称
  function addEllipsis(ele, isBorder) {
    var curPart = $(ele).filter(function () {
      return $(this).is(':visible')  // 获取当前显示的列表
    curPart.each(function () {
      var fixedHeight = $(this).outerHeight(); // 获取列表外盒子的固定高度
      var liOriginH = 0;
      var liLineHeight = parseInt($(this).find("li").eq(0).css("line-height")); // 获取行高
      $(this).find('li').each(function() {
        var liHeight = 0
        if (isBorder) {
          liHeight = Math.floor($(this).outerHeight() / liLineHeight) * liLineHeight
          $(this).outerHeight(liHeight)
        } else {
          liHeight = $(this).outerHeight(); // 获取每个li的高度        
        liOriginH += liHeight;  // 获取当前li的总高度
        if (liOriginH >= fixedHeight) {
          if (liOriginH > fixedHeight) { // li的高度超过外盒子固定高度,给超过高度的li加上'...'
            if ($(this).has('ins').length === 0) { // 避免重复添加
              $(this).append('<ins>...</ins>');
            var hideH = liOriginH - fixedHeight  // 获取超出部分的高度
            var t = $(this).outerHeight() - hideH - liLineHeight; // 获取'...'的定位高度
            $(this).find('ins').css('top', t)
            // $(this).find('span').css('bottom', hideH) // 给时间设置定位
          $(this).hover(function() {  // 鼠标滑过显示超出部分内容
            $(this).find('ins').hide(300)
            $(this).parent('ul').stop().animate({ 'top': -hideH }, 300)
            // $(this).find('span').stop().animate({ 'bottom': 0 }, 300)
          }, function() {
            $(this).find('ins').show(300)
            $(this).parent('ul').stop().animate({ 'top': 0 }, 300)
            // $(this).find('span').stop().animate({ 'bottom': hideH }, 300)
          return false;
</script>

7、解决父元素设置 ; 时,子元素 iframe 中 js 获取不到具体元素值的问题

场景:一个下拉列表设置隐藏,鼠标滑过其父元素时显示,下拉列表是用 iframe 嵌入的,iframe 中有 js 动态修改元素的 width

问题:设置 ; 时,子元素中 js 获取不到具体的 width 值

解决思路:

  • js 方法,在鼠标滑过时刷新 iframe,网上的方法有:
    • 用 iframe 的 name 属性定位
      • document.frames('ifrmname').location.reload() ---》报错
      • document.all.ifrmname.document.location.reload() --》报错
    • 用 iframe 的 id 属性定位
      • ifrmid.window.location.reload() ---》跨域(挺奇怪的,页面都在本地,还会出现跨域,希望有大神能解答下,谢谢)
    • 当 iframe 的 src 为其它网站地址(跨域操作时)
      • window.open(document.all.ifrmname.src,'ifrmname','') ---》可行
    • js 刷新
      • document.getElementById('some_frame_id').contentWindow.location.reload(); ---》跨域
      • document.getElementById('gh_dorpdown_iframe').src = document.getElementById('gh_dorpdown_iframe').name ---》建议name放链接,就不会出现页面闪动的情况
    • jq 刷新
      • $('#iframe').attr('src', $('#iframe').attr('name')); ---》议 name 放链接,就不会出现页面闪动的情况,和 js 第二种方式类似,主要的通过改变 src 来重新加载,问题是有时会出现 iframe 没加载出来的情况,页面空白,没找到原因,希望有大神能解答下,谢谢

按需求来说,只需要鼠标滑过下拉显示,离开下拉隐藏,所以可以不用考虑 iframe 刷新,只需考虑元素隐藏显示即可

元素隐藏的方法(除开 ):

  • /visible
    • 浏览器对其渲染不可见,占据空间却不可点击,能继承,但子元素可设置visible来显示;transition 对hidden -> visible 无效,对 visible -> hidden 有效;设置 position:absolute/fixed 或 float:left/right,可不占空间,原理是元素脱离了文档流
    • 不占据空间,不可点击,该元素及其后代一概不渲染,transition 不起作用
  • opacity:0;
    • 占据空间,可点击,能继承,但子元素可设置 opacity:1 或 rgba(x,x,x,1) 来显示,transition 起作用
    • 不兼容 ie8
  • position/float,将元素移到可视窗口外即可
  • overfloat:hidden/visible
    • 通过改变 width/height 实现
  • transform:scale(0)
    • 元素缩放无限小,元素所在的位置将保留
  • <div hidden="hidden"></div>
    • H5属性,效果和 ; 相同
  • filter:blur(0)
    • Css3 属性,将元素的模糊度设置为0
  • clip-path: polygon(0px 0px, 0px 0px, 0px 0px, 0px 0px);
    • 兼容性不是很好,具体看 MDN

8、标签栏切换

/**
* 栏目导航切换
* @param item // 鼠标滑过的项
* @param active // 当前的项
* @param list // 要显示的项
function switchNav(item, active, more, list) {
	$(item).mouseover(function() {
		if (!$(this).hasClass('on')) {
			$(this).addClass(active).siblings(item).removeClass(active);
		} else {
			$(this).siblings(item).removeClass(active)
		var index = $(this).index(item);
		$(more).eq(index).removeClass("hide").siblings(more).addClass("hide");
		$(list).eq(index).removeClass("hide").siblings(list).addClass("hide");

9、头部高亮、当前栏目高亮、当前位置去掉 table

// 头部高亮
$(document).ready(function () {
	if ($('.current-position').find('a').length > 0) {
		var currentCol = $.trim($('.current-position').find('a')[1].text)
		var isHome = false
		$('.nav .auto').find('a').map(function () {
			$(this).removeClass('bc')
			if ($.trim($(this)[0].text) === currentCol) {
				isHome = true
				$(this).addClass(' bc')
		if (!isHome) {
			$('.nav .auto').find('a').eq(0).addClass(' bc')
// 当前栏目高亮
$(document).ready(function () {
    var currentCol = $.trim($('meta[name="ColumnName"]').attr('content'))
    $('.column-col').find('li').map(function () {
        if ($.trim($(this).find('a').eq(0)[0].text) === currentCol) {
            $(this).addClass(' active').siblings('li').removeClass('avtive')
// 当前位置去掉table
$(document).ready(function() {
  var currentA = ''
  $('.current-position .w1200').find('a').map(function(index) {
    if (index > 0) {
      currentA += ' > ' + $(this)[0].outerHTML
    } else {
      currentA += $(this)[0].outerHTML
  $('.current-position .w1200').html(currentA)

10、js 动态引入 script 标签

function loadScript(url, callback) {
  var script = document.createElement('script');
  var head = document.getElementsByTagName('head')[0];
  script.type = 'text/javascript';
  script.charset = 'UTF-8';
  script.src = url;
  if (script.addEventListener) {
    script.addEventListener('load', function() {
      callback();
    }, false);
  } else if (script.attachEvent) {
    script.attachEvent('onreadystatechange', function() {
      var target = window.event.srcElement;
      if (target.readyState == 'loaded') {
        callback();
  head.appendChild(script);
loadScript('xxx.js', function() {
  console.log('加载完成')

11、$.ajax 在 ie8、ie9 下失效的问题:

  • IE 浏览器设置:“工具->Internet 选项->安全->自定义级别”->“其他”->“通过域访问数据源”->“启用”
  • 设置了浏览器的安全设置后,axios、angular 的 $http 以及原生 XMLHttpRequest 请求(原生可请求成功)都可以成功请求,jq 的话还是需要设置 jQuery.support.cors = true; 才可以请求( jq 未验证)

12、将类数组转化为数组

  • slice:原始方法
let arr = Array.prototype.slice.call(arguments)
// 等同于
let arr1 = [].slice.call(arguments)
  • from:ES6 方法
let arr = Array.from(arguments)
  • ...(扩展运算符):ES6 方法
let arr = [...arguments]
  • makeArray:jquery 方法
let arr = $.makeArray(arguments)

13、swiper 2.x 版本基本使用

<!-- 引入css、js文件 -->
<link rel="stylesheet" href="images/swiper.2.x.css">
<script type="text/javascript" src="./images/swiper.2.x.min.js"></script>
<div class="swiper-container">
  <div class="swiper-wrapper">
    <div class="swiper-slide">slider1</div>
    <div class="swiper-slide">slider2</div>
    <div class="swiper-slide">slider3</div>
  </div>
  <div class="pagination"></div>
</div>
<script type="text/javascript">
$(document).ready(function() {
  var mySwiper = new Swiper('.swiper-container',{
    loop: true, // 无限循环切换
    autoplay : 3000, // 自动切换
    speed:1000, // 滑动速度
    autoplayDisableOnInteraction : false, // 如果设置为false,用户操作swiper之后自动切换不会停止,每次都会重新启动autoplay
    pagination : '.pagination', // 分页器
    paginationClickable :true, // 分页器可点击
  // 鼠标悬停停止切换、移除开始切换
  $('.swiper-container').mouseenter(function() {
    mySwiper.stopAutoplay();
  }).mouseleave(function() {
    mySwiper.startAutoplay()
  // 分页器添加页码
  $('.pagination').find('.swiper-pagination-switch').map(function(index,item) {
    $(this).text(index + 1)
</script>