KieSun / today-i-learned

记录今天学了什么
509 stars 34 forks source link

2019.7.22 - 7.28 中你学到什么? #3

Open KieSun opened 5 years ago

xuhongbo commented 5 years ago

mac环境下,命令行杀死特定node服务

由于在前端开发的时候,几个项目来回切换,难免会有端口占用的情况,之前的做法都是手动查找,由于比较麻烦,所以自己搞了个命令,一行搞定

lsof -i tcp:8080 | grep LISTEN | awk '{print $2}'| awk -F"/" '{ print $1 }' | xargs kill -9

上面举例的是杀死 8080 端口,有更好的方式,欢迎讨论

KieSun commented 5 years ago

mac环境下,命令行杀死特定node服务

由于在前端开发的时候,几个项目来回切换,难免会有端口占用的情况,之前的做法都是手动查找,由于比较麻烦,所以自己搞了个命令,一行搞定

lsof -i tcp:8080 | grep LISTEN | awk '{print $2}'| awk -F"/" '{ print $1 }' | xargs kill -9

上面举例的是杀死 8080 端口,有更好的方式,欢迎讨论

很实用,可以做成 npm 命令,然后传参替换端口号

xnng commented 5 years ago

@KieSun

好像已经有人做了,我试了下,在 windows 环境下第二个库是可以用的,第一个库无效。 image

2019-07-22_14-18-27

bytemain commented 5 years ago

Windows 下关于端口被占用而又找不到被占用的程序的解决办法

之前用 SSR 的时候,有时候开机提示 1080 端口被占用,查看这个端口确实没被占用,遂不了了之。 今天用 WSL , 又出现了这个问题,一直报 3000 端口被占用,百度了很久,执行下面这句即可。

netsh winsock reset 

知识点分析:

netsh 是从windows xp sp2开始提供的功能强大的网络配置命令行工具。 是一个能够通过命令行操作几乎所有网络相关设置的接口,比如设置IP,DNS,网卡,无线网络等。

winsock是Windows网络编程接口,winsock工作在应用层,它提供与底层传输协议无关的高层数据传输编程接口。reset是对Winsock的重置操作。当执行完winsock的命令重启计算机后,需要重新配置IP等网络配置信息。 netsh winsock reset 是把它恢复到默认状态。作用是重置 Winsock 目录。如果一台机器上的Winsock协议配置有问题的话将会导致网络连接等问题,可通过使用netsh winsock reset命令来重置Winsock目录尝试恢复。这个命令可以重新初始化网络环境,以解决由于软件冲突、病毒原因造成的参数错误问题。例如电脑突然出现成功连接网络但不能上网、网络受限,打开网页出现显示问题,无法自动获取IP地址或指定IP地址仍无数据包传输,使用蓝牙适配器传输文件时提示“使用了与请求的协议不兼容的地址”等等网络协议应用相关故障。

输入netsh winsock reset命令,有何副作用

netsh winsock reset这个命令可以重新初始化网络环境,以解决由于软件冲突、病毒原因造成的参数错误问题。当执行完winsock的命令重启计算机后,需要重新配置IP。局域网的话需要DNS选择一下,另外因机而异可能会断网或网速变慢,这个就需要继续再进行解决了。

soraliu commented 5 years ago

Linux下通过命令行替换文本


# 将wxml文件的i标签替换为text
grep '<i ' -rl . --include='*.wxml' --exclude-dir=node_module --exclude-dir=dist | xargs sed -i -e 's/<i /<text /g'
grep '</i>' -rl . --include='*.wxml' --exclude-dir=node_module --exclude-dir=dist | xargs sed -i -e 's/<\/i>/<\/text>/g'
KieSun commented 5 years ago

@lengthmin 感谢分享!提出问题、问题的原因以及解决办法是一件很好的事情。 @lovesora 感谢分享!

erdong0604 commented 5 years ago

图片懒加载

<ul>
    <li><img src="./img/default.png" data="./img/1.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/2.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/3.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/4.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/5.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/6.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/7.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/8.png" alt=""></li>
</ul>
let imgs =  document.querySelectorAll('img')
// 窗口可视区高度
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// img 距离窗口可视区顶部的距离 imgs[i].getBoundingClientRect().top
function lazyLoadImg () {
    for (let i = 0; i < imgs.length; i ++) {
        if((imgs[i].getBoundingClientRect().top + imgs[i].height)>=0&&imgs[i].getBoundingClientRect().top < clientHeight ){
            imgs[i].src = imgs[i].getAttribute('data')
        }
    }      
}
window.addEventListener('scroll', lazyLoadImg);
princewck commented 5 years ago

@erdong0604 可以在js里预先加载图片,防止直接替换src图片在下载过程中闪白一下的问题

图片懒加载

