【JS】实用/工具函数/常用函数/Function方法

1.获取日月 时分秒

  //获取 月日
  getMonth=(time)=>{
    var date = new Date(time)
    var month = date.getMonth()+1<10?'0'+(date.getMonth()+1):(date.getMonth()+1)
    var date  = date.getDate()<10?'0'+date.getDate():date.getDate()
    return month+'-'+date
  }

  //获取时分秒
  getTime=(time)=>{
    var date = new Date(time)
    var hours = date.getHours()<10?'0'+date.getHours():date.getHours()
    var minutes  = date.getMinutes()<10?'0'+date.getMinutes():date.getMinutes()
    var second  = date.getSeconds()<10?'0'+date.getSeconds():date.getSeconds()
    return hours+':'+minutes+':'+second
  }

使用: 

const CreatedAt =  '0001-01-01T00:00:00Z'

  <Text style={{fontSize: 11, color: '#999999', marginRight: 6}}> { this.getMonth(item.CreatedAt) }  </Text>

 2.短信倒计时

按钮

<Touchable
    style={{
        position: 'absolute',
        right: 20,
        bottom: 15,
        backgroundColor: theme.bgc0,
        borderRadius: 25,
        justifyContent: 'center',
        alignItems: 'center',
         88,
        marginRight: 20,
        height:28,
    }}
    onPress={() => {
      this.send_sms();
    }}
>
    <View>
        <Text style={{
            color: '#FFFFFF',
            fontSize:11,
      }}>{buttonText}</Text>
    </View>
</Touchable>

发送验证码函数

  send_sms() {
    WalletAction.getVerificationCode().then((res) => { 
      if (res.status === 10000) {
        Toast.message('验证码发送成功');
        this.setState({ disabled: true });
        this._setTimeout(60);
      } else {
  
        Toast.message(res.message);
        this.setState({ disabled: false });
      }
    });
  }

倒计时函数

_setTimeout(number) {
    if (number) {
      if (this.state.time > 0) {
        return;
      }
      this.setState({
        time: number - 1,
        buttonText: `${number - 1}秒后重发`,
      }, () => {
        this._setTimeout();
      });
      return;
    }
    if (this.state.time < 1) {
      this.setState({
        buttonText: '获取验证码',
        disabled: false,
      });

    } else {
      this.setState({
        time: this.state.time - 1,
        buttonText: `${this.state.time}秒后重发`,
      });
      this.timer = setTimeout(() => {
        this._setTimeout();
      }, 1000);
    }
  }

 HTML 短信倒计时按钮

    function msgTimeout(number){
        if(number){
            if(time > 0){
                return
            }
            time = number;
            $('#captcha').text( time  + '秒后重新获取').css({'border':'1px solid #c5c5c5','color':'#c5c5c5'})
        }

       if(time < 1){
            $('#captcha').text('获取验证码').css({'border':'1px solid #dba95e','color':'#dba95e'}).attr('onclick'); //恢复点击事件
        }else {
            time = time -1;
            $('#captcha').text( time  + '秒后重新获取').removeAttr('onclick'); //移除点击事件
            setTimeout(function () {
                msgTimeout()
            },1000)
        }
    }

    //验证码按钮
    $('#captcha').on('click',function () {
        msgTimeout(10)
    });

React Hook 钩子倒计时

    const [smsText, setSmsText] = useState('60秒后重发');
    

    const send_sms = () => {
        if (!disable) {
            setDisable(true);
            _setTimeout(60);
        }
    };

    const _setTimeout = (number) => {
        if (number === 0) {
            setDisable(false);
        }
        setSmsText(`${number}秒后重发`);

        const smsTimeout = setTimeout(() => {
            _setTimeout(number - 1);
        }, 1000);
        if (number === 0) {
            clearTimeout(smsTimeout);
        }
    };

   <div
       className={classNames('reg-msg', {
         'reg-disable': disable,
         })}
         onClick={() => {
         send_sms();
         }}
          >
         {disable ? smsText : '发送验证码'}
   </div>

extra:一般倒计时

   countTime = (endTime) => {
        //获取当前时间
        let date = this.state.currentTime;
        let now = date.getTime();
        //设置截止时间
        let endDate =moment(endTime)._d;
        let end = endDate.getTime();
        //时间差
        let leftTime = end - now;
        //定义变量 d,h,m,s保存倒计时的时间
        let d, h, m, s;
        if (leftTime >= 0) {
            d = Math.floor(leftTime / 1000 / 60 / 60 / 24);
            h = Math.floor(leftTime / 1000 / 60 / 60 % 24);
            m = Math.floor(leftTime / 1000 / 60 % 60);
            s = Math.floor(leftTime / 1000 % 60);
        }
       // console.log('1',new Date("2020-6-01 00:00:00"))
        return  d + "天" + h + "时" + m + "分" + s + "秒"
    };

   {
title: '剩余时长',
200,
dataIndex: '',
key: '',
render:(text,record) => (
<div>{this.countTime(record.end_time)}</div>
)
}
 

