hogo呀

hogo呀 查看完整档案

成都编辑西南科技大学  |  电子商务 编辑科来  |  前端 编辑 hogozhang.github.io/code/ 编辑
编辑

登东皋以舒啸,濯清流而赋诗

个人动态

hogo呀 回答了问题 · 2020-12-08

el-input 怎么实现动态禁用

把聚焦事件改为点击事件,然后判断禁用状态,如果是禁用状态就取消禁用并聚焦,如果已经聚焦则不做处理

关注 5 回答 3

hogo呀 发布了文章 · 2020-12-08

github,gitlab提交格式

主要用于规范自己平时提交代码的格式,避免凌乱难以追溯
1.规范内容
  • [x] 组成:类型 - 模块 - 内容
  • [x] 示例:‘add-警报分析-列表增加排序功能’
2.规范类型字典
{
    add :"新增",
    update:"修改",
    delete:"删除",
    fix:"bug修复",
    docs:"文档修改",
    refctor:"重构",
    perf:"性能优化"
}
3.规范补充
  • 类型不包含但不仅限于(add,update,delete)
  • 内容部分尽量不超过20个字符
  • 超过一个大的代码功能,分多次提交

查看原文

赞 0 收藏 0 评论 0

hogo呀 发布了文章 · 2020-12-07

js表单验证(2):ipv4,ipv6,多个ip校验指令

场景

input或者textarea输入提交时校验是否内容是ipv4或者ipv6格式,多个ip用指定符号隔开

example

angularjs指令实现

1.用法
<input type="text" check-ip ng-model="ipValue"></input>
2.源码
app.directive('checkIp', function () {
  return {
    restrict: 'A',
    require: 'ngModel',
    link(scope, ele, attrs, ctrl) {
      function ipToArrayHandel(string) {
        if (!string) return [];
        let splitStr = ',';
        let temp = string.trim().split(splitStr);
        let result = temp.filter(str => str !== '')
          .map(str => str.trim());
        return result;
      }
      function ipValidator(ip) {
        if (!ip) return false;
        let reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])((\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}|(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){5})$/;
        let regIpv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
        let temp = ipToArrayHandel(ip);
        let passCheck = false;
        //格式校验
        for (let i = 0; i < temp.length; i++) {
          passCheck = (reg.test(temp[i]) || regIpv6.test(temp[i]));
          if (!passCheck) break;
        }
        //是否重复
        passCheck = passCheck && (temp.length === _.uniq(temp).length);

        return passCheck;
      }
      ctrl.$validators.checkIp = function (modelVal, viewVal) {
        if(attrs['required']==undefined&&(!viewVal)){
          return true
        }else{
          return ipValidator(viewVal);
        }
      }
    }
  }
});

vuejs指令实现

1.用法
<el-form-item label="ip:" :label-width="formLabelWidth" prop="ip"  :rules="[{ required: true, validator:validateIps, trigger: 'blur' }]">
    <el-input v-model="ipValue" autocomplete="off"></el-input>
</el-form-item>
2.源码
validateIps(rule, value, callback)  {
    let reg = /^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$/;
    let regIpv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
    let valdata = value.split(',');
    let isCorrect = true;
    if (valdata.length) {
        for (let i = 0; i < valdata.length; i++) {
            if (reg.test(valdata[i]) == false && regIpv6.test(valdata[i]) == false) {
                isCorrect = false;
            }
        }
    }
    F
    if (value == '') {
        return callback(new Error('请输入iP地址'));
    } else if (!isCorrect) {
        callback(new Error('请输入正确对ip地址'));
    } else {
        callback()
    }
}
查看原文

赞 0 收藏 0 评论 0

hogo呀 发布了文章 · 2020-12-07

js表单验证(1):域名校验指令

angularjs实现

