实战踩坑

js

audioPlay(event) {

返回目录

1. js 页面音频播放

  audioPlay(event) {
      // console.log('音乐播放', event)
      var audios = document.getElementsByTagName('audio')
      // 暂停函数
      function pauseAll() {
        var self = this;
        [].forEach.call(audios, function(i) {
          // 将audios中其他的audio全部暂停
          i !== self && i.pause()
        })
      }
      // **给play事件绑定暂停函数**
      [].forEach.call(audios, function(i) {
        i.addEventListener('play', pauseAll.bind(i))
      })
    }
  videoPlay(event) {
      // console.log('视频播放', event)
      var videos = document.getElementsByTagName('video')
      // 暂停函数
      function pauseAll() {
        var self = this
        ;[].forEach.call(videos, function(i) {
          // 将audios中其他的audio全部暂停
          i !== self && i.pause()
        })
      }
      // 给play事件绑定暂停函数
      [].forEach.call(videos, function(i) {
        i.addEventListener('play', pauseAll.bind(i))
      })
    }

2. js 图片转 base64,base64 转文件

//将图片转换为Base64

function getImgToBase64(url, callback) {
  var canvas = document.createElement("canvas"),
    ctx = canvas.getContext("2d"),
    img = new Image();
  img.crossOrigin = "Anonymous";
  img.onload = function () {
    canvas.height = img.height;
    canvas.width = img.width;
    ctx.drawImage(img, 0, 0);
    var dataURL = canvas.toDataURL("image/png");
    callback(dataURL);
    canvas = null;
  };
  img.src = url;
}

//将base64转换为文件

function dataURLtoFile(dataurl, filename) {
  var arr = dataurl.split(","),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, { type: mime });
}

//可以将图片转换为base64

getImgToBase64("img/test.png", function (data) {
  var myFile = dataURLtoFile(data, "testimgtestimgtestimg");
  console.log(myFile);
});

3. js 文本框监听粘贴事件,获取粘贴板上的图片数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="text" id="myInput" />
<script>
    document.getElementById('myInput').addEventListener('paste',function(e){
        if ( !(e.clipboardData && e.clipboardData.items) ) {
            return;
        }
        for (var i = 0, len = e.clipboardData.items.length; i < len; i++) {
            var item = e.clipboardData.items[i];

            if (item.kind === "string") {
                item.getAsString(function (str) {
                    console.log(str);
                })
            } else if (item.kind === "file") {
                var f= item.getAsFile();
                console.log(f);
            }
        }
    });
</script>
</body>
</html>

4. js reduce() 拆分数组

const arr = [
  { id: 1, name: 1, pinyin: "A" },
  { id: 2, name: 2, pinyin: "B" },
  { id: 3, name: 3, pinyin: "B" },
  { id: 4, name: 4, pinyin: "C" },
  { id: 5, name: 5, pinyin: "C" },
  { id: 6, name: 6, pinyin: "C" },
  { id: 7, name: 7, pinyin: "D" },
  { id: 8, name: 8, pinyin: "D" },
  { id: 9, name: 9, pinyin: "D" },
];
  1. 获取索引值