3.计时器: 时分秒

  countTime() { // 记录已用聊天时间
    this._timer = setInterval(() => {
      let {seconds} = this.state; // 获取秒
      let {minutes} = this.state; // 获取分钟
      let {hour} = this.state; // 获取小时
      if (seconds < 60) { // 秒数如果小于60 就加1
        seconds++;
        if (seconds == 60) { // 秒数如果等于60 就 重置为0
          seconds = 0,
          minutes = ++minutes;
          if (minutes == 60) {
            minutes = 0;
            hour = ++hour;
          }
        }
        this.setState({
          seconds, // 更改秒的状态
          minutes, // 更改分钟的状态
          hour, // 更改小时的状态
        });
      }
    }, 1000);
  }


<Text style={{fontSize: 12, color: '#fff'}}>
               {
                 hour.toString().length == 2 ? null : 0
               }
               {hour}
               :
               {
                 minutes.toString().length == 2 ? null : 0
               }
               {minutes}
               :
               {
                 seconds.toString().length == 2 ? null : 0
               }
               {seconds}
</Text>

4.评分组件

import React, { Component } from 'react'
import {
    View,
    StyleSheet,
    TouchableOpacity,
    Image,
} from 'react-native';
import PropTypes from 'prop-types';


export default class StarRating extends Component {
    static defaultProps = {
        maxStars: 5,
        rating: 1,
        starSize: -1,
        interItemSpacing: 0,
        valueChanged: (index) => { },
        editAble: true,
    };
    static propTypes = {
        maxStars: PropTypes.number,
        rating: PropTypes.number,
        unSelectStar: PropTypes.number,
        valueChanged: PropTypes.func,
        starSize: PropTypes.number,
        interItemSpacing: PropTypes.number,
        editAble: PropTypes.bool,
    };

    constructor(props) {
        super(props);
        this.state = {
            maxStars: this.props.maxStars,
            rating: this.props.rating,
            firstImageLayout: null,
            starSize: this.props.starSize,
        };
    }

    render() {
        let starArray = [];
        let imageSource = null;
        for (let i = 1; i <= this.state.maxStars; i++) {
            if (i <= this.props.rating) {
                imageSource = this.props.selectStar;
            }
            else {
                imageSource = this.props.unSelectStar;
            }

            let styleArray = [];
            if (i !== this.state.maxStars) {
                styleArray.push({ marginRight: this.props.interItemSpacing });
            }
            if (this.state.starSize > 0) {
                styleArray.push({  this.state.starSize, height: this.state.starSize });
            }

            //push Image
            starArray.push(
                <TouchableOpacity
                    key={i}
                    onPress={() => {
                        if (this.props.editAble) {
                            this.props.valueChanged(i)
                        }
                    }}
                >
                    <Image
                        source={imageSource}
                        style={styleArray}
                    />
                </TouchableOpacity>
            );
        }
        return (
            <View
                style={styles.container}
            >
                {starArray}
            </View>
        )
    }

};

const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
    }
});

使用:

<StarRating
    maxStars={5} // 最大星星数量
    rating={this.state.sellerScore} // 当前星星数
    starSize={20} // 星星大小
    interItemSpacing={23} // 星星之间的间距
    valueChanged={(star) => {this.setState({sellerScore: star},() => {console.log(this.state.sellerScore)})}} // 星星数量改变
    selectStar={videoVoice} // 选中图片
    unSelectStar={videoAudio} // 未选中图片
/>

5.点赞

 //点赞
  like(id,isLike) {
    Http.postForm('/api/user/find/timeline/like/count', {
      id: id,
      status:isLike   //1点赞,2取消
    }).then((res) => {
      if (res.status === 10000) {
        if (isLike === 1) {
          this.setState({
            isLike: 2,
        });
        } else {
          this.setState({
            isLike: 1,
        });
        }
        this.getUserInfo() //获取点赞数量
    }
    })
  }

 getUserInfo() {
      Http.postForm('/api/user/userinfo').then(res => {
        console.log('获取用户ID',res)
        if (res.status === 10000) {
          this.Checklike(this.props.item.ID,res.user.ID)
          this.setState({
            Userid:res.user.ID
          })
        }
      })
    }
    //查看动态详情
  Checklike(id,Userid) {
    Http.postForm('/api/user/find/timeline/detail', {
      id,
      user_id:Userid
    }).then((res) => {
      console.log('查看返回信息',res);
      if (res.status === 10000) {
        this.setState({
          like_number:res.data.like_number,
          comment_number:res.data.comment_number,
          is_like:res.data.is_like,//1 已点赞 2 没点赞
          isLike:res.data.is_like===1?2:1
        })
    }
    })
  }

// 渲染标签
<Touchable
            delayPress={300}
            style={{
              flexDirection: 'row',
              alignItems: 'center',
              marginRight: 30,
            }}
            onPress={()=>{this.like(item.ID,isLike)}}
          >
            {is_like === 2? <Image source={unstar}/>: <Image source={star} />}
            <Text style={{fontSize: 11, color: '#C1C1C1', marginLeft: 6,marginTop:3 }}>{like_number}</Text>
          </Touchable>

 6.在数组中跟根据id数组筛选出相同id的对象