<ul>
  <li><img src="./img/default.png" data="./img/1.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/2.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/3.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/4.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/5.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/6.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/7.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/8.png" alt=""></li>
</ul>
let imgs =  document.querySelectorAll('img')
// 窗口可视区高度
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// img 距离窗口可视区顶部的距离 imgs[i].getBoundingClientRect().top
function lazyLoadImg () {
 for (let i = 0; i < imgs.length; i ++) {
     if((imgs[i].getBoundingClientRect().top + imgs[i].height)>=0&&imgs[i].getBoundingClientRect().top < clientHeight ){
        const imgUrl = imgs[i].getAttribute('data');
        _preloadImg(imgUrl, function () {
           imgs[i].src = imgUrl;
        }, function () {
           imgs[i].src = '/img/loaderror.jpg';
        });
     }
 }      
}

function _preloadImg(url, callback, onerror) {
  const img = new Image();
  img.src = url;
  img.onload = function () {
    if (callback) {
      callback();
    }
  }
  img.onerror = function () {
    if (onerror) {
      onerror();
    }
  }
}
window.addEventListener('scroll', lazyLoadImg);
princewck commented 5 years ago

用gitHooks约束 commit message

之前有用过,这周看 vue-cli 源码发现了如下的 verify commit message 逻辑,觉得挺实用的,特别适合对项目有追求的强迫症患者或者多人合作的项目约束风格的统一。

const chalk = require('chalk')  // eslint-disable-line
const msgPath = process.env.GIT_PARAMS
const msg = require('fs').readFileSync(msgPath, 'utf-8').trim()

const commitRE = /^(v\d+\.\d+\.\d+(-(alpha|beta|rc.\d+))?)|((revert: )?(feat|fix|docs|style|refactor|perf|test|workflow|ci|chore|types)(\(.+\))?!?: .{1,50})/

