前端常用功能笔记

1.字符串.replace(正则, function(v,i,str){ return 'xxx' })        //xxx为替换掉匹配到的内容

//v为匹配到的值,i是下标,str是'myTestJob'这个字符串
'myTestJob'.replace(/[A-Z]/g, (v,i,str) => `_${v.toLowerCase()}`)        

输出结果为 'my_test_job'

2.如何用异步post请求 文件流数据,并触发浏览器的下载功能

    //以下例子是在vue中的写法

    downloadFile(url, params, fileName) {        //下载文件
      this.$http.post(url, params, {'responseType': 'blob'}).then(res => {
        const blob = new Blob([res.data], {type: res.headers['content-type']});
        const a = document.createElement('a');
        if ('download' in a) {                    // 非IE下载
          a.style.display = 'none';
          a.download = fileName;
          a.href = URL.createObjectURL(blob);
          document.body.appendChild(a);
          a.click();
          URL.revokeObjectURL(a.href);            //不释放的话会一直占用资源
          document.body.removeChild(a);
        }else{                                    // IE10+下载
          navigator.msSaveBlob(blob, fileName);
        }
      })
    }

注意:html5中a标签新增了download属性,用于重命名下载文件,不指定则使用默认文件名;
但当a标签用于下载文件流的时候,必须指定download,否则无法触发浏览器的下载模块。

3.canvas内容实现水平翻转(垂直翻转同理)

    1) 先ctx.scale(width缩放倍数,height缩放倍数)进行水平翻转
        ctx.scale(-1, 1)

    2) 再ctx.translate(x坐标移动距离, y坐标移动距离)把翻转后的结果移回画布
        ctx.translate(100, 0)    //假设画布宽为100px

4.前端计算文件md5最快最准的插件使用(其他插件在计算大文件会算错)

//该插件是在js-spark-md5插件的基础上进行封装的
import BMF from 'browser-md5-file';
     
const el = document.getElementById('upload');
const bmf = new BMF();
     
el.addEventListener('change', handle, false);
     
function handle(e) {
    const file = e.target.files[0];
    bmf.md5(file, (err, md5) => {
        console.log('md5 string:', md5);
    }, progress => { // 计算的进度值
        console.log('progress number:', progress);
        bmf.abort(); // 中止md5计算
    });
}

5.--save-dev 和 --save的区别

    --save会写入package.json的dependencies下;    //指定 生产环境 下需要安装的依赖
    当npm install --production 或 当NODE_ENV变量值 为production时,会将dependencies的依赖下载到node_modules中

    --save-dev会写入package.json的devDependencies下;    //指定 非生产环境 下需要安装的依赖
    当npm install 或 当NODE_ENV变量值 不为production时,会将devDependencies的依赖下载到node_modules中

6.替代eval的方法

function myEvil(str) {    //str指表达式字符串
    var Fn = Function;  //一个变量指向Function,防止有些前端编译工具报错
    return new Fn('return ' + str)();
}

注意:str中如果涉及外部变量,会变成undefined

7.字符串插入值,比如千分位

'12312312'.replace(/\d(?=(\d{3})+$)/g, "$&,")  // 输出结果为"12,312,312"    

/\d(?=(\d{3})+$)/g 表示 匹配一组数字,且该组数字后面至少连着一组3位数,直到结尾
// ?= 表示限定后面的字符
// $& 表示匹配到的部分

// 千分位 另一种写法(要求 数据源 必须是 数字)
(123456789).toLocaleString() // 输出结果为"123,456,789"
// 完整写法(千分位取决于style,与前面的'en'无关)
(123456789).toLocaleString('en', { style: 'decimal' }) // 默认decimal