大数组.filter(item=>
            id数组.filter(e=>e === item.id).length > 0 )

为什么length要大于0呢?

7.颜色渐变代码

 getColor = (bili) => {
    //var 百分之一 = (单色值范围) / 50;  单颜色的变化范围只在50%之内
    let one = (255+255) / 100;
    let r=0;
    let g=0;
    let b=0;

    if ( bili < 50 ) {
      // 比例小于50的时候红色是越来越多的,直到红色为255时(红+绿)变为黄色.
      r = one * bili;
      g=255;
    }
    if ( bili >= 50 ) {
      // 比例大于50的时候绿色是越来越少的,直到0 变为纯红
      g =  255 - ( (bili - 50 ) * one) ;
      r = 255;
    }
    r = parseInt(r);// 取整
    g = parseInt(g);// 取整
    b = parseInt(b);// 取整

    return "rgb("+r+","+g+","+b+")";

  };

8.生成一周时间

new Array 创建的数组只是添加了length属性,并没有实际的内容。通过扩展后,变为可用数组用于循环

function getWeekTime(){
  return [...new Array(7)].map((j,i)=> new Date(Date.now()+i*8.64e7).toLocaleDateString())
}

使用

getWeekTime()
// ["2020/2/26", "2020/2/27", "2020/2/28", "2020/2/29", "2020/3/1", "2020/3/2", "2020/3/3"]

9.类型判断

判断核心使用 Object.prototype.toString,这种方式可以准确的判断数据类型。

/**
 * @param {any} target 
 * @param {string} type 
 * @return {boolean} 
 */
function isType(target, type) {
  let targetType = Object.prototype.toString.call(target).slice(8, -1).toLowerCase()
  return targetType === type.toLowerCase()
}

使用

isType([], 'Array') // true
isType(/d/, 'RegExp') // true
isType(new Date(), 'Date') // true
isType(function(){}, 'Function') // true
isType(Symbol(1), 'Symbol') // true

10.对象属性剔除

应用场景很简单,当你需要使用一个对象,但想移除部分属性时,可以使用该方法。同样的,你可以实现一个对象属性选取方法。

/**
 * @param {object} object
 * @param {string[]} props
 * @return {object}
 */
function omit(object, props=[]){
  let res = {}
  Object.keys(object).forEach(key=>{
    if(props.includes(key) === false){
      res[key] = typeof object[key] === 'object' && object[key] !== null ?
        JSON.parse(JSON.stringify(object[key])):
        object[key]
    }
  })
  return res
}

使用

let data = {
  id: 1,
  title: 'xxx',
  comment: []
}
omit(data, ['id']) // {title: 'xxx', comment: []} 

11.日期格式化  /或者用moment

一个很灵活的日期格式化函数,可以根据使用者给定的格式进行格式化,能应对大部分场景

/**
 * @param {string} format
 * @param {number} timestamp - 时间戳
 * @return {string} 
 */
function formatDate(format='Y-M-D h:m', timestamp=Date.now()){
  let date = new Date(timestamp)
  let dateInfo = {
    Y: date.getFullYear(),
    M: date.getMonth()+1,
    D: date.getDate(),
    h: date.getHours(),
    m: date.getMinutes(),
    s: date.getSeconds()
  }
  let formatNumber = (n) => n > 10 ? n : '0' + n
  let res = format
    .replace('Y', dateInfo.Y)
    .replace('M', dateInfo.M)
    .replace('D', dateInfo.D)
    .replace('h', formatNumber(dateInfo.h))
    .replace('m', formatNumber(dateInfo.m))
    .replace('s', formatNumber(dateInfo.s))
  return res
}

使用

formatDate() // "2020-2-24 13:44"
formatDate('M月D日 h:m') // "2月24日 13:45"
formatDate('h:m Y-M-D', 1582526221604) // "14:37 2020-2-24"

extra:

      var formatDateTime = function (date) {

            var y = date.getFullYear();

            var m = date.getMonth() + 1;

            m = m < 10 ? ('0' + m) : m;

            var d = date.getDate();

            d = d < 10 ? ('0' + d) : d;

            var h = date.getHours();

            h=h < 10 ? ('0' + h) : h;

            var minute = date.getMinutes();

            minute = minute < 10 ? ('0' + minute) : minute;

            var second=date.getSeconds();

            second=second < 10 ? ('0' + second) : second;

            return y + '-' + m + '-' + d+' '+h+':'+minute+':'+second;

        };

         formatDateTime(new Date()) //2020-05-16 16:03:13

12.性能分析

Web Performance API允许网页访问某些函数来测量网页和Web应用程序的性能

performance.timing 包含延迟相关的性能信息

performance.memory 包含内存信息,是Chrome中添加的一个非标准扩展,在使用时需要注意