app.directive('checkDomainCommon', function () {
  return {
    restrict: 'A',
    require: 'ngModel',
    link(scope, ele, attrs, ctrl) {

      ctrl.$validators.checkDomainCommon = function (modelVal) {
        // reg为域名的正则的正则
        let reg =/^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][--a-zA-Z0-9]{0,62})+\.?/
        if (attrs['required'] === undefined || attrs['required'] === false) {
          return true
        }
        else if(!modelVal){
          return false;
        }else {
          //加入输入类型判断,防止错误的将指令绑定在如number类型的输入框上
          if(typeof modelVal !== 'string'){
            console.error('the type of input value is not string,can not check domain format!');
            return false;
          }
          // 系统中现有用逗号分隔的,和分号分隔的做兼容。都是英文符号
          // 中横线隔开的是domain范围,也需要验证是否符合输入规范
          let domainArr = attrs['separatorReg']? modelVal.split(new RegExp(attrs['separatorReg'])):modelVal.split(/,|;|-/);
          let domain = "";
          let isOk = false;
          for (let i = 0; i < domainArr.length; i++) {
            domain = domainArr[i];
            if (reg.test(domain)) {
              isOk = true;
            } else {
              // 只要一个不合符,未通过验证,直接break
              isOk = false;
              break;
            }
          }

          return isOk;
        }
      }
    }
  }
});

vue实现

import Vue from 'vue'

const domianReg = '';

// 注册一个全局自定义指令 `v-checkDomain`
Vue.directive('checkDomain', {
    // 当被绑定的元素插入到 DOM 中时……
    inserted: function (el, binding, vNode) {
        el.addEventListener('keyup', function (event) {
            // 首先去除已有样式

            //removeErrorStyle
            
            // 判断是否是否必填
            let isRequired = binding.value.required
            if (isRequired) {
                if (!el.value || el.value === '') {
                    //do something with error 
                }
            }

            // 判断正则
            let regex = binding.value.regex
            if (regex === 'IpRegex') {
                if (!el.value.match(domainReg)) {
                    //do something with error 
                }
            } else if (!el.value.match(regex)) {
                //do something with error 
            }
        })
    }
})

// 注册一个全局自定义指令 `v-checkSubmit`
Vue.directive('checkSubmit', {
    // 当被绑定的元素插入到 DOM 中时……
    inserted: function (el, binding, vNode) {
        el.addEventListener('click', function (event) {
            let elements = document.getElementsByClassName('v-check')
            var evObj = document.createEvent('Event')
            evObj.initEvent('keyup', true, true)
            for (let element of elements) {
                element.dispatchEvent(evObj)
            }
            let errorInputs = document.getElementsByClassName('errorClssDom');
            if (errorInputs.length === 0) {
                vNode.context.submit();
            }
        })
    }
})
查看原文

赞 0 收藏 0 评论 0

hogo呀 发布了文章 · 2020-12-04

loadash.js源码学习笔记(2)

个人记忆

lodash.js->Array->difference

用法

返回一个去重后的数组,每个值不包含在其他数组参数中。结果值的顺序是由第一个数组中的顺序确定。

例子

    _.difference([1,2,3],[3],[1,5])
    //==>[2];

源码理解

    difference(array, values, iteratee, comparator) {
      var index = -1,
          includes = arrayIncludes,
          isCommon = true,
          length = array.length,
          result = [],
          valuesLength = values.length;

      if (!length) {
        return result;
      }
      if (iteratee) {
        values = arrayMap(values, baseUnary(iteratee));
      }
      if (comparator) {
        includes = arrayIncludesWith;
        isCommon = false;
      }
      else if (values.length >= LARGE_ARRAY_SIZE) {
        includes = cacheHas;
        isCommon = false;
        values = new SetCache(values);
      }
      outer:
      while (++index < length) {
        var value = array[index],
            computed = iteratee ? iteratee(value) : value;

        if (isCommon && computed === computed) {
          var valuesIndex = valuesLength;
          while (valuesIndex--) {
            if (values[valuesIndex] === computed) {
              continue outer;
            }
          }
          result.push(value);
        }
        else if (!includes(values, computed, comparator)) {
          result.push(value);
        }
      }
      return result;
    }


    1.核心代码
      outer:
      while (++index < length) {
        var value = array[index],
            computed = iteratee ? iteratee(value) : value;

        if (isCommon && computed === computed) {
          var valuesIndex = valuesLength;
          while (valuesIndex--) {
            if (values[valuesIndex] === computed) {
              continue outer;
            }
          }
          result.push(value);
        }
        else if (!includes(values, computed, comparator)) {
          result.push(value);
        }
      }
      return result;
      `思路:`将除array之外的数组参数合并去重,得到values,再使用includes方法,判断array中的元素是否存在于values中,若不存在即将value放进新数组result中,最后返回result。