if (!commitRE.test(msg)) {
  console.log()
  console.error(
    `  ${chalk.bgRed.white(' ERROR ')} ${chalk.red(`invalid commit message format.`)}\n\n` +
    chalk.red(`  Proper commit message format is required for automated changelog generation. Examples:\n\n`) +
    `    ${chalk.green(`feat(compiler): add 'comments' option`)}\n` +
    `    ${chalk.green(`fix(v-model): handle events on blur (close #28)`)}\n\n` +
    chalk.red(`  See .github/COMMIT_CONVENTION.md for more details.\n`) +
    chalk.red(`  You can also use ${chalk.cyan(`npm run commit`)} to interactively generate a commit message.\n`)
  )
  process.exit(1)
}

要使上面的逻辑生效,我们还需要安装 yorkie

npm install yorkie --save-dev

然后在项目的 package.json 中加入以下配置

{
  "gitHooks": {
    "commit-msg": "node scripts/verifyCommitMessage.js"
  },
}

到此我们就配置完成了

脚本的作用是限制 commit 信息必须是 feat|fix|docs|style|refactor|perf|test|workflow|ci|chore|types打头,或者版本号开头,看vue-cli的提交记录更直观 image

配置完成后我们要是不按照约定的格式书写commit message,提交就会被挡住,看下图: image

相关原理可以参看 Git hooks,我们引入的第三方库安装后会在仓库的.git/hooks目录下为我们设置一些hooks脚本,这些hooks脚本的任务是接管我们的node或shell脚本,使其在正确的时机执行,为我们隐藏了直接自己在./git/hooks路径下编写hook脚本的复杂性

你还可以指定在commit前做一些预处理(pre-commit),比如执行eslint,对git提交做进一步的规范和约束,详细用法请阅读文档。

类似的工具还有 husky

erdong0604 commented 5 years ago

@erdong0604 可以在js里预先加载图片,防止直接替换src图片在下载过程中闪白一下的问题

图片懒加载

<ul>
    <li><img src="./img/default.png" data="./img/1.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/2.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/3.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/4.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/5.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/6.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/7.png" alt=""></li>
    <li><img src="./img/default.png" data="./img/8.png" alt=""></li>
</ul>
let imgs =  document.querySelectorAll('img')
// 窗口可视区高度
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// img 距离窗口可视区顶部的距离 imgs[i].getBoundingClientRect().top
function lazyLoadImg () {
 for (let i = 0; i < imgs.length; i ++) {
     if((imgs[i].getBoundingClientRect().top + imgs[i].height)>=0&&imgs[i].getBoundingClientRect().top < clientHeight ){
        const imgUrl = imgs[i].getAttribute('data');
        _preloadImg(imgUrl, function () {
           imgs[i].src = imgUrl;
        }, function () {
           imgs[i].src = '/img/loaderror.jpg';
        });
     }
 }      
}

function _preloadImg(url, callback, onerror) {
  const img = new Image();
  img.src = url;
  img.onload = function () {
    if (callback) {
      callback();
    }
  }
  img.onerror = function () {
    if (onerror) {
      onerror();
    }
  }
}
window.addEventListener('scroll', lazyLoadImg);

@princewck good

KRISACHAN commented 5 years ago

2019/7/12份学习

无loop生成指定长度的数组


const List1 = len => ''.padEnd(len, ',').split('.')

const List2 = len => [...new Array(len).keys()]

shfshanyue commented 5 years ago

2019/07/22

01 graphql 中多级分页查询时的 N+1 问题

此处只能在客户端避免多层分页查询,而当有恶意查询时会加大服务器压力。可以使用 Hash Query 避免此类问题,避免暴露原始 Query,同时也在生产环境禁掉 introspection

{
  users (page: 1, pageSize: 3) {
    id
    todos (page: 1, pageSize: 3) {
      id 
      name
    } 
  }
}
select id from users limit 3

select id, name from todo where user_id = 1 limit 3
select id, name from todo where user_id = 2 limit 3
select id, name from todo where user_id = 3 limit 3

记录

02 在前端中把 gql 统一管理减小打包体积

准确说,已经把 gql 统一管理为 query.gql,通过 loader 引入,会被打入 common.js。 而在个别页面又单独通过 graphql-tag 引入,被按需加载打包,而此时 graphql-tag 又依赖 graphql,gql 统一管理后,此时的两个模块的依赖也就没有了。

通过 webpack 分析,gzip 后的总体积变化: 191.64KB -> 176.51KB,体积缩减还是比较可观的。

优化记录

03 获取当前 commit hash

可以通过 npm scripts 注入到项目中,方便集成到 sentrylogger 等工具组件中

git rev-parse --verify HEAD  | cut -c 1-8

后来找到更简单的命令 git rev-parse --short HEAD

2019/07/23

01 本地更好的流式日志格式化

服务器端的日志很重要,一般设置为 jsonl 格式,方便在 elk 上查询或者使用 spark 分析。而在本地调试时就不是很直观了,而日志又是 stream 的数据。此时可以使用 jq 对日志进行美化

# 实时查看日志,并且只关注 message 字段
tail -f logs/db.log | jq '{message}'

此时你不仅有了更好的可视化,而且只需要关注你自己关心的字段就可以了,体验很棒

02 Intersection Observel 做路由页面预加载与图片懒加载

由于我的网站使用了 next.js 的技术栈,最近对 next 升级到了 v9,对 next 一直有所关注。在今天读了 Next.9 features,其中有一个点:

Next.js 9 will automatically prefetch components as they appear in-viewport.

其中原理便是使用 Intersection Observel 来监听元素是否出现在当前可视窗口内。 Next.js 可以对新的页面资源做懒加载,举一反三,我们也可以使用它对图片做懒加载。

03 了解一个 APP 从开发到盈利所经历的事

2019/07/24

01 在 React 中使用 React.Fragment 或者 <></> 包含多个子元素

恩,这个是查看某项目代码时看到的,虽然一直知道了 react 目前已经可以包含多元素,但也没有细究,今天偶然得知,受用很多。

(
  <>
    <td>Hello</td>
    <td>World</td>
  </>
);

02 sar (System Activity Monitor)

sarvmstatiostat 相比,不仅可以实时监控 linux 系统 IO/memory/cpu 等的信息,而且可以 获取一段时间内的系统统计信息,比如他可以获取一天时间内的 CPU 使用率。我也把它记录在了我的博客里

linux 指标监控

03 Apollo Federation & GraphQL Gateway

简而言之,Apollon Federation 可以把多个 graphql service 组合成一个 API Gateway。如果公司的所有业务与微服务都使用了 GraphQL,则它正好可以做一个不错的服务整合,这还挺令人兴奋的。

2019/07/25

总结了LF 与 CRLF 的一篇文章

了解一些底层知识,视野会开阔很多。如本篇文章可以通过系统调用来看换行符到底是什么。

用户增长模型 RARRA

我的理解,用户留存比较重要,应作为着力点

2019/07/26

了解 vuepress 如何写插件,并给我的博客写了一个归档的插件

https://github.com/shfshanyue/blog/blob/master/.vuepress/config.js

2019/07/27

尝试使用 netlify 新建了我的博客

博客地址 https://shanyue.netlify.com/

至于我现在的博客还是使用 hugo 构建,不得不说 hugo 的构建速度真是很快。另外使用自建的 gitlab,gitlab-ci,docker-compose 来做自动部署,不得不说运维这些还是有些成本的。而 netlify 就简单很多了,这些运维工作都不需要你来关心。

云是一种趋势,以后考虑能够 SAAS 化的服务全部 SAAS 化。

graphql-code-generator 自动为前端生成 graphql schema 相对应的 ts 的 type

毫无疑问,前端不用手动配置关于接口的 interface,大大解放了前端的生产力,而且减少了失误率。

2019/07/28

了解关于 IO 复用的几种机制

guanweiwang commented 5 years ago

mac环境下,命令行杀死特定node服务

由于在前端开发的时候,几个项目来回切换,难免会有端口占用的情况,之前的做法都是手动查找,由于比较麻烦,所以自己搞了个命令,一行搞定

lsof -i tcp:8080 | grep LISTEN | awk '{print $2}'| awk -F"/" '{ print $1 }' | xargs kill -9

上面举例的是杀死 8080 端口,有更好的方式,欢迎讨论

我都是全杀 killall node

Flcwl commented 5 years ago

mac环境下,命令行杀死特定node服务

由于在前端开发的时候,几个项目来回切换,难免会有端口占用的情况,之前的做法都是手动查找,由于比较麻烦,所以自己搞了个命令,一行搞定

lsof -i tcp:8080 | grep LISTEN | awk '{print $2}'| awk -F"/" '{ print $1 }' | xargs kill -9

上面举例的是杀死 8080 端口,有更好的方式,欢迎讨论

@xuhongbo awk -F"/" '{ print $1 }' 这部分命令解释一下,没懂

Bulandent commented 5 years ago

Javascript隐式类型转换 https://juejin.im/post/5bc5c752f265da0a9a399a62

[] == ![] // true [] == 0 // true [2] == 2 // true ['0'] == false // true '0' == false // true [] == false // true [null] == 0 // true null == 0 // false [null] == false // true null == false // false [undefined] == false // true undefined == false // false

teachat8 commented 5 years ago

毕业两年我的感悟:

  • 自身的实力最重要,要有一样核心技能,其他方面也要有所涉猎。
  • 公司带给个人的影响是很大的,如果一个公司不愿意培养你,真的不值得去付出。
  • 沟通确实很重要,沟通不明确会导致接下来一系列的问题。
  • 说话是后天锻炼出来的,多和人交流,话到嘴边留三分。
  • 不用讨厌加班,人与人拉开差距就在下班后的几个小时,加班可以学习啊。雷军还说过你拿3000块钱换我一个月的青春,多不划算。
KieSun commented 5 years ago

毕业两年我的感悟:

  • 自身的实力最重要,要有一样核心技能,其他方面也要有所涉猎。
  • 公司带给个人的影响是很大的,如果一个公司不愿意培养你,真的不值得去付出。
  • 沟通确实很重要,沟通不明确会导致接下来一系列的问题。
  • 说话是后天锻炼出来的,多和人交流,话到嘴边留三分。
  • 不用讨厌加班,人与人拉开差距就在下班后的几个小时,加班可以学习啊。雷军还说过你拿3000块钱换我一个月的青春,多不划算。

junglehunter96 commented 5 years ago

今天刷博客的时候看到一个题 :

异步的 Promise的 then 方法的回调是何时被添加到microtasks queue中的?

const pro = new Promise((resolve, reject) => {
    const pro1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(3);
        }, 0);
    });
    resolve(4);
    pro1.then((args) => {
        console.log(args);
    });
});
pro.then((args) => {
    console.log(args);
});

