分页: 8/273 第一页 上页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 下页 最后页 [ 显示模式: 摘要 | 列表 ]
5月21
包管理工具npm和yarn缓存
npm
缓存命令
npm cache 提供了三个命令,分别是npm cache add, npm cache clean, npm cache verify。

npm cache add
官方解释说这个命令主要是 npm 内部使用,但是也可以用来手动给一个指定的 package 添加缓存。(This command is primarily intended to be used internally by npm, but it can provide a way to add data to the local installation cache explicitly.)

npm cache clean
删除缓存目录下的所有数据。从 npm@5 开始,为了保证缓存数据的有效性和完整性,需要加上 --force 参数。

npm cache verify
验证缓存数据的有效性和完整性,清理垃圾数据。

缓存策略
npm 的缓存目录是通过 cache 变量指定的,一般默认是在 ~/.npm 文件夹(Windows 系统在 %AppData%/npm-cache 文件夹),可以执行下面的命令查看

npm config get cache
在 npm@5 以前,每个缓存的模块在 ~/.npm 文件夹中以模块名的形式直接存储,例如 koa 模块存储在 ~/.npm/koa 文件夹中。而 npm@5 版本开始,数据存储在 ~/.npm/_cacache 中,并且不是以模块名直接存放。

npm 的缓存是使用 pacote 模块进行下载和管理,基于 cacache 缓存存储。由于 npm 会维护缓存数据的完整性,一旦数据发生错误,就回重新获取。因此不推荐手动清理缓存,除非需要释放磁盘空间,这也是要强制加上 --force 参数的原因。

目前没有提供用户自己管理缓存数据的命令,随着你不断安装新的模块,缓存数据也会越来越多,因为 npm 不会自己删除数据。

离线安装
npm 提供了离线安装模式,使用 --offline, --prefer-offline, --prefer-online 可以指定离线模式。

–prefer-offline / --prefer-online
“离线优先/网络优先”模式。

如果设置为 --prefer-offline 则优先使用缓存数据,如果没有匹配的缓存数据,则从远程仓库下载。

如果设置为 --prefer-online 则优先使用网络数据,忽略缓存数据,这种模式可以及时获取最新的模块。

–offline
完全离线模式,安装过程不需要网络,直接使用匹配的缓存数据,一旦缓存数据不存在,则安装失败。

yarn
缓存命令
yarn cache 提供了三个命令,分别是yarn cache ls, yarn cache dir, yarn cache clean。

yarn cache ls
列出当前缓存的包列表。

yarn cache dir
显示缓存数据的目录。

yarn cache clean
清除所有缓存数据。

缓存策略
官方文档没有详细介绍缓存策略,不过进入缓存目录也可以看出一些端倪。在 ~/Library/Caches/Yarn 文件夹中,每个缓存的模块被存放在独立的文件夹,文件夹名称包含了模块名称、版本号等信息。

离线安装
yarn 默认会使用 “prefer-online” 的模式,也就是先尝试从远程仓库下载,如果连接失败则尝试从缓存读取。yarn 也提供了 --offline 参数,即通过 yarn add --offline 安装依赖。

另外 yarn 还支持配置离线镜像,通过以下命令设置离线缓存仓库。具体细节参照官方博客《Running Yarn offline》。

yarn config set yarn-offline-mirror ./npm-packages-offline-cache
5月21

js emoji表情长度判断