window.onload = function(){
  setTimeout(()=>{
    let t = performance.timing,
        m = performance.memory
    console.table({
      'DNS查询耗时': (t.domainLookupEnd - t.domainLookupStart).toFixed(0),
      'TCP链接耗时': (t.connectEnd - t.connectStart).toFixed(0),
      'request请求耗时': (t.responseEnd - t.responseStart).toFixed(0),
      '解析dom树耗时': (t.domComplete - t.domInteractive).toFixed(0),
      '白屏时间': (t.responseStart - t.navigationStart).toFixed(0),
      'domready时间': (t.domContentLoadedEventEnd - t.navigationStart).toFixed(0),
      'onload时间': (t.loadEventEnd - t.navigationStart).toFixed(0),
      'js内存使用占比': m ? (m.usedJSHeapSize / m.totalJSHeapSize * 100).toFixed(2) + '%' : undefined
    })
  })
}

13.防抖

性能优化方案,防抖用于减少函数请求次数,对于频繁的请求,只执行这些请求的最后一次。

基础版本

function debounce(func, wait = 300){
  let timer = null;
  return function(){
    if(timer !== null){
      clearTimeout(timer);
    }
    timer = setTimeout(fn,wait);
  }
}

改进版本添加是否立即执行的参数,因为有些场景下,我们希望函数能立即执行。

/**
 * @param {function} func - 执行函数
 * @param {number} wait - 等待时间
 * @param {boolean} immediate - 是否立即执行
 * @return {function}
 */
function debounce(func, wait = 300, immediate = false){
  let timer, ctx;
  let later = (arg) => setTimeout(()=>{
    func.apply(ctx, arg)
    timer = ctx = null
  }, wait)
  return function(...arg){
    if(!timer){
      timer = later(arg)
      ctx = this
      if(immediate){
        func.apply(ctx, arg)
      }
    }else{
      clearTimeout(timer)
      timer = later(arg)
    }
  }
}

使用

let scrollHandler = debounce(function(e){
  console.log(e)
}, 500)
window.onscroll = scrollHandler

14.节流

性能优化方案,节流用于减少函数请求次数,与防抖不同,节流是在一段时间执行一次。

/**
 * @param {function} func - 执行函数
 * @param {number} delay - 延迟时间
 * @return {function}
 */
function throttle(func, delay){
  let timer = null
  return function(...arg){
    if(!timer){
      timer = setTimeout(()=>{
        func.apply(this, arg)
        timer = null
      }, delay)
    }
  }
}

使用

let scrollHandler = throttle(function(e){
  console.log(e)
}, 500)
window.onscroll = scrollHandler

15.base64数据导出文件下载

/**
 * @param {string} filename - 下载时的文件名
 * @param {string} data - base64字符串
 */
function downloadFile(filename, data){  
  let downloadLink = document.createElement('a');  
  if ( downloadLink ){  
    document.body.appendChild(downloadLink);  
    downloadLink.style = 'display: none';  
    downloadLink.download = filename;  
    downloadLink.href = data;  
    if ( document.createEvent ){  
      let downloadEvt = document.createEvent('MouseEvents');  
      downloadEvt.initEvent('click', true, false);  
      downloadLink.dispatchEvent(downloadEvt);  
    } else if ( document.createEventObject ) {
      downloadLink.fireEvent('onclick');  
    } else if (typeof downloadLink.onclick == 'function' ) {
      downloadLink.onclick();
    }
    document.body.removeChild(downloadLink);  
  }  
}  

16.检测是否为PC端浏览器

function isPCBroswer() {  
  let e = window.navigator.userAgent.toLowerCase()  
    , t = "ipad" == e.match(/ipad/i)  
    , i = "iphone" == e.match(/iphone/i)  
    , r = "midp" == e.match(/midp/i)  
    , n = "rv:1.2.3.4" == e.match(/rv:1.2.3.4/i)  
    , a = "ucweb" == e.match(/ucweb/i)  
    , o = "android" == e.match(/android/i)  
    , s = "windows ce" == e.match(/windows ce/i)  
    , l = "windows mobile" == e.match(/windows mobile/i);
  return !(t || i || r || n || a || o || s || l)  
} 

17.识别浏览器及平台

function getPlatformInfo(){
  //运行环境是浏览器 
  let inBrowser = typeof window !== 'undefined';  
  //运行环境是微信  
  let inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;  
  let weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();  
  //浏览器 UA 判断  
  let UA = inBrowser && window.navigator.userAgent.toLowerCase();
  if(UA){
    let platforms = {
      IE: /msie|trident/.test(UA),
      IE9: UA.indexOf('msie 9.0') > 0,
      Edge: UA.indexOf('edge/') > 0,
      Android: UA.indexOf('android') > 0 || (weexPlatform === 'android'),
      IOS: /iphone|ipad|ipod|ios/.test(UA) || (weexPlatform === 'ios'),
      Chrome: /chrome/d+/.test(UA) && !(UA.indexOf('edge/') > 0),
    }
    for (const key in platforms) {
      if (platforms.hasOwnProperty(key)) {
        if(platforms[key]) return key
      }
    }
  }
}

18.休眠函数

   //参数n为休眠时间,单位为毫秒:    
    function sleep(n) {
        var start = new Date().getTime();
        console.log('休眠前:' + start);
        while (true) {
            if (new Date().getTime() - start > n) {
                break;
            }
        }
        console.log('休眠后:' + new Date().getTime());
    }
    function abc(){
  console.log('123')
    
sleep(3000)
console.log('222')
}