很多人都知道这道题的输出结果是4,3;但是我对题主的这个问题产生了很大的疑问,因为个人并没有着手实现过符合promise A/A+规划的promise,所以每次做这种题都是凭着平时的使用经验,实际上内心虚得很,然后自己查阅了 spec:ECMAScript 2018 Language Specification 根据 spec,如果调用 then 时 promise 是 pending 状态,回调会进入 promise 的 [[PromiseFulfill/RejectReactions]] 列表里;否则会进入 PromiseJobs; PromiseJob 以及 Job Queue 是 ES 中的说法,而 macroTask 和 microTask 是浏览器中的概念,包括 setTimeout 也是宿主环境提供的。因此输出 4 3 是 ECMAScript 和 浏览器两种规范共同约束的结果。PromiseJob 对应浏览器中的一个 microTask.对于调用 then 时 promise 处于 pending 状态,回调函数进入到对应的 reactions 队列中。当该 promise 被 fulfill 或 reject 时,则 flush 对应的 reactions 队列 ,其中的每个 reaction 对应一个 PromiseJob 被按序 enqueue 到 Job Queue如果调用 then 时 promise 处于其他两个状态,Js 引擎就直接 enqueue 一个对应的 PromiseJob 到 Job Queue示例中的代码,在浏览器中如下顺序