8.正则匹配括号:/[(]/

9.初始化数组的值

方法1:
new Array(num).fill(val, startIdx, endIdx); //含头不含尾

例子:
new Array(5).fill(10);          //结果为[10, 10, 10, 10, 10]
new Array(5).fill(10, 0, 2);    //结果为[10, 10, undefined, undefined, undefined]

方法2:
[...str.repeat(num)]; //str必须是字符串

例子:
[...'1'.repeat(5)];     //结果为['1', '1', '1', '1', '1']
[...'10'.repeat(2)];    //结果为['1', '0', '1', '0']

注意:扩展运算符 打散字符串时,是以 1个字符为单位 进行打散的

10.将某个html内容块转为图片 - 插件 html2canvas

    <div id="result">1234</div>
    <div id="resultImg"></div>

    html2canvas(document.getElementById('result')).then(function (canvas) {
      var newImg = new Image();
      newImg.width = window.innerWidth;
      newImg.height = window.innerHeight;
      //生成的jpeg图片为base64数据(比png小很多)
      newImg.src = canvas.toDataURL("image/jpeg"); 
      newImg.onload = function(){
        document.getElementById('resultImg').appendChild(newImg);
      }
    })

11.flex布局常用写法

    display: flex;

    /* flex-direction 决定主轴的方向 row(默认)|row-reverse|column|column-reverse*/
    /* flex-direction: row; */

    /* flex-wrap决定当排列不下时是否换行以及换行的方式,nowrap(默认)|wrap|wrap-reverse */
    /* flex-wrap:wrap; */

    /* flex-flow是lex-direction和flex-wrap的简写形式,如:row wrap|column wrap-reverse等。默认值为row nowrap,即横向排列 不换行 */
    flex-flow:row wrap;

    /* !当主轴沿水平方向时!justify-content,决定item在主轴上的对齐方式,可能的值有flex-start(默认),flex-end,center,space-between,space-around */
    justify-content:center;

    /* !主轴水平时!决定了item在交叉轴上的对齐方式,可能的值有flex-start|flex-end|center|baseline|stretch */
    align-items:center;

12.input上传文件反应很慢 问题解决

  问题描述:
      input标签上传文件,当选中文件后,会卡顿2-3秒才触发onchange事件(vue里会,原生的写法不会),同时上传的文件越多,卡顿越久,且无法监听到在选中文件之后触发loading

  解决办法:
      1) 在input标签上监听click事件,当点击"浏览"时弹出loading
    2) 在loading标签上监听mousemove事件,触发时隐藏loading,用于点击"取消"选择文件
    3) 在input标签上监听change事件,触发时隐藏loading

13.数组的every()和some()

  用法:
      arr.every((v) => { return 布尔值 });  //每一个元素经回调方法处理后都返回true该方法才返回true,否则返回false
    arr.some((v) => { return 布尔值 });     //只要有一个元素经回调方法处理返回true该方法就返回true,否则返回false

14.H5获取经纬度方法(参考文章)

  if(navigator.geolocation){
    navigator.geolocation.getCurrentPosition(success, error, option);
  }
  
  success为成功的回调:
  success(res){ console.log(res.coords.latitude, res.coords.longitude) }

  error为失败的回调:
  error(err){ console.log(err) }

  option为配置对象:
  {
     enableHighAccuracy: true,    //是否使用高精度
     timeout: 3000,               //设置超时时间,单位ms
  }