// 动态获取索引列表
  getIndexList(arr) {
    // 1. 排序
    var mySort = arr.sort()
    // var mySort = arr.sort(this.sortBy('pinyin', true))
    // 2. 过滤
    mySort = mySort.map((item, index) => {
      return item.pinyin
    })
    console.log('mySort',mySort)  // ['A','B',‘B’,'C','C','C','D','D','D']
    // 3. 去重
    const mySet = Array.from(new Set(mySort))
    return mySet    // ['A','B','C','D']
  1. 按索引拆分数组
  getCellList(arr) {
    // 1. 排序
   arr = arr.sort()
   const result = arr.reduce(function(initArray, item) {
   const p = item.pinyin
      if (initArray[p]) {
          initArray[p].push(item)
         } else {
         initArray[p] = [item]
      }
      return initArray
      }, [])
      // // console.log('getCellList', result)
      return result
    },
  1. 根据对象的 key 提取 value 拼成新数组
const temp = this.getCellList(arr);
this.friendList = Object.keys(temp).map((item) => temp[item]);
  1. reduce 语法
arr.reduce(function(prev,cur,index,arr){
...
}, init);

arr 表示原数组;
prev 表示上一次调用回调时的返回值,或者初始值 init;
cur 表示当前正在处理的数组元素;
index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为 0,否则索引为 1;
init 表示初始值。

原理
① 初始化一个空数组
② 将需要去重处理的数组中的第 1 项在初始化数组中查找,如果找不到(空数组中肯定找不到),就将该项添加到初始化数组中
③ 将需要去重处理的数组中的第 2 项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中
④ ……
⑤ 将需要去重处理的数组中的第 n 项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中
⑥ 将这个初始化数组返回

5. js 获取输入框输入前后的值

使用场景:比较输入框前后的值是否相等,判断是否需要执行对应的方法

  • @focus 方法把点击输入框时的初始值保存下来
  • @change 方法把输入后的 value 值传出
  • 在 element UI 中 @change 是 blur 或点击回车才执行的,可以用 @blur替换

上代码

<el-input
  v-model.trim="remark"
  placeholder="请输入备注"
  @focus="setDefault(remark)"
  @change="changeRemark($event,id)"
/>

6. js 一次性渲染大量数据解决方案


   refresh(total, onceCount, arrval) {
      console.log('总数,每次渲染条数', total, onceCount)
      // total -> 渲染数据总数 onceCount -> 一次渲染条数
      let count = 0 // 初始渲染次数值
      const loopCount = total / onceCount // 渲染次数
//------------<
      const that = this
      let once = []
      let cell = []
      let show = []
//------------>
      function refreshAnimation() {
        /*
         * 在此处渲染数据
         */
//------------<
        once = arrval.slice(count * onceCount, (count + 1) * onceCount)
        // (count * onceCount, onceCount)
        // console.log(`渲染${count}`, once)
        cell = that.getCellList(once)
        show = Object.keys(cell).map(item => cell[item])
        // console.log(`渲染${count}`, show)
        show.forEach(e => {
          that.friendList.push(e)
        })
        // that.friendList = that.friendList.concat(show)
        // console.log(`friends${count}`, that.friendList)
//------------>
        if (count < loopCount) {
          count++
          window.requestAnimationFrame(refreshAnimation)
        }
      }
      window.requestAnimationFrame(refreshAnimation)
    },
//调用
    refresh(arr.length,5,arr)

7. js 获取图片宽高等信息

    // 获取图片宽高
    getImgInfo(url) {
      return new Promise((resolve, reject) => {
        const img = new Image()
        img.src = url
        img.onload = function() {
          const imgInfo = {
            width: img.width,
            height: img.height
          }
          resolve(imgInfo)
        }
        img.onerror = function() {
          reject(new Error('图片加载错误!'))
        }
      })
    },

8. js 获取视频宽高,时长等信息

    // 获取视频的信息
    getVideoInfo(url) {
      return new Promise((resolve, reject) => {
        const video = document.createElement('video')
        video.src = url
        video.onloadedmetadata = function(e) {
          const videoInfo = {
            width: video.videoWidth,
            height: video.videoHeight,
            duration: video.duration
          }
          resolve(videoInfo)
        }
        video.onerror = function() {
          reject(new Error('图片加载错误!'))
        }
      })
    },

9. js 点击播放一个文件关闭其他资源

// play_source : 给需要控制的文件的类名,音频视频都用这个
    // 只播放一个音频或视频
    playOne() {
      var source = document.getElementsByClassName('play_source')
      // console.log(source) // 获取所有要控制的音频视频元素
      // 暂停函数
      function pauseAll() {
        var self = this
        ;[].forEach.call(source, function(i) {
          // 将source中其他的source全部暂停
          i !== self && i.pause()
        })
      }
      // **给play事件绑定暂停函数**
      [].forEach.call(source, function(i) {
        i.addEventListener('play', pauseAll.bind(i))
      })
    }

10. js 常用正则匹配

// g-global 全局搜索 i- 忽略大小写搜索 m-多行搜索

// 手机号
// 匹配所有号码(手机卡 + 数据卡 + 上网卡)
const phoneReg=/^(?:\+?86)?1(?:3\d{3}|5[^4\D]\d{2}|8\d{3}|7(?:[01356789]\d{2}|4(?:0\d|1[0-2]|9\d))|9[189]\d{2}|6[567]\d{2}|4(?:[14]0\d{3}|[68]\d{4}|[579]\d{2}))\d{6}$/

// 手机号-普通版
var reg = /^(0|86|17951)?(13[0-9]|15[012356789]|18[0-9]|14[57]|17[678])[0-9]{8}$/

// 手机号-简单版
var reg = /^1[34578]\d{9}$/

// qq号
const qqReg=/^[1-9][0-9]{4,9}$/gim

// 身份证
const IdReg = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/;

// 邮箱
const emailReg=/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/
var reg = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;

// URL
const urlReg = /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i;

// IP
const ipReg = /^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/gi;

// 邮政编码
const reg = /^[1-9]\d{5}$/g;

// 检查字符串是否存在中文
const reg = /[\u4e00-\u9fa5]/gm;

// 去除空格
trim(str) {
    var reg = /^\s+|\s+$/g;
    return str.replace(reg, '');
    },

// 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线)
const reg=/^[a-zA-Z]\w{5,17}$/

// 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间)
const reg=/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$/

11. vue.js 输入框限制特殊符号

// 全局声明
Vue.prototype.validForbid = function (value) {
  // 限制input不能输入特殊符号
  value = value
    .replace(
      /[`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g,
      ""
    )
    .replace(/\s/g, "");
  return value;
};
// 页面使用 @input="e => uploadWord.title = validForbid(e)"
<el-input
  v-model="uploadWord.title"
  maxlength="10"
  show-word-limit
  @input="e => uploadWord.title = validForbid(e)"
/>

12. qrcode.js 识别图片二维码

场景: 上传图片前识别图片是否二维码

  1. npm install --save qrcode-decoder 引入
// npm install --save qrcode-decoder

import QrcodeDecoder from 'qrcode-decoder'

    async decodeImg(file) {
      // file是通过input或elementUI组件中的upload 上传的二维码图片文件
      // 获取预览图片路径方法
      var getObjectURL = function(file) {
        var url = null
        if (window.createObjectURL !== undefined) { // basic
          url = window.createObjectURL(file)
        } else if (window.URL !== undefined) { // mozilla(firefox)
          url = window.URL.createObjectURL(file)
        } else if (window.webkitURL !== undefined) { // webkit or chrome
          url = window.webkitURL.createObjectURL(file)
        }
        return url
      }
      console.log(getObjectURL(file)) // 查看是否成功获取图片路径

      var QRCode = new QrcodeDecoder()
      const img = await getObjectURL(file)
      const isQrcode = await QRCode.decodeFromImage(img).then((res) => {
        console.log(' QRCode.decodeFromImage', res.data)
        return !!res.data
      })
      // 这里仅返回ture和false用于判断, 没有返回解析二维码得到的文本
      return isQrcode
    },

13. vue.js 引入第三方 js

methods: {
loadVaptchaScript() {
      return new Promise(resolve => {
        var script = document.createElement('script')
        script.src = '@/utils.qrcode.js'
        script.async = true
        script.onload = script.onreadystatechange = function() {
          if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
            resolve()
            script.onload = script.onreadystatechange = null
          }
        }
        document.getElementsByTagName('head')[0].appendChild(script)
      })
    },
}
//获取预览图片路径
var getObjectURL = function(file){
  var url = null ;
  if (window.createObjectURL!=undefined) { // basic
  url = window.createObjectURL(file) ;
  } else if (window.URL!=undefined) { // mozilla(firefox)
  url = window.URL.createObjectURL(file) ;
   } else if (window.webkitURL!=undefined) { // webkit or chrome
   url = window.webkitURL.createObjectURL(file) ;
  }
   return url ;
}
console.log(getObjectURL(newfile[0]));// newfile[0]是通过input file上传的二维码图片文件
qrcode.decode(getObjectURL(newfile[0]));
qrcode.callback = function(imgMsg){
    console.log("imgMsg",imgMsg);
}

14. js 获取今天 0 点和 23 点 59 分 59 秒

// 0点
new Date(new Date(new Date().toLocaleDateString()).getTime());
// 23:59:59
new Date(
  new Date(new Date().toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1
);

15. 使用 async/await 替代 promise

// 声明一个方法, 延迟打印输入的时间
function asyncfunc(time) {
  return new Promise((reslove, reject) => {
    setTimeout(() => {
      console.log("setTimeout", time);
      reslove(time);
    }, time);
  });
}

// 1. 使用 promise链式调用执行
asyncfunc(3000).then((time) => {
  console.log("done", time); // 3000
})(
  // 结果 3秒后输出
  // setTimeout 3000
  // done 3000

  // 2. 使用 async/await执行
  async () => {
    const time = await asyncfunc(5000);
    console.log("done", time);
  }
)();
// 结果 5秒后输出
// setTimeout 5000
// done 5000

// async function 调用后返回的 Promise 本身是立即执行的,所以如果你不想管后面发生了什么,也可以直接这样调用。
// Promise.all / Promise.race

const temp = [1000, 2000, 3000, 4000];
(async () => {
  const result = await Promise.all(
    temp.map((time) => {
      return asyncfunc(time);
    })
  );
  console.log("done", result);
})();
// Promise {<pending>}
// init.js:1 setTimeout 1000
// init.js:1 setTimeout 2000
// init.js:1 setTimeout 3000
// init.js:1 setTimeout 4000
// init.js:1 done (4) [1000, 2000, 3000, 4000]
  • 异常处理
// 上面说到,async function 实际上就是 Promise,而 Promise 并不能通过 try-catch 来捕获异常(事实上我们没有办法捕获异步回调中的的异常), 是通过 reject 调用相应的回调的。而 await 实际上会在被 reject 时 throw 相应的异常:

(async () => {
  try {
    await Promise.reject("aha");
  } catch (e) {
    console.log(e);
  }
})();

// 会得到 aha。

// 相应的,在 async function 中 throw 也会导致其返回的 Promise reject:

(async () => {
  throw "aha";
})().catch((err) => {
  console.log(err); // aha
});
参考链接: https://zhuanlan.zhihu.com/p/23249103?utm_medium=social&utm_source=weibo

16. js 复制一个数组

//拷贝一个数组(相当于复制并创建一个新的数组,对新数组进行操作bu影响原来的数组)
// 方法一
var arr = [1, 2, 3, 4];
var arr1 = arr.concat();

// 方法二
var arr = [1, 2, 3, 4, 5];
var arr1 = arr.slice(0);

//方法三(ES6中的Rest运算符)
var arr = [1, 2, 3, 4];
var arr1 = [...arr];

//方法四
var arr = [1, 2, 3, 4];
arr1 = Array.from(arr);

//方法五
var arr1 = [],
  arr = [1, 2, 3, 4],
  len = arr.length;
for (var i = 0; i < len; i++) {
  arr1.push(arr[i]);
}
console.log(arr1);

//方法六
var arr = [1, 2, 3, 4];
var arr1 = Object.assign([], arr);

//方法七(for..of..循环)
var arr = [1, 2, 3, 4];
var arr1 = [];
for (var val of arr) {
  arr1.push(val);
}

//方法八(for..of..+arr.entries()方法)
var arr = [1, 2, 3, 4];
var arr1 = [];
for (var item of arr.entries()) {
  arr1[item[0]] = item[1];
}

17. js 区分统计中英文长度

validateTextLength(value) {
      //中文、中文标点、全角字符按1长度,英文、英文符号、数字按0.5长度计算
      let cnReg = /([\u4e00-\u9fa5]|[\u3000-\u303F]|[\uFF00-\uFF60])/g;
      let mat = value.match(cnReg);
      let length = 0;
      if (mat) {
        return (length = mat.length + (value.length - mat.length) * 0.5);
      } else {
        return (length = value.length * 0.5);
      }
    }

18. js 上传文件进度条

axios({
  url,
  method: "post",
  data,
  headers: {},
  //原生获取上传进度的事件
  onUploadProgress: function (progressEvent) {
    let complete =
      (((progressEvent.loaded / progressEvent.total) * 100) | 0) + "%";
    console.log("上传 " + complete);
  },
})
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  });

19. js 进制转换

  // 10转16并补一个0
  ten2hex(num) {
    var result = num.toString(16).toUpperCase()
    if (result.length < 2) {
      result = '0' + result
    }
    return result
  },
  // 16转10
  hex2ten(hex) {
  var ten = parseInt(hex,16);
  return ten
 }
  // string转16
  str2hex(str) {
    var val = "";
    for (var i = 0; i < str.length; i++) {
      if (val == "")
        val = str.charCodeAt(i).toString(16);
      else
        val += str.charCodeAt(i).toString(16);
    }
    return val
  },
  // 16转string
  hex2str(hexCharCodeStr) {  
    var trimedStr = hexCharCodeStr.trim();  
    var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x"?trimedStr.substr(2):trimedStr;  
    var len = rawStr.length;  
    if (len % 2 !== 0) {    
      // alert("Illegal Format ASCII Code!");    
      return "";  
    }  
    var curCharCode;  
    var resultStr = [];  
    for (var i = 0; i < len; i = i + 2) {    
      curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value    
      resultStr.push(String.fromCharCode(curCharCode));  
    }  
    return resultStr.join("");
  },
  // 16转buffer
  hex2ab(hex) {
    const buffer = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(h => {
      return parseInt(h, 16)
    }))
    return buffer.buffer
  },
  // buffer转16
  ab2hex(buffer) {
    var hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function(bit) {
        return ('00' + bit.toString(16)).slice(-2)
      }
    )
    return hexArr.join('');
  },

20. js crc8检验

  // crc8校验
  encodeCrc8(hex) {
    var _crc8 = [

      0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,

      0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,

      0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e,

      0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc,

      0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0,

      0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62,

      0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d,

      0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff,

      0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5,

      0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07,

      0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58,

      0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a,

      0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6,

      0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24,

      0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b,

      0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9,

      0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f,

      0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,

      0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92,

      0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50,

      0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c,

      0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee,

      0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1,

      0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73,

      0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49,

      0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b,

      0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4,

      0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16,

      0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a,

      0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,

      0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7,

      0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35

    ];

    var typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function(h) {

      return parseInt(h, 16)

    }))

      
    var ucLen = typedArray.length;
    var ucPtr = typedArray;
    var ucCRC8 = 0;
    var i = 0;
    while (ucLen--) {
      ucCRC8 = _crc8[ucCRC8 ^ ucPtr[i]];
      i++;
    }
    return ucCRC8.toString(16).toUpperCase();
  },

21. js 点击输入框自动全选内容

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input id="input" value="" />
  </body>

  <script>
    var input = document.getElementById("input");
    input.addEventListener("focus", function (e) {
      input.select();
    });
  </script>
</html>

22. vue.js 解决打包更新版本,浏览器缓存问题

每次打包更新版本发到服务器上,导致偶尔会出现不能及时更新最新代码,浏览器存在缓存的问题。总不能让每个用户都强制刷新一下或者打开一个无痕窗口吧

vue.config.js(vue cli3.x 生成的项目默认没有这个文件,需要自己创建)

// 时间戳保证不会版本重复
const Timestamp = new Date().getTime();
module.exports = {
  ....
  configureWebpack: { // webpack 配置
    output: { // 输出重构  打包编译后的 文件名称  【模块名称.版本号.时间戳】
      filename: `[name].${process.env.VUE_APP_Version}.${Timestamp}.js`,
      chunkFilename: `[name].${process.env.VUE_APP_Version}.${Timestamp}.js`
    },
  }
  ...
};

nginx 配置,让 index.html 不缓存。

location = / index.html {
    add_header Cache-Control "no-cache, no-store";
}
  • no-cache, no-store 可以只设置一个
  • no-cache 浏览器会缓存,但刷新页面或者重新打开时 会请求服务器,服务器可以响应 304,如果文件有改动就会响应 200
  • no-store 浏览器不缓存,刷新页面需要重新下载页面

23. vue.js 实现判断页面是否编辑及编辑页面未保存离开弹窗提示

<script>
export default {
    name: 'Form',
    props: [],
    beforeRouteLeave (to, from, next) {//离开当前页
      if(this.updateCount > 1){ //更新次数大于1 说明用户修改过当前页数据 因为获取详情时会更新一次
        if(from.path.includes('nowPath')){
          this.$confirm('即将离开当前页,请确定是否保存当前数据?', '离开当前页', {
            confirmButtonText: '保存',
            cancelButtonText: '不保存',
            type: 'warning'
          }).then(() => {
            //...todo 这里调接口 保存数据
            next()
          }).catch(() => {next()});
        }else{next()}
      }else{
        next()
      }
    },
    data() {
      return {
        updateCount:0,//判断用户是否更新当前数据
        form:{
          radio:'',
          select:[]
          input:''
        }
      }
    },
    computed:{},
    // 用watch或者用updated都可以,根据实际情况选择
    watch:{
      form: {
        handler (val) {
          if (val) {
            this.updateCount++
          }
        },
        deep: true
      }
    },
    updated:function () {
      this.updateCount = this.updateCount + 1
    },
    mounted:function () {
    this.getInitData()
  },
    methods: {
    getInitData:function(){
    //...todo  页面进来,先获取默认数据

    }

  },
  }
</script>

24.