0. current cycle of evevt loop start
1. Install Timer,Timer get enqueued
2. Resovle pro, because there is no fulfillReaction binding to pro, do nothing
3. call then() at pro1, because pro1 is pending, add fulfillReaction to pro1
4. call then() at pro, because pro is reolved,immediately enqueue a PromiseJob
5. current macroTask is finished
6. run all PromiseJobs(microTasks) in order, 
7. console.log(4)
8. current cycle of event loop is finishedanother cycle starts
9. Timer Fires, and pro1 is resolved
10. at this time, pro1 hasfulfillReactions,enqueue every fulfillReaction as a PromiseJob in order
11. current macro Job is finished 
12. run all PromiseJobs in order
13. console.log(3)
14. current cycle of event loop is finished
fee-pg commented 5 years ago

2019/07/22

git更新远程仓库分支列表

git remote update origin --prune

取消/重置 git ssh 私钥密码

// 找到.ssh所在的文件夹,命令行执行
ssh-keygen -f id_rsa -p
lczc commented 5 years ago

移动端打开指定App或者下载App

navToDownApp() {
      let u = navigator.userAgent
      if (/MicroMessenger/gi.test(u)) {
        // 如果是微信客户端打开,引导用户在浏览器中打开
        alert('请在浏览器中打开')
      }
      if (u.indexOf('Android') > -1 || u.indexOf('Linux') > -1) {
        // Android
        if (this.openApp('en://startapp')) {
          this.openApp('en://startapp') // 通过Scheme协议打开指定APP
        } else {
          //跳转Android下载地址
        }
      } else if (u.indexOf('iPhone') > -1) {
        if (this.openApp('ios--scheme')) {
          this.openApp('ios--scheme') // 通过Scheme协议打开指定APP
        } else {
          // 跳转IOS下载地址
        }
      }
    },
    openApp(src) {
      // 通过iframe的方式试图打开APP,如果能正常打开,会直接切换到APP,并自动阻止a标签的默认行为
      // 否则打开a标签的href链接
      let ifr = document.createElement('iframe')
      ifr.src = src
      ifr.style.display = 'none'
      document.body.appendChild(ifr)
      window.setTimeout(function() {
        // 打开App后移出这个iframe
        document.body.removeChild(ifr)
      }, 2000)
    }
欢迎一起讨论,如果有更好的写法欢迎指教
yanghuiqi commented 5 years ago

@lczc 这个前提是 达到腾讯的相应目标(唤起APP能力),才能唤起把。

ihupoo commented 5 years ago

浏览器原生拖拽的元素超过300px会自动加上半透明效果

xuhongbo commented 5 years ago

lsof -i tcp:8080

mac环境下,命令行杀死特定node服务

由于在前端开发的时候,几个项目来回切换,难免会有端口占用的情况,之前的做法都是手动查找,由于比较麻烦,所以自己搞了个命令,一行搞定 lsof -i tcp:8080 | grep LISTEN | awk '{print $2}'| awk -F"/" '{ print $1 }' | xargs kill -9 上面举例的是杀死 8080 端口,有更好的方式,欢迎讨论

@xuhongbo awk -F"/" '{ print $1 }' 这部分命令解释一下,没懂

这个是取斜杠之前的数字部分,由于linux中的PID带有斜杠,习惯性写了个这个过滤,可以忽略

xuhongbo commented 5 years ago

mac环境下,命令行杀死特定node服务

由于在前端开发的时候,几个项目来回切换,难免会有端口占用的情况,之前的做法都是手动查找,由于比较麻烦,所以自己搞了个命令,一行搞定 lsof -i tcp:8080 | grep LISTEN | awk '{print $2}'| awk -F"/" '{ print $1 }' | xargs kill -9 上面举例的是杀死 8080 端口,有更好的方式,欢迎讨论

我都是全杀 killall node

现在vscode这些服务也是node启动的,还有钉钉,真的这样做没有问题吗???

double306 commented 5 years ago

将svg保存成图片到本地(问题:需要执行两次保存才会得到完整图片,求探讨!)

补充:可以随便找个svg代码,放在id为svg-wrap2的div下即可 //页面代码如下, `