15.谷歌地图vue插件vue2-google-maps

    谷歌官方api文档

    1) 在main.js引入:

        import * as VueGoogleMaps from 'vue2-google-maps';
        Vue.use(VueGoogleMaps, {
          load: {
            key: 'AIzaSyAd1qk6XSs2u-Ea5Muc1hCf-ibL2mXOZKw',   //需要一个结算账户才可正常使用
            libraries: 'places',
            language: 'cn',                                      //语言码根据国际标准即可
          }
        });
    
    2) vue页面中:

      html部分:
        <GmapMap class="deviceMap" ref="gMap" :center="centerInfo" :zoom="zoom" :options="{
          zoomControl: false,          //放大、缩小
          mapTypeControl: false,       //卫星地图
          scaleControl: false,         //距离尺
          streetViewControl: false,    //街景视图
          rotateControl: false,        //旋转立体地图
          fullscreenControl: false,    //全屏
          //disableDefaultUi: false
        }">
          <GmapMarker @click="fillAddress" :visible="true" :position="centerInfo" :icon="{url: markUrl, scaledSize: {width: 20, height: 20}}" :animation="1"/>
          <!-- animation 1:循环跳动 2:水滴落下 -->
        </GmapMap>

      js部分:
        import { gmapApi } from 'vue2-google-maps';
        computed: {
          google: gmapApi
        },
        mounted: {
          this.$refs.gMap.$mapPromise.then((map) => {
            this.gMap = map;                                    //渲染完获取地图对象
            this.geocoder = new this.google.maps.Geocoder();    //实例化Geocoder对象,用于定位功能
          })
        },
        methods: {
          reset(){
            this.gMap.setCenter({lat: xx, lng: xx});    //动态设置中心点
            this.gMap.setZoom(12);                        //动态设置地图缩放倍数
          },
          search(){            
            this.geocoder.geocode({address: 'xxx'}, (results, status) => {    //搜地址返回经纬度
              if (status === 'OK') {
                this.centerInfo = {
                  lng: results[results.length - 1].geometry.location.lng(),
                  lat: results[results.length - 1].geometry.location.lat()
                }
              }
            });
            this.geocoder.geocode({location: {lat: x, lng: x}}, (results, status) => {    //根据经纬度返回地址
              if (status === 'OK') {
                this.searchAddr = results[results.length - 1].formatted_address;
              }
            });
          }
        }

16.ios的兼容问题

  onkeyup事件在有些ios手机上不生效,一般要用oninput事件(支持ie8以上)或          onpropertychange事件(支持ie8及以下)来实时监听用户输入

17.计算某元素到页面顶部的距离

  function getToTop(){
      const elem = document.getElementById('elem');
      let top = 0;
      while(elem = elem.offsetParent){
        top += elem.offsetTop;
      }
      return top;
  }

18.二维码生成插件qrcodejs2 (直接用npm安装)

  <div id="twoCode"></div>

  import QRCode from 'qrcodejs2';

  components: { QRCode },

  makeCode() {
    document.getElementById('twoCode').innerHTML = '';    //清除上一次的二维码
    new QRCode('twoCode', {  
          width: 180,        // 二维码宽度 
          height: 180,        // 二维码高度
          text: codeUrl,    //转二维码的url
    });
  }