19.数组去重,返回一个新数组

案例一

function unique(arr){
    if(!isArrayLink(arr)){ //不是类数组对象
        return arr
    }
    let result = []
    let objarr = []
    let obj = Object.create(null)
    
    arr.forEach(item => {
        if(isStatic(item)){//是除了symbol外的原始数据
            let key = item + '_' + getRawType(item);
            if(!obj[key]){
                obj[key] = true
                result.push(item)
            }
        }else{//引用类型及symbol
            if(!objarr.includes(item)){
                objarr.push(item)
                result.push(item)
            }
        }
    })
    
    return resulte
}

 案例二 checkBox 多选框  拼接多个种类

拼接多个数组,分门别类组成一个新的总数组。

    //获取二级策略 访问同一接口多次
    _getList(id) {
       //时机为第一个
    
if (id == this.props.list[0].id) { this.setState({ loading:window.$message.loading('加载中', 0) }); } HttpUtils.postForm('/api/admin/dm/strategy/list', { dm_strategy_temp_id: id, page: 1, pers: 50 }).then(res => { if (res.status === 10000) { if(res.data.length > 0){ this.setState({ data:this.state.data.concat([{fatherId:id,son:res.data}]), }) }
          //时机为最后一个
if(id == this.props.list[this.props.list.length - 1].id){ setTimeout(()=>{ this.setState({ visible:true, }) this.state.loading() },500) } }else { this.state.loading()
          //时机为最后一个
if(id == this.props.list[this.props.list.length - 1].id){ window.$message.warn(res.message); } } }).catch(() => { this.state.loading() window.$message.error('通讯失败') }) }

//checkBox 多选 选了一类二级分类1 ,再去选择二类二级分类1的时候, 一类二级分类1 直接没了(因为这里使用的onChange函数是同一个checkedList)
一类
一类二级分类1
二类
二类二级分类1
//解决办法: 使用组件
//父组件
{
this.props.list && this.props.list.filter(item=>{return item.id !== -1 }).map(items=>(
<CheckedItem onChange={this._getChecklist} ref={(e)=>{this._checkBox = e}} data={this.state.data} items={items} />
    ))
}

CheckedItem.js
render() {
const {items,data} = this.props
return (
<div>
<div className="site-checkbox-all-wrapper">
<Checkbox
onChange={this.onCheckAllChange}
checked={this.state.checkAll}
>
{items.name}
</Checkbox>
</div>
<br />
<CheckboxGroup
options={this.state.plainOptions}
value={this.state.checkedList}
onChange={(e)=>{this.onChange(e,items.id)}}
style={{marginBottom:10}}
/>
</div>
);
}
 

 new Map() 函数去重 / 拼接checkedItem组件的值 

//数组去重
unique = (arr)=>{ const res = new Map(); return arr.filter((val)=>!res.has(val) && res.set(val,1)) }
   _getChecklist = (checkedList,isRemove,val)=>{
        const newArr = this.unique(this.state.checkedList.concat(checkedList))
        if (isRemove){
            for(let i = 0 ; i < newArr.length ; i ++){
                if (newArr[i] == val) {
                    newArr.splice(i,1)
                }
            }
        }

        this.setState({
            checkedList:newArr
        })
    };

按类别筛选

    componentDidMount() {
        const {items,data} = this.props
        this.setState({
            plainOptions:data.length>0 &&  data.filter(item=>{
                return item.fatherId === items.id
            }).length > 0 &&  data.filter(item=>{
                return item.fatherId === items.id //自己做的数组中的值 fatherId === 8个对象中的id值
            })[0].son.map(item=>{
                return{
                    label: item.name,
                    value: item.id
                }
            })
        })
    }

 删除数组中指定元素 这个例子中不能直接使用,但可以借鉴

//删除数组中指定元素
    const a  = [30,60,90,120,150]
    Array.prototype.indexOf = function (val) {
        for (let i = 0 ; i < a.length ; i ++ ){
            console.log('index',i,'val',val)
            if(this[i] == val) return i ;
        }
        return -1;
    };

    Array.prototype.remove = function (val) {
        const index = a.indexOf(val)
        if(index > -1){
            this.splice(index,1)
            console.log('哈哈',this)
        }
    };

    a.remove([90])
    console.log('让我康康',a) // 30 ,60 120 ,150

借鉴修改的函数

 includes 函数 检查数组是否含有某元素 是则返回true

//CheckItem中的选择框onChange函数,数组相减获取需要删除的元素

    onChange = (checkedList,id) => {

        console.log('当前',checkedList,'上次',this.state.checkedList)

        if(checkedList.length < this.state.checkedList.length){ //这里说明有的勾选被取消了
            this.props.onChange(checkedList,true,this.state.checkedList.filter(el => !checkedList.includes(el)))
            console.log('两个数组相减',this.state.checkedList.filter(el => !checkedList.includes(el)))
        }else {
            this.props.onChange(checkedList)
        }

        this.setState({
            checkedList,
            indeterminate: !!checkedList.length && checkedList.length < this.state.plainOptions.length,
            father:id,
            checkAll: checkedList.length === this.state.plainOptions.length,
        });
    };