</div>`
<script type="text/javascript">
    var svgXml2 = document.getElementById('svg-wrap2').innerHTML;

    var image1 = new Image();
    image1.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svgXml2))); //给图片对象写入base64编码的svg流

    var canvas2 = document.createElement('canvas');  //准备空画布
    canvas2.width = document.getElementsByTagName('svg')[1].width['animVal'].value;
    canvas2.height = document.getElementsByTagName('svg')[1].height['animVal'].value;

    var context1 = canvas2.getContext('2d');  //取得画布的2d绘图上下文
    context1.drawImage(image1, 0, 0);

    //图片导出为 png 格式
    var type = 'png';
    var imgData = canvas2.toDataURL(type);
    /**
     * 获取mimeType
     * @param  {String} type the old mime-type
     * @return the new mime-type
    */
    var _fixType = function(type) {
       type = type.toLowerCase().replace(/jpg/i, 'jpeg');
       var r = type.match(/png|jpeg|bmp|gif/)[0];
       return 'image/' + r;
    }; 

    // 加工image data,替换mime type
    imgData = imgData.replace(_fixType(type),'image/octet-stream');
    console.log(imgData);

    /**
     * 在本地进行文件保存
     * @param  {String} data     要保存到本地的图片数据
     * @param  {String} filename 文件名
     */
    var saveFile = function(data, filename){
        var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
        save_link.href = data;
        save_link.download = filename;

        var event = document.createEvent('MouseEvents');
        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        save_link.dispatchEvent(event);
    };

    // 下载后的文件名
    var filename = '二维码 .' + type;
    // download
    saveFile(imgData,filename);
</script>
lczc commented 5 years ago

@yanghuiqi 如果在微信浏览器中是无法唤醒App的,因为微信对所有的分享链接接做了scheme屏蔽,也就是说分享连接中所有对于scheme的调用都被微信封掉了,所以我们提示用户尝试在浏览器打开,浏览器也是不能够判读用户是否安装了某个App的,只能尝试打开,打不开就去下载。有些app是能在微信打开是因为微信有一个白名单(有关系就是不错),对于在白名单中的分享链接是不会屏蔽掉scheme调用的,所以能打开。

KRISACHAN commented 5 years ago

2019年7月23日份学习

同步阻塞法实现sleep函数

const sleep = delay => {
    const start = new Date().getTime();
    while (new Date().getTime() < start + delay) {
        continue;
    };
};
console.log(1);
sleep(3000);
console.log(2);
Yangfan2016 commented 5 years ago

20190723

利用 a 标签解析 URL


function parseURL(url) {
    var a =  document.createElement('a');
    a.href = url;
    return {
        host: a.hostname,
        port: a.port,
        query: a.search,
        params: (function(){
            var ret = {},
                seg = a.search.replace(/^\?/,'').split('&'),
                len = seg.length, i = 0, s;
            for (;i<len;i++) {
                if (!seg[i]) { continue; }
                s = seg[i].split('=');
                ret[s[0]] = s[1];
            }
            return ret;
        })(),
        hash: a.hash.replace('#','')
    };
}
cyhwinner commented 5 years ago

websocket实战运用中, 在与后台连接中,会发现有两个问题点。第一个在谷歌浏览器下会报错

Error during WebSocket handshake: Incorrect 'Sec-WebSocket-Accept' header value

而在safari浏览器下报错

 Error during WebSocket handshake: Sec-WebSocket-Accept mismatch

两个报错原因是相同的,是因为后台返回的Sec-WebSocket-Accept 和 给前端发送的头部Sec-WebSocket-Key算出的结果不一致。这时候可以让后台手动添加这个头部值,这样一来每一次计算的值必定是会正确的。具体为什么有时候后台框架计算有时候正确有时候错误,这个就不得知了。 还有一个问题点是在于,在两者没有消息通信的时候,会隔一段时间,websocket会被自动断开。原因在于,中间代理的nginx在没有发生通信的时候,会隔一定时间就会断开连接不再进行代理。所以可以采用心跳法来保持连接,通俗的说就是隔一段时间发一次消息给后台,让nginx保持连接。还有一种方式就是在即将断开连接,也就是websocket中的onclose回调中,重新再调用一次websocket连接

teachat8 commented 5 years ago

如何优雅的用js写一个最简单的商品星级评价:"★★★★★☆☆☆☆☆" 例如后台返回是1 则展示1个有颜色的星星 4个空星星 返回2则展示2个有颜色的星星 3个空的空星星

"★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate);rate为星级1-5

欢迎一起讨论,如果有更好的写法欢迎指教

Flcwl commented 5 years ago

提高 ssh 连接 git clone 的速度!!!

把下面两行加到 /etc/hosts 文件末尾

151.101.72.249 github.http://global.ssl.fastly.net
192.30.253.112 github.com

有梯子的的可以设置代理(建设本机监听socks5服务为 https://127.0.0.1:1086

$ git config --global http.https://github.com.proxy https://127.0.0.1:1086
$ git config --global https.https://github.com.proxy https://127.0.0.1:1086
zghbyslzf commented 5 years ago

19.07.24收获

node 压缩文件夹

let path = require("path");//工具模块,处理文件路径的小工具
let JSZIP = require("jszip");
let zip = new JSZIP();

//读取目录及文件
function readDir(obj, nowPath) {
    let files = fs.readdirSync(nowPath);//读取目录中的所有文件及文件夹(同步操作)
    files.forEach(fileName => {//遍历检测目录中的文件
        let fillPath = nowPath + "/" + fileName;
        console.log(fileName, '\n' ,fillPath);//打印当前读取的文件名
        let file = fs.statSync(fillPath);//获取一个文件的属性
        if (file.isDirectory()) {//如果是目录的话,继续查询
            let dirlist = obj.folder(fileName);//压缩对象中生成该目录
            readDir(dirlist, fillPath);//重新检索目录文件
        } else {
            obj.file(fileName, fs.readFileSync(fillPath));//压缩目录添加文件
        }
    });
}

//开始压缩文件
function startZIP() {
    var currPath = __dirname;//文件的绝对路径 当前当前js所在的绝对路径
    var targetDir = path.join(currPath, "web-mobile");
    readDir(zip, targetDir);
    zip.generateAsync({//设置压缩格式,开始打包
        type: "nodebuffer",//nodejs用
        compression: "DEFLATE",//压缩算法
        compressionOptions: {//压缩级别
            level: 9
        }
    }).then(content => {
        fs.writeFileSync(currPath + "/mobile.zip", content, "utf-8");//将打包的内容写入 当前目录下的 result.zip中
    });
}

startZIP();
KRISACHAN commented 5 years ago

2019年7月24日份学习

计算多个参数的平方根

Math.hypot(3, 4) // 5

数字取整(非向下,向上争取,纯去掉小数点后面的数字)

Math.trunc(13.37) // 13
shfshanyue commented 5 years ago

图片懒加载

<ul>
  <li><img src="./img/default.png" data="./img/1.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/2.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/3.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/4.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/5.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/6.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/7.png" alt=""></li>
  <li><img src="./img/default.png" data="./img/8.png" alt=""></li>
</ul>
let imgs =  document.querySelectorAll('img')
// 窗口可视区高度
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// img 距离窗口可视区顶部的距离 imgs[i].getBoundingClientRect().top
function lazyLoadImg () {
    for (let i = 0; i < imgs.length; i ++) {
        if((imgs[i].getBoundingClientRect().top + imgs[i].height)>=0&&imgs[i].getBoundingClientRect().top < clientHeight ){
            imgs[i].src = imgs[i].getAttribute('data')
        }
    }      
}
window.addEventListener('scroll', lazyLoadImg);

可以使用最新的 API https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API 来做这件事,会更简单而且可控一些

Yangfan2016 commented 5 years ago

20190724

解决Vuex状态丢失的问题

原文 npm 在线例子

  • 默认存储到localStorage
    
    import createPersistedState from "vuex-persistedstate"
    const store = new Vuex.Store({
    // ...
    plugins: [createPersistedState()]
    })
- 想要存储到sessionStorage,配置如下
```js
import createPersistedState from "vuex-persistedstate"
const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState({
      storage: window.sessionStorage
  })]
})
KieSun commented 5 years ago