延申

假设有一需求,重点展示本月在本年没有出现过的新出现的天气类型:
difference(month12,month1,month2.....);
查看原文

赞 0 收藏 0 评论 0

hogo呀 发布了文章 · 2020-12-03

loadash.js源码学习笔记(1)

lodash.js->Array->chunk

用法

将数组拆分为等长的若干个新数组组成的二维数组,如果无法被分割成全部都等长的新数组,那么最后剩下的数组元素将组成最后一个数组。

例子

    _.chunk([1,2,3,4,5,6],3)
    //==>[[1,2,3],[4,5,6]];
    //3为等长的长度参数,取消参数则默认长度为1

源码理解

    function chunk(array, size, guard) {
      if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
        size = 1;
      } else {
        size = nativeMax(toInteger(size), 0);
      }
      var length = array ? array.length : 0;
      if (!length || size < 1) {
        return [];
      }
      var index = 0,
          resIndex = 0,
          result = Array(nativeCeil(length / size));

      while (index < length) {
        result[resIndex++] = baseSlice(array, index, (index += size));
      }
      return result;
    } 

    `guard意思是守卫`

    1.直接看核心代码
     var index = 0,
         resIndex = 0,
         result = Array(nativeCeil(length / size));

      while (index < length) {
        result[resIndex++] = baseSlice(array, index, (index += size));
      }
      return result;
      (a).初始化原数组下标index,新二维数组下标resIndex,新二维数组result,并占位
      (b).无限循环剪切index开始,index+size结束的数组元素并填入result,直到末位

延申

Ceil(length/size)从0开始向上取整,完美的得到了新数组的下标

取2数组前三组成新数组
return _.chunk(a,3).concat(_chunk(b,3));
查看原文

赞 0 收藏 0 评论 0

hogo呀 收藏了文章 · 2020-07-13

关于修改DOM是异步还是同步的问题

@bf 同学

本篇文章不是笔记也不是心得,而是关于一个问题的讨论,问题最初出现于https://segmentfault.com/q/1010000005630545?_ea=903562

由于 @bf 同学不方便加QQ/微信,而这个问题又比较大,在问答评论里不好描述清楚,so,趁着周末专门写了一篇文章来回应 @bf 同学

@bf 同学,提到了一个观点:对DOM的修改永远是异步的

当时就震惊到我了(可能技术不达标,少见多怪的缘故,哈哈)

说实话,干了好几年开发,第一次明确地听到有人这样说,根据自己看的书及一些javascript编程经验来说,起初我认为是错误的。

然后看了看 @bf 同学的回复,能自圆其说,还说的头头是道,所以我真的以为对DOM的修改永远是异步的是正确的。然后怀着震惊的心情(因为跟经验相违背),还写了一篇博客记录http://www.liyanshan.com/2016/06/09/%E5%AF%B9DOM%E7%9A%84%E4%BF%AE%E6%94%B9%E6%B0%B8%E8%BF%9C%E9%83%BD%E6%98%AF%E5%BC%82%E6%AD%A5%E7%9A%84/

经过这么些天的发酵和消化,觉得对这个观点又回到了最初的认识(即这个观点是错的)。

还请 @bf 同学跟我多多探讨 !

关于javascript修改dom是异步还是同步的问题:

先来看代码:

<ul>
    <li id="i0"></li>
    <li id="i1"></li>
    <li id="i2"></li>
    <li id="i3"></li>
    <li id="i4"></li>
</ul>
<ul id="newEle"></ul>