19.堆排序(原理

    const target = [6,30,1,9,2,8,5,7,4,10,20,5,14,13,88,-1];

    function stackSort(arr, n){                                //大根堆(结果为升序)
        if(arr.length && n < arr.length - 1){             //数组中至少有2个数才需做排序
            let stackNum = arr.length - n;                //每次组成堆的所有节点数
            let last = parseInt(stackNum/2 - 1);    //从最后一个节点(除叶子节点)开始往根方向做对比,把本次堆的最大值冒出到根节点
            for(let i=last; i>=0; i--){
                let parentIdx = Math.floor((i-1)/2);
                let leftIdx = 2*i + 1;
                let rightIdx = 2*i + 2;
                if(leftIdx < stackNum && arr[i] < arr[leftIdx]){        //(1)跟左子节点比较
                    arr[leftIdx] = [arr[i], arr[i] = arr[leftIdx]][0];
                }
                if(rightIdx < stackNum && arr[i] < arr[rightIdx]){        //(2)跟右子节点比较
                    arr[rightIdx] = [arr[i], arr[i] = arr[rightIdx]][0];
                }
                if(parentIdx >= 0 && arr[parentIdx] < arr[i]){        //(3)跟父节点比较
                    arr[parentIdx] = [arr[i], arr[i] = arr[parentIdx]][0];
                }
            }
            arr[0] = [arr[stackNum - 1], arr[stackNum - 1] = arr[0]][0];
            stackSort(arr, n+1);
        }
    }
    stackSort(target, 0);            //结果为[-1, 1, 2, 4, 5, 5, 6, 7, 8, 9, 10, 13, 14, 20, 30, 88]

注意:小根堆 则把(1)(2)(3)中第2个条件的 "<" 改为 ">" 即可(结果为降序)

20.将字符串false转为布尔值false

    JSON.parse('false')        //false

21.css中隐藏的几种方式和区别

    display: none;                //脱落文档流,不占位置
    visibility: hidden;        //隐藏,占位置(元素自身的事件不可触发,如:input框中的内容 不可选中)
    opacity: 0;                        //隐藏,占位置(元素自身的事件可触发,如:input框中的内容 可选中,$('#input').select())

22.类型对比

    1)实例化结果对比的是值、或者内存地址,且有些值的对比会进行隐式转换;

        例如:let a = new Array(); let b = new Array(); a === b;   // false

    2)实例化结果的constructor指向其构造函数

        例如:let a = new Array();  a.constructor === Array;     // true

    3)构造函数的对比其实就是2个构造函数的内存地址对比

        例如:Array === Object;         // false

    4)任何构造函数本身的constructor都是指向Function这个构造函数

        例如:Array.constructor === Function;     // true

                  Object.constructor === Function;     // true

                  Function.constructor === Function;    //true

23.数组的sort方法

sort() 默认排序是按 字符串 做 升序排序(冒泡)

    [4,1,23,0,5].sort()                                                     //[0,1,23,4,5]

sort(fn)中回调函数返回值的作用:

    返回-1,则会将2个入参的排序顺序对调;

    返回0或1,则按原来的顺序;

    [4,1,23,0,5].sort(()=> 0)                                            //[4,1,23,0,5] 不变

    [4,1,23,0,5].sort(()=> 1)                                            //[4,1,23,0,5] 不变

    [4,1,23,0,5].sort(()=> -1)                                           //[5,0,23,1,4] 全反

    [4,1,23,0,5].sort((next,prev)=>next - prev)               //[0,1,4,5,23] 按数字升序

    [4,1,23,0,5].sort((next,prev)=>prev - next)               //[23,5,4,1,0] 按数字降序

24.回流和重绘

    解析html+解析css -> 生成render tree -> layout(回流)-> painting(重绘)-> 展示

    参考1:你真的了解回流和重绘吗 - SegmentFault 思否

    参考2:重绘和回流----降低回流减少性能影响_weixin_30416871的博客-CSDN博客

    注意1:浮动会脱离文档流,但不会脱离文本流(文字会围绕在其周围),absolute和fixed定位则二者都脱离

    注意2:绝对定位的元素已经脱离文档流,可减少其父元素和后续兄弟元素多余的回流

表格渲染大数据卡死问题

表格如果是滚动加载数据的话,那么会不断回流重绘,因为在不断地添加dom;如果只是单纯滚动,那么只会重绘,因为dom没有发生变化,而重绘是让你看到滚动的效果。

表格加载大数据会卡死,通常是在渲染前卡死,因为操作的dom太多了,一般渲染成功后去滚动则不怎么卡,因为单纯的滚动没有引起dom的改变

25.从后往前截取字符串

    ‘12345’.slice(-2);    // -2表示从后往前截取2位,即 '45'

26.hasOwnProperty报错问题

const obj = {a:1};
obj.hasOwnProperty('a')   // true

    在严格模式下会报错,可改为以下写法即可:

const obj = {a:1};
Object.hasOwnProperty.call(obj, 'a')   //true

27..call(),.apply(),.bind()的区别

.call(obj, a, b, ...)
.apply(obj, [a,b,...])
.bind(obj, a, b, ...)()