如何优雅的用js写一个最简单的商品星级评价:"★★★★★☆☆☆☆☆" 例如后台返回是1 则展示1个有颜色的星星 4个空星星 返回2则展示2个有颜色的星星 3个空的空星星

"★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate);rate为星级1-5

欢迎一起讨论,如果有更好的写法欢迎指教

简单是简单的了,但是在真实需求下这种方法基本是用不了。

不说如何展示半颗星,即使是星星的样式就不大好把控。

当然还是很感谢分享内容!

mengsixing commented 5 years ago

20190724

学习希尔排序

希尔排序使用算法中的分治思想,先把需要排序的数组拆分成 n 个小数组,在 n 个小数组中分别进行插入排序,然后将排序好的小数组再组合起来。

插入排序在处理小数据或者基本有序数据时,效率很高。希尔排序将数据拆分成小数据,并分别排序,就能大大提高插入排序的效率,可以说是插入排序的升级版。

function shellSort(array) {
  // 定义间隔序列,这里写死了,可以动态定义
  const gaps = [5, 3, 1];
  for (let index = 0; index < gaps.length; index++) {
    const gap = gaps[index];

    for (let outer = gap; outer < array.length; outer++) {
      // 检查的数字
      const temp = array[outer];
      for (
        let inner = outer - gap;
        // 如果比之前的 gap 小,就交换一下,直到交换到第一个 gap 处
        inner >= 0 && array[inner] > temp;
        inner -= gap
      ) {
        swap(array, inner, inner + gap);
      }
    }
  }
  return array;
}
kdush commented 5 years ago

内网环境 如何使用gitKraken

Geek-James commented 5 years ago

阅读了jQuery源码-延迟函数的解决方案,并且写了学习笔记 https://github.com/Geek-James/Blog

HEternally commented 5 years ago

20190723 发布个人第一个npm包 介绍 基于人像区域的蒙版(mask)图层的人像抠出方法,即将人和背景进行分离 npm Github

KieSun commented 5 years ago

内网环境 如何使用gitKraken

可以参考下别人的格式,写一下学到的内容。

KieSun commented 5 years ago

正在学习node,没有用框架,做了两个事。 1.用node建立了一个服务端,接收post图片并压缩。 2.用node爬了nba官网的信息,将内容作为邮件发送给自己。 还有就是希望大家给点学习nodejs的建议