//父组件调用删除函数

   _getChecklist = (checkedList,isRemove,val)=>{
        const newArr = this.unique(this.state.checkedList.concat(checkedList))
        if (isRemove){
            for(let i = 0 ; i < newArr.length ; i ++){
                if (newArr[i] == val) {
                    newArr.splice(i,1)
                }
            }
        }

        this.setState({
            checkedList:newArr
        })
    };

 

20.获取Url参数,返回一个对象

function GetUrlParam(){
    let url = document.location.toString();
    let arrObj = url.split("?");
    let params = Object.create(null)
    if (arrObj.length > 1){
        arrObj = arrObj[1].split("&");
        arrObj.forEach(item=>{
            item = item.split("=");
            params[item[0]] = item[1]
        })
    }
    return params;
}
// ?a=1&b=2&c=3 ==> {a: "1", b: "2", c: "3"}

21.禁止键盘事件

document.addEventListener('keydown', function(event){
    return !(
        112 == event.keyCode || //F1
        123 == event.keyCode || //F12
        event.ctrlKey && 82 == event.keyCode || //ctrl + R
        event.ctrlKey && 78 == event.keyCode || //ctrl + N
        event.shiftKey && 121 == event.keyCode || //shift + F10
        event.altKey && 115 == event.keyCode || //alt + F4
        "A" == event.srcElement.tagName && event.shiftKey //shift + 点击a标签
    ) || (event.returnValue = false)
});

22.禁止 右键/选择/复制

['contextmenu', 'selectstart', 'copy'].forEach(function(ev){
    document.addEventListener(ev, function(event){
        return event.returnValue = false
    })
});

23.交集/并集/去重

    1.求交集
    var arr1 = [{name:'name1',id:1},{name:'name2',id:2},{name:'name3',id:3}];
      var arr1Id = [1,2,3]
      var arr2 = [{name:'name1',id:1},{name:'name2',id:2},{name:'name3',id:3},{name:'name4',id:4},{name:'name5',id:5}];
      var result = arr2.filter(function(v){
            return arr1Id.indexOf(v.id)!==-1 // 利用filter方法来遍历是否有相同的元素
        })
      console.log(result);
      2.求并集
    let arr1 = [{name:'name1',id:1},{name:'name2',id:2},{name:'name3',id:3}];
      let arr2 = [{name:'name1',id:1},{name:'name4',id:4},{name:'name5',id:5}];
      let arr3 = arr1.concat(arr2);
      let result = [];
      var obj = [];
      result = arr3.reduce(function(prev, cur, index, arr) {
        console.log(prev, cur);
        obj[cur.id] ? '' : obj[cur.id] = true && prev.push(cur);
        return prev;
      }, []);
      console.log(result);
3.求差集<br>    let arr1 = [{name:'name1',id:1},{name:'name2',id:2},{name:'name3',id:3}];
  let arr1Id = [1,2,3];
  let arr2 = [{name:'name1',id:1},{name:'name4',id:4},{name:'name5',id:5}];
  let arr2Id = [1,4,5];
  let arr3 = arr1.concat(arr2);
  let result = arr3.filter(function(v){
      return arr1Id.indexOf(v.id)===-1 || (arr2Id.indexOf(v.id)===-1)
  })
  console.log(result);
      4.去重
    let arr = [{name:'name1',id:1},{name:'name2',id:2},{name:'name3',id:3},{name:'name1',id:1},{name:'name4',id:4},{name:'name5',id:5}];
      var obj = [];
      let result = arr.reduce(function(prev, cur, index, arr) {
        console.log(prev, cur);
        obj[cur.id] ? '' : obj[cur.id] = true && prev.push(cur);
        return prev;
      }, []);
去重运用:
 a方法
       let includeThis = false
            let vm = this
            if(vm.informedPersonList.length>0){
                vm.informedPersonList.forEach(el =>{
                    if(el.id == vm.selectedTrueItem.id){
                        includeThis = true
                    }
                })
            }
            if(includeThis===false){
                vm.informedPersonList.push(vm.selectedTrueItem)
            }else{
                Message({message: '请勿重复添加',type: 'warning'})
            }
 b方法(必须先let informedPersonL = vm.informedPersonList,不能直接使用vm.informedPersonList,否则浏览器控制台会报错)

vm.informedPersonList.push(this.selectedTrueItem)
let obj = {};
let informedPersonL = vm.informedPersonList
informedPersonL = informedPersonL.reduce((cur,next) => {
    obj[next.id] ? "" : obj[next.id] = true && cur.push(next);
    return cur;
},[]) //设置cur默认类型为数组,并且初始值为空的数组
vm.selectedTrueItem = {}
vm.$emit("backInformedPList",informedPersonL);