11:31大前端  From: 本站原创
[codes=c#]
1、需求:输入框长度限制为10个字符,包括表情。超出长度提示。

注:iPhone手机自定义的表情,有四个小人的,三个小人的,主要是长度还都不一样。有的表情可能一个就超出了长度限制(10),比如?‍?‍?‍?这个表情长度为11,当然我这个长度设置的比较小,可以随意设置。

查阅资料的过程中发现了lodash可以处理数组,并且可以处理表情。

console.log(_.toArray('12?').length); // --> 3);
这样的话就能符合我截取的条件了。判断如果数组的某一个长度超出我的限制长度,就截取数组。

本来这样就可以了,但是就为了转这个引入一个文件,也不合适。于是我就把源码里面的一些符合我的需要的内容摘出来。

let rsAstralRange = '\\ud800-\\udfff',
    rsZWJ = '\\u200d',
    rsVarRange = '\\ufe0e\\ufe0f',
    rsComboMarksRange = '\\u0300-\\u036f',
    reComboHalfMarksRange = '\\ufe20-\\ufe2f',
    rsComboSymbolsRange = '\\u20d0-\\u20ff',
    rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange;
let reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');

let rsFitz = '\\ud83c[\\udffb-\\udfff]',
    rsOptVar = '[' + rsVarRange + ']?',
    rsCombo = '[' + rsComboRange + ']',
    rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
    reOptMod = rsModifier + '?',
    rsAstral = '[' + rsAstralRange + ']',
    rsNonAstral = '[^' + rsAstralRange + ']',
    rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
    rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
    rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
    rsSeq = rsOptVar + reOptMod + rsOptJoin,
    rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
let reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');

export function toArray (val) { // 字符串转成数组
    return hasUnicode(val)
        ? unicodeToArray(val)
        : asciiToArray(val);
}

export function hasUnicode (val) {
    return reHasUnicode.test(val);
}

export function unicodeToArray (val) {
    return val.match(reUnicode) || [];
}

export function asciiToArray (val) {
    return val.split('');
}

是的,一大堆正则。看着就头疼。这个方法可以满足,把表情转成数组中的一份子。这样的话,我们只用判断数组就好了。
然后根据得到的数组,去挨个判断每一个的长度;代码如下:
let strarr = utils.toArray(val);
let str = '', strlen = 0, num = 0, lastarr = [];
for (let i = 0;i < strarr.length;i++) {
    strlen += strarr[i].length; // 数组中每一个字符的长度相加
    if (strlen > this.limit) { // 如果长度大于限制
        num = i; // 记录下到第几个开始超出限制
        lastarr = strarr.slice(0, this.limit); // 取出限制内的数组
        this.$toast('长度超出了');
        break; // 退出循环
        // return;
    }
}
if (strlen > this.limit) { // 如果输入的第一个数长度大于限制的表情
    for (var j = 0;j < num;j++) {
        str += lastarr[j]; // 取出限制内的数组的字符
    }
    this.currentValue = str;
}

其实这块也可以封装一个方法调用。
[/codes]
5月7
有后台的,npm组件的,基于ts的,集成单元测试的,更多可git上撸一下
点击在新窗口中浏览此图片
https://github.com/typescript-project

5月4

20200501

20:45tommy的掰活  From: 本站原创
这是一个很充实的假期,小姨子出嫁啦,希望疫情早日结束,一切好起来,也希望妈妈的腿脚也早日利索起来,恩,加油?
4月27

vue中使用高德地图

09:26大前端  From: 本站原创
高德的jsapi v2.0已经新鲜出炉,可以耍一耍:https://lbs.amap.com/api/jsapi-v2/summary


别用三方的,例如vue-amap,elementui的确不错,这element的高德封装就是一坨翔



入门:https://lbs.amap.com/api/jsapi-v2/guide/abc/load

需要注意的是移动端的点击事件 是 touch,而不是click,被坑了几个小时,

https://www.cnblogs.com/xiaomg/articles/10432907.html
4月27
移动的端的1px,你懂的,这个是真的,挺好用的
[codes=c#]
.border(@t:1px, @r:1px, @b:1px, @l:1px, @radius:5px,@style:solid, @color:#D1D1D1){
    position: relative;
    &:before {
        content: "";
        box-sizing: border-box;
        position: absolute;
        width: 200%;
        height: 200%;
        left: 0;
        top: 0;
        -webkit-transform: scale(0.5);
        -webkit-transform-origin: 0 0;
        transform: scale(0.5);
        transform-origin: 0 0;
        border-style: @style;
        border-color: @color;
        border-top-width: @t;
        border-bottom-width: @b;
        border-left-width: @l;
        border-right-width: @r;
        border-radius:@radius;
    }
}
[/codes]

使用
[codes=c#]
.test {
>i {
     // 下边1px
     .border(0,0,1px,0,0);
  }
}
[/codes]
4月27
CSS的同理也可以撸一个
[codes=c#]
export default function remoteLoadJS (url, hasCallback) {
  return createScript(url)
  /**
   * 创建script
   * @param url
   * @returns {Promise}
   */
  function createScript (url) {
    let scriptElement = document.createElement('script')
    document.body.appendChild(scriptElement)
    let promise = new Promise((resolve, reject) => {
      scriptElement.addEventListener('load', e => {
        removeScript(url)
        if (!hasCallback) {
          resolve(e)
        }
      }, false)

      scriptElement.addEventListener('error', e => {
        removeScript(url)
        reject(e)
      }, false)

      if (hasCallback) {
        window.____callback____ = function () {
          resolve()
          window.____callback____ = null
        }
      }
    })

    if (hasCallback) {
      url += '&callback=____callback____'
    }

    scriptElement.src = url

    return promise
  }

  /**
   * 移除script标签
   * @param scriptElement script dom
   */
  function removeScript (src) {
    var scripts = document.getElementsByTagName("script");
    for (var i = 0; i < scripts.length; i++) {
        if (scripts[i] && scripts[i].src && scripts[i].src.indexOf(src) != -1) {
            scripts[i].parentNode.removeChild(scripts[i]);
        }
    }
  }
}

[/codes]
4月15

监视滑动事件touch event

17:56大前端 » vue.js  From: 本站原创
当然可以用vue-tap,vue-touch
这里讲的是原生的
给dom加个ref,例如demo
[codes=c#]
data() {
  return {
      touchDistance: 40 // 滑动的距离
  }
},
mounted(){
   this.handleTouchEvent(this.$refs.demo)
},
methods: {
    handleTouchEvent(el) {
        el.addEventListener('touchstart', this.touchStartEvent true)
        el.addEventListener('touchend', this.touchEndEvent, true)
        el.addEventListener('touchmove', this.touchMoveEvent, true)
    },
    removeEventListener(el) {
        el.removeEventListener('touchstart', this.touchStartEvent true)
        el.removeEventListener('touchend', this.touchEndEvent, true)
        el.removeEventListener('touchmove', this.touchMoveEvent, true)
    },
    touchStartEvent(event) {
        event.stopPropagation()
        this.clientY = event.changedTouches[0].clientY
    },
    touchEndEvent(event) {
        event.stopPropagation()
        const diffY = event.changedTouches[0].clientY - this.clientY
        if (diffY > this.touchDistance) {
            // 下划
        }
        if (diffY < -1 * this.touchDistance) {
            // 上划
        }
    },
    touchMoveEvent(event) {
        event.preventDefault()
    }
},
beforeDestroy() {
    this.removeEventListener(this.$refs.demo)
}
[/codes]
4月15
[codes=c#]
addEventListener() 事件监听
removeEventListener() 移除事件监听
element.addEventListener(event, function, useCapture);
[/codes]
第一个参数是事件的类型 (如 “click” ).

第二个参数是事件触发后调用的函数

第三个参数是个布尔值。默认是false(冒泡阶段执行)true(捕获阶段产生)

事件传递有两种方式:冒泡与捕获。事件是先捕获再冒泡的

冒泡阶段,内部元素的事件会先被触发,然后再触发外部元素。即: p 元素的点击事件先触发,然后会触发 div 元素的点击事件。
捕获阶段,外部元素的事件会先被触发,然后才会触发内部元素的事件。即: div元素的点击事件先触发 ,然后再触发 p元素的点击事件。

[codes=c#]

    

some text... ...




[/codes]
4月10

some codes base  on vue2.6+

21:22大前端 » vue.js  From: 本站原创
[codes=c#]
mounted () {
    window.addEventListener('resize', this.resizeHandler);
},
beforeDestroy () {
    window.removeEventListener('resize', this.resizeHandler);
}

mounted () {
  window.addEventListener('resize', this.resizeHandler);
  this.$on("hook:beforeDestroy", () => {
    window.removeEventListener('resize', this.resizeHandler);
  })
}
[/codes]

[codes=c#]

[/codes]

[codes=c#]


[/codes]

[codes=c#]

代替

[/codes]

[codes=c#]
:key 是个好东西
[/codes]
Tags: , , ,
分页: 8/273 第一页 上页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 下页 最后页 [ 显示模式: 摘要 | 列表 ]