可以参考下别人的格式,写一下学到的内容。

Geek-James commented 5 years ago
teachat8 commented 5 years ago

2019年7月25日份学习

vscode内存占用过高解决方法?

文件>首选项>设置, 搜索设置 "search.followSymlinks" :false;

TNTrocket commented 5 years ago

2019.7.25

  • web打印
    @media print {
    .noPrint{
    display: none
    }
    }

    可以css控制打印的样式

lancelot-song commented 5 years ago

分享些Flutter的相关吧: Flutter的底层图像渲染引擎是基于C++开发的Skia,被Google收购后应用于Chrome、Android等核心产品上,目前Android系统都内置的有此技术,所以在打包方面,因IOS系统不支持Skia进行渲染,会配上此渲染引擎,所以打包时会比Android的包大一些,底层渲染能力达到一致了,就解决了平台不同渲染有差异的问题。 也因为Flutter的开发需要新的语言特性,若使用Javascript则需要经过漫长的W3C标准审批等流程,影响整体开发进度,故使用Dart作为Flutter的开发语言,也因为Dart是新语言,借鉴了多类语言的优点,并且Dart是自家产品,可以快速的进行迭代更新。 Flutter的绘制顺序是按照深度遍历进行渲染,并优先渲染父节点,再渲染子节点,若其中一个节点改变了渲染,则会将所有图层一起计算出和最终效果后交由Skia来做处理,而不是单独渲染,影响渲染性能。

在windows环境编写Flutter的时候可以安装Android Studio/VScode来开发,但都要安装插件来支持Flutter的语法,其中AndroidStudio内置的有android模拟器,提供便捷的测试效果,所以Anrdoid Studio是必装的

至于Dart语法相关知识我还没学透,说不了太多,但聊胜于无,它和JavaScript类似的点有: class Child extends Parent 继承父类; 类似的运算符: a?.print() : a为null则不调用自身或父类继承的print方法,防止发生意外的错误调用 a ??= b :a为null 则赋值为b a ?? b : a存在返回a 否则返回b 相当于a ? a : b

TS语法: class Child implements Parent 实现抽象父类

Dart语法也就是所谓的集百家之所长,很多语言的优点特性都引入了进来,光凭借JavaScript的编写思想是无法运用好它的,需要学习其他语言的优势思想与语法糖,这也是极好的。

HEternally commented 5 years ago

20190725 Promise相关知识: 1、then方法提供一个自定义的回调函数,若传入非函数,则会忽略当前then方法。 2、回调函数中会把上一个then中返回的值当做参数值供当前then方法调用。 3、then方法执行完毕后需要返回一个新的值给下一个then调用(没有返回值默认使用undefined)。 4、每个then只可能使用前一个then的返回值。

qifengwangye commented 5 years ago

偶然看到一种之前没有想到过的数组去重方法:

  var array = [1, 2, 1, 1, '1'];
  function unique(array) {
    var obj = {};
    return array.filter(function(item, index, array){
      return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
    })
  }
  • 利用一个空的 Object 对象,我们把数组的值存成 Object 的 key 值,比如 Object[value1] = true,在判断另一个值的时候,如果 Object[value2]存在的话,就说明该值是重复的。因为 1 和 '1' 是不同的,但是这种方法会判断为同一个值,这是因为对象的键值只能是字符串,所以我们可以使用 typeof item + item 拼成字符串作为 key 值来避免这个问题
kdush commented 5 years ago

效率怎么样呢 有比较吗

原始邮件 发件人:qifengwangyenotifications@github.com 收件人:KieSun/today-i-learnedtoday-i-learned@noreply.github.com 抄送:Ray Zhangzhangdaleigogo@qq.com; Commentcomment@noreply.github.com 发送时间:2019年7月25日(周四) 17:09 主题:Re: [KieSun/today-i-learned] 2019.7.22 - 7.28 中你学到什么? (#3)

偶然看到一种之前没有想到过的数组去重方法: var array = [1, 2, 1, 1, '1']; function unique(array) { var obj = {}; return array.filter(function(item, index, array){ return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true) }) } 利用一个空的 Object 对象,我们把数组的值存成 Object 的 key 值,比如 Object[value1] = true,在判断另一个值的时候,如果 Object[value2]存在的话,就说明该值是重复的。因为 1 和 '1' 是不同的,但是这种方法会判断为同一个值,这是因为对象的键值只能是字符串,所以我们可以使用 typeof item + item 拼成字符串作为 key 值来避免这个问题 — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

Mikerui commented 5 years ago

退出微信网页窗口的方法,ios和Android都有的 setTimeout(function() { document.addEventListener( 'WeixinJSBridgeReady', function() { WeixinJSBridge.call('closeWindow'); }, false ); // 关闭iPhone WeixinJSBridge.call('closeWindow'); }, 300);