<script>
 for(var i = 0;i<5;i++){
    var item = document.getElementById('i'+i);
    item.innerHTML = i;
 }
 var newEle = document.getElementById('newEle');
 for(i=0;i<5;i++){
    var li = document.createElement("li");
    li.innerHTML = i;
    newEle.appendChild(li);
 }
</script>  

上述代码的结果完全就是同步的表现,如果是异步的话,毫无疑问,第一个ul下的li每个内容都应该是5,第二个也应该是5。

这是数学中的反证法。即一个命题,哪怕我找出一个特例(何况我能找出很多例子)能推翻这个命题,那么这个命题就不成立。

@bf 同学可能会说了,他也用反证法,比如script标签的加载,来证明DOM修改是异步的

但是这个特例的问题在于:

把下载的异步性当成了DOM修改的异步性

script标签加载是异步的,因为要走网络(比如走网络的ajax和图片下载等都是异步的,当然ajax也可以写成同步的),也就是说,浏览器开了一个线程下载要用的script,但是马上返回(交给HTTP请求线程就不管了,请求结束,请求线程会把结果放入事件队列里),接着执行或下载其他部分。其实这个问题我在引起这个讨论的问题上已经回答了(可能回答的没有那么清楚)。

然后又陆陆续续地看了一些书,查了一些资料,问了一些大牛,越来越坚信DOM修改是同步的

JavaScript异步编程第一章 - 异步的I/O函数(1.2.1)

图片描述

这个也符合我最初跟 @bf 同学的解释:修改DOM是同步的,但是渲染是异步的。因为JavaScript引擎线程跟GUI渲染线程是互斥的,即我执行的时候,你就靠边站,我执行完你才能执行

详见我2014年写的一篇关于异步的文章(当时就是记录一下心得与笔记,也不会自己搭博客,也不会MD,所以请 @bf 同学凑合看)http://blog.sina.com.cn/s/blog_6fd55a970102v64x.html

在群里提问

这个其实就相当于回答了js是同步修改的。。因为这是三个异步函数!

图片描述

@bf 同学在后面的回复中,提到了一篇文章https://leozdgao.me/why-dom-slow/,额,我看了看这篇文章,发现其实我今年年初就看过了,当时貌似是用浏览器重排和重绘搜索到的。。

这篇文章主要是讲 重排和重绘及性能优化一类的知识。

@bf 同学可能受到这句话的影响:

一般情况下,浏览器的layout是lazy的,也就是说:在js脚本执行时,是不会去更新DOM的,任何对DOM的修改都会被暂存在一个队列中,在当前js的执行上下文完成执行后,会根据这个队列中的修改,进行一次layout。

这个其实说明不了修改DOM永远是异步的,这个是JavaScript引擎实现层面上的知识,是对js修改DOM的优化,它放入的队列其实不是事件队列,如果放到了事件队列中,才是异步的。。C++实现一个队列是何其简单啊!js实现队列更简单!只是实现层面的东西,对程序猿都是透明的。。所以没啥可说的。只能帮助我们理解重排和重绘的机制,而不能得出修改DOM永远是异步的结论。。

查看原文

hogo呀 回答了问题 · 2020-07-13

解决不懂就要问,浏览器到底是什么时候更新dom?

DOM结构的修改是同步完成的,dom的实际效果修改或者说渲染是异步的,个人认为是同步js代码执行完毕和异步队列执行之前的中间段进行更新

关注 6 回答 3

hogo呀 回答了问题 · 2020-05-14

echarts 设置yAxis的type属性为log之后无法显示的问题,控制台也不报错

请问你解决了吗,我也遇到相同的问题

关注 2 回答 2

hogo呀 回答了问题 · 2019-10-15

解决为什么计算机能读懂机器码?

5的二进制是0101?

关注 18 回答 13

认证与成就

  • 获得 16 次点赞
  • 获得 82 枚徽章 获得 3 枚金徽章, 获得 20 枚银徽章, 获得 59 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2017-08-07
个人主页被 2.1k 人浏览