24.删除数组对象中相同的对象

       deteleObject = (obj) =>{
                var uniques = [];
                var stringify = {};
                for (var i = 0; i < obj.length; i++) {
                    var keys = Object.keys(obj[i]);
                    keys.sort(function(a, b) {
                        return (Number(a) - Number(b));
                    });
                    var str = '';
                    for (var j = 0; j < keys.length; j++) {
                        str += JSON.stringify(keys[j]);
                        str += JSON.stringify(obj[i][keys[j]]);
                    }
                    if (!stringify.hasOwnProperty(str)) {
                        uniques.push(obj[i]);
                        stringify[str] = true;
                    }
                }
                uniques = uniques;
                return uniques;
            }
            const obj = [
                {name:'1',url:'a'},
                {name:'1',url:'a'},
                {name:'2',url:'b'},
            ]
            console.log('让我康康',this.deteleObject(obj))

25.JS 阿拉伯数字与中文数字互转

var chnUnitSection = ["","万","亿","万亿","亿亿"]; //阿拉伯数字转中文数字用
var chnUnitChar = ["","十","百","千"]; //阿拉伯数字转中文数字用
var chnNumChar = ["零","一","二","三","四","五","六","七","八","九"]; //两个都要用到
var chnNameValue = { //中文数字转阿拉伯数字作用

    ChineseToNumber(chnStr){
var rtn = 0; var section = 0; var number = 0; var secUnit = false; var str = chnStr.split(''); for(var i = 0; i < str.length; i++){ var num = chnNumChar[str[i]]; if(typeof num !== 'undefined'){ number = num; if(i === str.length - 1){ section += number; } }else{ var unit = chnNameValue[str[i]].value; secUnit = chnNameValue[str[i]].secUnit; if(secUnit){ section = (section + number) * unit; rtn += section; section = 0; }else{ section += (number * unit); } number = 0; } } return rtn + section; } SectionToChinese(section){ var strIns = '', chnStr = ''; var unitPos = 0; var zero = true; while(section > 0){ var v = section % 10; if(v === 0){ if(!zero){ zero = true; chnStr = chnNumChar[v] + chnStr; } }else{ zero = false; strIns = chnNumChar[v]; strIns += chnUnitChar[unitPos]; chnStr = strIns + chnStr; } unitPos++; section = Math.floor(section / 10); } return chnStr; } NumberToChinese = (num)=>{ var unitPos = 0; var strIns = '', chnStr = ''; var needZero = false; if(num === 0){ return chnNumChar[0]; } while(num > 0){ var section = num % 10000; if(needZero){ chnStr = chnNumChar[0] + chnStr; } strIns = this.SectionToChinese(section); strIns += (section !== 0) ? chnUnitSection[unitPos] : chnUnitSection[0]; chnStr = strIns + chnStr; needZero = (section < 1000) && (section > 0); num = Math.floor(num / 10000); unitPos++; } return chnStr; }

阿拉伯数字转汉字二

    const numberChinese = (number) => {
        let units = '个十百千万@#%亿^&~', chars = '零一二三四五六七八九';
        let a = (number + '').split(''), s = []
        if (a.length > 12) {
            throw new Error('too big');
        } else {
            for (let i = 0, j = a.length - 1; i <= j; i++) {
                if (j == 1 || j == 5 || j == 9) {//两位数 处理特殊的 1*
                    if (i == 0) {
                        if (a[i] != '1') s.push(chars.charAt(a[i]));
                    } else {
                        s.push(chars.charAt(a[i]));
                    }
                } else {
                    s.push(chars.charAt(a[i]));
                }
                if (i != j) {
                    s.push(units.charAt(j - i));
                }
            }
        }
        //return s;
        return s.join('').replace(/零([十百千万亿@#%^&~])/g, function (m, d, b) {//优先处理 零百 零千 等
            b = units.indexOf(d);
            if (b != -1) {
                if (d == '亿') return d;
                if (d == '') return d;
                if (a[j - b] == '0') return ''
            }
            return '';
        }).replace(/零+/g, '').replace(/零([万亿])/g, function (m, b) {// 零百 零千处理后 可能出现 零零相连的 再处理结尾为零的
            return b;
        }).replace(/亿[万千百]/g, '亿').replace(/[零]$/, '').replace(/[@#%^&~]/g, function (m) {
            return { '@': '', '#': '', '%': '', '^': '', '&': '', '~': '' }[m];
        }).replace(/([亿万])([一-九])/g, function (m, d, b, c) {
            c = units.indexOf(d);
            if (c != -1) {
                if (a[j - c] == '0') return d + '' + b
            }
            return m;
        });
    }

 

 

 

26.科学计数法转化为数字

function toFixed(x) {
  if (Math.abs(x) < 1.0) {
    var e = parseInt(x.toString().split('e-')[1]);
    if (e) {
        x *= Math.pow(10,e-1);
        x = '0.' + (new Array(e)).join('0') + x.toString().substring(2);
    }
  } else {
    var e = parseInt(x.toString().split('+')[1]);
    if (e > 20) {
        e -= 20;
        x /= Math.pow(10,e);
        x += (new Array(e+1)).join('0');
    }
  }
  return x;
}

 27.时间戳转化为日期

    var dateFormat = function (timestamp, formats) {
        // formats格式包括
        // 1. Y-m-d
        // 2. Y-m-d H:i:s
        // 3. Y年m月d日
        // 4. Y年m月d日 H时i分
        formats = formats || 'Y-m-d';

        var zero = function (value) {
            if (value < 10) {
                return '0' + value;
            }
            return value;
        };

        var myDate = timestamp? new Date(timestamp): new Date();

        var year = myDate.getFullYear();
        var month = zero(myDate.getMonth() + 1);
        var day = zero(myDate.getDate());

        var hour = zero(myDate.getHours());
        var minite = zero(myDate.getMinutes());
        var second = zero(myDate.getSeconds());

        return formats.replace(/Y|m|d|H|i|s/ig, function (matches) {
            return ({
                Y: year,
                m: month,
                d: day,
                H: hour,
                i: minite,
                s: second
            })[matches];
        });
    };

    console.log('date',dateFormat(1589365354007,'Y年m月d日 H时i分')) // 2020年05月13日 18时22分

 28.自动分隔手机号     

       

    $("#mobilePhone").keyup(function(){
        let text_len = this.value.length;
        if ((text_len === 3 || text_len === 8) && window.event.keyCode !== 8 ) {
            this.value += " ";
        }

    });
//表单验证替换空格
const tel = $('#mobilePhone').val().replace(/s*/g,"");

29.textarea高度自适应

$.fn.autoHeight = function(){
        function autoHeight(elem){
            elem.style.height = 'auto';
            elem.scrollTop = 0; //防抖动
            elem.style.height = elem.scrollHeight + 'px';
        }
        this.each(function(){
            autoHeight(this);
            $(this).on('keyup', function(){
                autoHeight(this);
            });
        });
    };
    $('textarea[autoHeight]').autoHeight();

直接在textarea标签上添加 autoHeight='true' 即可

 

 30.jQuery点击空白处关闭弹窗 

    $(document).mouseup(function(e){
        var _con=$('目标区域');//设置目标区域
        if(!_con.is(e.target)&&_con.has(e.target).length===0){//Mark1
            $('.confirm-info').addClass('hidden')
            $('.confirm-box').addClass('hidden')
        }
    });

 

经过测试,在移动端Iphone手机上点击页面空白处弹出层关闭失效,不支持document写法,解决方案:可以添加一个背景层作为页面空白对象处理。  (用main替代document)

       $('.main').mouseup(function(e){
            if(!con.is(e.target)&& con.has(e.target).length === 0){
                con.addClass('hidden')
             $('.main').addClass('hidden')

            }
        })

然后又发现了一个问题 ios系统点击会有灰色背景出现,解决方法

html,body{
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}

CSS3 鲜为人知的属性-webkit-tap-highlight-color的理解

(一)-webkit-tap-highlight-color
        这个属性只用于iOS (iPhone和iPad)。当你点击一个链接或者通过Javascript定义的可点击元素的时候,它就会出现一个半透明的灰色背景。要重设这个表现,你可以设置-webkit-tap-highlight-color为任何颜色。
想要禁用这个高亮,设置颜色的alpha值为0即可。
示例:设置高亮色为50%透明的红色:
-webkit-tap-highlight-color: rgba(255,0,0,0.5);
浏览器支持: 只有iOS(iPhone和iPad).
(二)css3中-webkit-text-size-adjust详解:      

1、当样式表里font-size<12px时,中文版chrome浏览器里字体显示仍为12px,这时可以用 html{-webkit-text-size-adjust:none;}

2、-webkit-text-size-adjust放在body上会导致页面缩放失效

3、body会继承定义在html的样式

4、用-webkit-text-size-adjust不要定义成可继承的或全局的

(三)outline:none(1)在pc端为a标签定义这个样式的目的是为了取消ie浏览器下点击a标签时出现的虚线。ie7及以下浏览器还不识别此属性,需要在a标签上添加hidefocus="true"(2)input,textarea{outline:none}  取消chrome下默认的文本框聚焦样式(3)在移动端是不起作用的,想要去除文本框的默认样式可以使用-webkit-appearance,聚焦时候默认样式的取消是-webkit-tap-highlight-color。看到一些移动端reset文件加了此属性,其实是多余。

(四)webkit-appearance   -webkit-appearance: none;   //消除输入框和按钮的原生外观,在iOS上加上这个属性才能给按钮和输入框自定义样式 。   注意:不同type的input使用这个属性之后表现不一。text、button无样式,radio、checkbox直接消失
(五).-webkit-user-select   -webkit-user-select: none; // 禁止页面文字选择 ,此属性不继承,一般加在body上规定整个body的文字都不会自动调整
(六)-webkit-touch-callout   -webkit-touch-callout:none;  // 禁用长按页面时的弹出菜单(iOS下有效) ,img和a标签都要加
 
 
 

31 生成指定位数随机数

 function getRandom(num){
         let random = Math.floor((Math.random()+Math.floor(Math.random()*9+1))*Math.pow(10,num-1));
         return random
    }
原文地址:https://www.cnblogs.com/it-Ren/p/11703813.html