详情可见:JavaScript 中 call()、apply()、bind() 的用法 | 菜鸟教程

28.tiansition冲突

假如某个组件本身样式有transition,你自己想再加另一个transition,两者就会冲突,只有里面那个生效。因为transition样式不可被继承。

解决:可以在该组件外层套一个<div>,然后把另一个transition的样式写在这个div上

29.正则.exec()的使用

let reg = /[a-z]+-c\d+/g;
let str = 'asa/ddd-c123/p33asa/eee-c456/p44';
let arr = reg.exec(str);    //返回['ddd-c123']

exec会返回一个数组arr,arr[0]就是匹配到的第一个结果,然后就停下了(所以g标识对exec而言是无效的,可以不写),内部的lastIndex指到第一个匹配结果的下一个字符串。如果想继续匹配下一个结果,那么就得再执行一次exec,一直到匹配不到为止,则返回null。所以用exec想匹配所有结果,必须自己写循环逻辑,如下:

while(arr){
    arr = reg.exec(str);
}

假如只想从匹配到'ddd-c123'中的子片段,如ddd和123,那么可以用()在正则中包裹起来即可。结果仍然返回一个数组arr,arr[0]还是匹配到的第一个完整片段,后续的则都是正则中用()包裹起来的内容,如ddd和123,如果()包裹的内容匹配不到,则会返回一个空字符串,比如[完整片段,'','']。

let reg = /([a-z]+)-c(\d+)/;
let str = 'asa/ddd-c123/p33asa/eee-c456/p44';
let arr = reg.exec(str);    //返回['ddd-c123','ddd','123']

30.JS的事件冒泡

<div id="box1" onclick3>
    <div id="box2" onclick2>
        <span id="span" onclick1>This is a span.</span>
    </div>
</div>

点击子元素span,这个点击事件会冒泡给所有父元素,事件朝 子元素->父元素 这个方向传递,称为冒泡。点击完开始朝冒泡的方向依次执行各自的回调 onclick1 -> onclick2 -> onclick3。

在onclick(e)中使用e.stopPropagation()可阻止冒泡。

31.web worker介绍
参考文档:Web Worker 使用教程 - 阮一峰的网络日志

作用:为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。

注意:Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

// 主线程
var myWorker = new Worker('worker.js', { name : 'subWorker' });

Worker.onerror:指定 error 事件的监听函数。
Worker.onmessage:指定 message 事件的监听函数,发送过来的数据在Event.data属性中。
Worker.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
Worker.postMessage():向 Worker 线程发送消息。
Worker.terminate():立即终止 Worker 线程。

// subWorker 线程
self.name: Worker 的名字。该属性只读,由构造函数指定。
self.onmessage:指定message事件的监听函数。
self.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
self.close():关闭 Worker 线程。
self.postMessage():向产生这个 Worker 线程发送消息。
self.importScripts():加载 JS 脚本。

32.两个||和两个??的区别

0 || 123     //输出123

0 ?? 123   //输出0

|| 前面的表达式只要能转为false,就会执行后面的
?? 前面的表达式为undefined或null的时候,才会执行后面的

33.前端实现页面水印

1)利用canvas画出单个水印,然后利用.toDataURL('image/png')转为base64数据

2)创建一个与根元素(比如<div id="root"></div>)平级的另一个div,并把上一步的数据放入background-image: url(...)中

3)对该新的div做绝对定位,遮住整个页面

4)设置该新div的css为 pointer-events: none; 画重点,如果不设置的话,这个新div会挡住页面的所有其他事件,因为该div本身也有hover/click等等事件)

34.JSON.stringify()解析undefined

将对象转字符串时,会自动删掉 值为undefined的属性;

JSON.stringify({test: undefined});   结果为 '{}'

将数组转字符串时,会把undefined自动转为null;

JSON.stringify([undefined]);    结果为 '[null]'

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值