Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019.7.29 - 8.4 中你学到什么? #7

Open
KieSun opened this issue Jul 28, 2019 · 39 comments
Open

2019.7.29 - 8.4 中你学到什么? #7

KieSun opened this issue Jul 28, 2019 · 39 comments

Comments

@KieSun
Copy link
Owner

KieSun commented Jul 28, 2019

No description provided.

@shfshanyue
Copy link

shfshanyue commented Jul 29, 2019

2019/07/29

01 简单了解 netlify 的一些配置

由于所有的静态资源都打了 hash,为所有静态资源添加了永久缓存。另外配置了自动部署

[[headers]]
  for = "/assets/*"

  [headers.values]
    cache-control = "max-age=31536000"

配置文件

02 一篇关于 exit code 与 node 中异常的文章

https://shanyue.tech/post/exit-code-node-and-docker.html

2019/07/30

01 一篇关于调试 js 的示例总结

https://shanyue.tech/post/js-debug-examples/

02 关于 kill 的一些信号 (signal)

当起了一个 server 时,

  • <Ctrl+C> 使用 SIGINT(2) 来杀死进程
  • kill 默认使用 SIGTERM(15) 杀死进程,进程可以对该信号进行捕捉
  • kill -9 使用 SIGKILL(9) 杀死进程,进程无法对信号进行捕捉 (强制杀死)

03 对指定进程的 signal 进行监控

strace -e signal -p $pid

2019/07/31

01 graphql 中 apollo-server 对 cache 的处理

今天对我的脚手架的服务端添加了对缓存的处理,具体改动如下

shfshanyue/apollo-server-starter@e40f596

具体看了下相关插件关于缓存的源码,发现与我想的缓存机制不大一样。graphql 可以说是以 field 为主要关注点,本以为它会根据 field 来进行缓存,就如同客户端的apollo-clientrelay 一般。结果它还是以整个 query 为单位进行缓存,不过,细想也是有原因的:

  1. 方便 http response,(GET)
  2. 返回 field 的数据无法组成 resolver 函数中 Parent 的数据类型

关于如何对一个 query 计算它的缓存时间的源码如下

type Post @cacheControl(maxAge: 240) {
  id: Int!
  votes: Int @cacheControl(maxAge: 300)
}

type Query {
  latestPost: Post @cacheControl(maxAge: 10)
}

02 对个人 Next + React + GraphQL 的项目添加了简单的 ts 支持

以下是具体改动,Next 现在对新增 ts 支持的体验真是棒,只需要按着提示走就可以了

2019/08/01

每日一诗:荷风送香气,竹露滴清响。

01 React Hook 的学习

hook 的出现真是振奋人心,可惜现在才看。最喜欢它的两点:复用逻辑和减少嵌套。

graphql 中再配合 react-apollon-hooks 使用,体验极佳。

PS: 再结合 graphql-code-generator 前端自动生成类型/(及注释文档),不知少了多少前后端的沟通。graphql 后端的接口一出来,前端立即可以

  1. 使用 graphql-code-generator 自动拉取 type.ts,解决前后端联调最大的问题,及 API 的前后端数据类型一致性,且不用手工维护
  2. 在 type.ts 中有注释,即文档,不懂的可以再问后端
  3. 自动补全以及类型校验接口字段

02 总结了一份关于 graphql-code-generator 自我感觉良好的配置文件

overwrite: true
schema: "http://localhost:5000/graphql"
documents: "query.gql"
generates:
  query.ts:
    plugins:
      - "typescript"
      - "typescript-operations"
    config:
      scalars:
        DateTime: Date
        JSON: "{ [key: string]: any }"
      namingConvention:
        typeNames: change-case#pascalCase
        transformUnderscore: true
        enumValues: keep

2019/08/02

因过竹院逢僧话,又得浮生半日闲。

01 看源码 Bluebird.map 中的 concurrency 的实现原理 (doing)

自然自己可以实现一个关于 Promise 的限流,但是能设计好 API 就是另一回事了

function get (i) {
  console.log('In ', i)
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve() 
      console.log('Out', i)
    }, i * 1000)
  })
}

// 如何使用 get 请求这些数据,并且限流三个
const list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

let count = 0
function run () {
  if (count < 3 && list.length) {
    count+=1
    get(list.shift()).then(() => {
      count-=1 
      run()
    })
  }
}

run()
run()
run()

2019/08/03

叶上初阳干宿雨,水面清圆,一一风荷举。

01 看源码 featurist/promise-limit 中的 promise 限流的实现

02 接昨日,实现一个 Promise.map

class Limit {
  constructor (n) {
    this.limit = n
    this.count = 0
    this.queue = []
  }

  enqueue (fn) {
    return new Promise((resolve, reject) => {
      this.queue.push({ fn, resolve, reject })
    })
  }

  dequeue () {
    if (this.count < this.limit && this.queue.length) {
      const { fn, resolve, reject } = this.queue.shift()
      this.run(fn).then(resolve).catch(reject)
    }
  }

  async run (fn) {
    this.count++
    const value = await fn()
    this.count--
    this.dequeue()
    return value
  }

  build (fn) {
    if (this.count < this.limit) {
      return this.run(fn)
    } else {
      return this.enqueue(fn)
    }
  }
}

PromiseMap = function (list, fn, { concurrency }) {
  const limit = new Limit(concurrency)
  return Promise.all(list.map((...args) => {
    return limit.build(() => fn(...args))
  }))
}

function get (i) {
  console.log('In ', i)
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve() 
      console.log('Out', i)
    }, i * 1000)
  })
}
PromiseMap(list, i => get(i), { concurrency: 3 })

2019/08/04

风吹古木晴天雨,月照平沙夏夜霜。

@ddzy
Copy link

ddzy commented Jul 29, 2019

2010/07/29

简单了解 netlify 的一些配置

我穿越了么

@ddzy
Copy link

ddzy commented Jul 29, 2019

大部分时间写毕设

  • 早上更新一下仓库, 写毕业设计
  • 下午抽空看看react源码
  • 晚上看电影, 玩

@LHM0105
Copy link

LHM0105 commented Jul 29, 2019

今天解决了个bug:
bug:微信小程序在ios真机上,文本内容不显示(随机性),安卓和模拟器正常
hack:经排查,原因是对显示异常的文本使用了超出一行省略,去掉对应的超出省略样式即可正常显示

@shfshanyue
Copy link

shfshanyue commented Jul 29, 2019

2010/07/29

简单了解 netlify 的一些配置

我穿越了么

这...哈哈哈哈

@470772345
Copy link

leetcode 求数组中心索引
输入:
nums = [1, 7, 3, 6, 5, 6]
输出: 3
解释:
索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。
同时, 3 也是第一个符合要求的中心索引。

在学习这道题途中,发现网友一个比较有趣的解法,分享一下

@1.先算出总数, 2, 遍历, 总数减去当前值 再除以2. 是否等于当前累计值
var pivotIndex = function(nums) {
if(nums.length < 3) return -1;
let sum=0 , left=0
for(let i=0;i<nums.length;i++) {
sum+=nums[i]
}
for(let i=0;i<nums.length;i++){
if((sum-nums[i])/2==left){
return i;
}
left+=nums[i]
}
return -1;
};

@plushao
Copy link

plushao commented Jul 29, 2019

iviewui 的Upload组件中,当图片文件被上传前会调用before-upload 方法,我们对图片对大小对验证也就是在这里进行:
beforeUpload(file){ return this.checkImageWH(file,700,400); } checkImageWH(file, width, height) { let self = this; return new Promise(function (resolve, reject) { let filereader = new FileReader(); filereader.onload = e => { let src = e.target.result; const image = new Image(); image.onload = function () { if (width && this.width != width) { // console.log('hhhh') self.$Message.error({ content: 请上传宽为${width},高为${height}的图片, duration: 3 }); reject(); } else if (height && this.height != height) { self.$Message.error({ content: 请上传宽为${width},高为${height}的图片, duration: 3 }); reject(); } else { resolve(); } }; image.onerror = reject; image.src = src; }; filereader.readAsDataURL(file); }); },
之前也有思考如何对图片上传前对规格进行验证,这个方案感觉很妙。

@yuuk
Copy link

yuuk commented Jul 29, 2019

typescript使用 typeof 关键字可以自动获取数据类型。
在写react项目时,有些时候,你的state可能会有默认值,比如:

const initialState = {
   username: '',
   mobile: '',
   isVip: false,
  addresses: [],
}

type IState = typeof initialState

class Comp extends Component<any, IState> {
   constructor(props) {
        super(props);
        this.state = {
            ...initialState
        };
    }
}

这样就不用分开定义state的初始值和state的类型了。

@pass13046132
Copy link

pass13046132 commented Jul 29, 2019

从掘金过来的,感觉这个项目挺有意思的,大家互相学习吧!
分享一下最近get到的一个小技巧。交换数组指定位置元素位置:

例如: [1 ,2, 3, 4] ===> [1, 2, 4, 3]

function arrIndexExchange(array, x, y){
    array.splice(x - 1, 1, ...array.splice(y - 1, 1, array[x - 1]));
    return array;
};

// x , y是要交换元素的位置(index+1)

@Yangfan2016
Copy link

Yangfan2016 commented Jul 29, 2019

20190729

提高你工作效率的位运算

请注意 位运算适用于 32 位整数,所以精度可能会丢失

  • 用 "|" 取整
let num=1.5
num=num|0; // 1
  • 用 ">>" 取半
let num=4;
num=num>>1; // 2
  • 用 "<<" 加倍
let num=2;
num=num<<1; / / 4
  • 用 "^" 两值交换
let a=1;
let b=2;

a^=b;
b^=a;
a^=b;

// a===2,b===1
  • 用 "&" 判断奇数
let n=3;
let m=4;

n&1===1; // true 奇数
m&1===1; // false 偶数
  • 用 "~" 判断项是否存在
let firstname="Ma";
let fullname="Jack Ma";

let isExist=!!~fullname.indexOf(firstname); // true

@ximendatie
Copy link

git高频指令

新建分支并切换到该分支

git checkout -b test

删除本地分支

git branch -d dev

删除远程分支

git branch -r -d origin/branch_dev 
and
git push origin :branch_dev

本地新分支同步到远程

git push origin branch_dev:branch_dev
冒号前是本地分支的名,冒号后面是要创建的远程分支名,自己另起名称随便,如果直接使用 git push origin branch_dev 则默认和远程分支同名

远程新分支拉到本地

  1. git checkout -b test origin/test
    如果失败,尝试先git fetch后执行
    采用此种方法建立的本地分支会和远程分支建立映射关系
  2. git fetch origin test:test
    使用该方式会在本地新建分支,但是不会自动切换到该本地分支,需要手动checkout。
    采用此种方法建立的本地分支不会和远程分支建立映射关系。

head指向控制

git checkout test
git checkout ea9a77f 切到某一次提交

仅合并部分文件

https://segmentfault.com/a/1190000008360855

另外

github使用的pull request和gitlab使用的merge request,意义相同

回滚

git reset直接回到某一commit适用于本地回滚;
git revert撤销某一commit,但是版本会向前走,可以用于远程回滚。前者指定id会定位到某个id,后者指定id会把某个id的提交撤销

@luohong123
Copy link

luohong123 commented Jul 30, 2019

2019-07-29 study

学会写脚本提高工作效率,并学会用commander download-git-repo handlebars inquirer fs ora chalk log-symbols等依赖自己实现 cli 脚手架,对 vue-cli、angular-cli 脚手架有初步的理解,写这个脚本的初衷,是因为公司基于 Angular5 做了一个内网项目,一套代码,10-20个不同后台服务环境,每次升级项目,需要修改 environment文件,一个一个的敲ng build命令,打包半天,这个脚本的思路是把后台的服务地址、服务器名称等变量放到一个数组里面,不用去修改 environment 文件夹 和 angular-cli.json 文件下的配置,只需要管理这个数组,动态的创建 enviroment.ts 文件和修改 angular-cli.json文件,运行 npm run multienv 命令,就能一次打包 20 个不同的环境配置。
我写的脚手架已提交到 GitHub: https://github.com/luohong123/ng-multienv-build

2019-07-31 study

  1. 学会通过 return this写链式调用
<script type="text/javascript">
        /**
         * 获取名字
         */
        function getName() {
            console.log('qingcheng')
            return this
        }
        /**
         * 获取年龄
         */
        function getAge() {
            console.log('25')
            return this
        }
        /**
         * 获取爱好
         */
        function getHobby() {
            console.log('eat、coding...')
            return this
        }
        getName().getAge().getHobby() // qingcheng 25 eat、coding
</script>

2019-08-02 study

VSCode 中下载集成了 leetcode 插件,自动保存 练习的代码到指定文件夹,适合随时刷题、做笔记,挺方便的

@Yangfan2016
Copy link

Yangfan2016 commented Jul 30, 2019

20190730

arguments 的坑 MDN 文档

注意严格模式下,没有这个问题

  • 当非严格模式中的函数 没有 包含 剩余参数默认参数解构赋值,那么arguments对象中的值会跟踪参数的值(反之亦然)
function sidEffecting(ary) {
  ary[0] = ary[2];
}
function bar(a,b,c) {
  c = 10 // 注意这里,其实它修改的就是 arguments 对象里的参数
  sidEffecting(arguments);
  return a + b + c;
}
bar(1,1,1);   // 21
  • 当非严格模式中的函数 包含剩余参数默认参数解构赋值,那么arguments对象中的值不会跟踪参数的值(反之亦然)
function sidEffecting(ary) {
  ary[0] = ary[2];
}
function bar(a,b,c=3) {
  c = 10
  sidEffecting(arguments);
  return a + b + c;
}
bar(1,1,1); // 12

@KieSun
Copy link
Owner Author

KieSun commented Jul 30, 2019

20190729 study

学会写脚本提高工作效率,并学会用commander download-git-repo handlebars inquirer fs ora chalk log-symbols等依赖自己实现 cli 脚手架,对 vue-cli、angular-cli 脚手架有初步的理解,写这个脚本的初衷,是因为公司基于 Angular5 做了一个内网项目,一套代码,10-20个不同后台服务环境,每次升级项目,需要修改 environment文件,一个一个的敲ng build命令,打包半天,这个脚本的思路是把后台的服务地址、服务器名称等变量放到一个数组里面,不用去修改 environment 文件夹 和 angular-cli.json 文件下的配置,只需要管理这个数组,动态的创建 enviroment.ts 文件和修改 angular-cli.json文件,运行 npm run multienv 命令,就能一次打包 20 个不同的环境配置。
我写的脚手架已提交到 GitHub: https://github.com/luohong123/ng-multienv-build

有兴趣的话可以对内容做个总结

@KieSun
Copy link
Owner Author

KieSun commented Jul 30, 2019

20190729

提高你工作效率的位运算

请注意 位运算适用于 32 位整数,所以精度可能会丢失

  • 用 "|" 取整
let num=1.5
num=num|0; // 1
  • 用 ">>" 取半
let num=4;
num=num>>1; // 2
  • 用 ">>" 加倍
let num=2;
num=num<<1; / / 4
  • 用 "^" 两值交换
let a=1;
let b=2;

a^=b;
b^=a;
a^=b;

// a===2,b===1
  • 用 "&" 判断奇数
let n=3;
let m=4;

n&1===1; // true 奇数
m&1===1; // false 偶数
  • 用 "~" 判断项是否存在
let firstname="Ma";
let fullname="Jack Ma";

let isExist=!!~fullname.indexOf(firstname); // true

总结的蛮好的,很多人对于位运算的认知都很少

@KieSun
Copy link
Owner Author

KieSun commented Jul 30, 2019

typescript使用 typeof 关键字可以自动获取数据类型。
在写react项目时,有些时候,你的state可能会有默认值,比如:

const initialState = {
   username: '',
   mobile: '',
   isVip: false,
  addresses: [],
}

type IState = typeof initialState

class Comp extends Component<any, IState> {
   constructor(props) {
        super(props);
        this.state = {
            ...initialState
        };
    }
}

这样就不用分开定义state的初始值和state的类型了。

这个小技巧很有用,能省很多代码

@KieSun
Copy link
Owner Author

KieSun commented Jul 30, 2019

分享一篇文章,领域驱动设计在前端中的应用

@bitfishxyz
Copy link

这周我完善了之前的文章: fish-stack/Algo#2
我在这篇文章中详细的介绍了二叉树和二叉搜索树的用法,通过这种写作的方式,让自己对这个数据结构理解的更加的深刻了。

@ghost
Copy link

ghost commented Jul 30, 2019

这周研究 thingsboard,发现一个奇妙的分页设计。

分页查询数据接口,要求四个参数:
"idOffset": "string", // 从某条数据对应的id
"limit": 0, //每页请求条数
"textOffset": "string", // 从某页开始的页码
"textSearch": "string" //搜索参数

返回的数据格式:

{
  "data": [], //数据
  "hasNext": true, //是否有下一页
  "nextPageLink": {
    "idOffset": "string", // 从某条数据对应的id
    "limit": 0, //每页请求条数
    "textOffset": "string", // 从某页开始的页码
    "textSearch": "string" //搜索参数
  }
}

这种设计适合触底加载,因为不需要在一开始就知道数据有几页
不适合传统的拿到总条数的设计,因为一开始不知道有几条数据

@yy523697597
Copy link

7月30日

  1. ES6 中 class 类,包含 constructor 函数。派生类的构造函数中必须使用 super(),如果不这样程序就会报错。使用this之前一定要调用super()。
  2. Object.assign() 可以使用 …运算符代替
let a = {
	num:12
};
let b = {
	count:13
}
let c = Object.assign(a,b);
let d = {...a,...b}; 
  1. electron 中如果页面中需要开启node语法,需要在创建BrowserWindow 时,开启nodeIntegration

     webPreferences: {
          nodeIntegration: true
     }
  2. node 中默认不支持 import 和 export 语法,需要使用 module.exports 或者 exports 导出,使用 require 引入模块。如果要使用import 和 export 需要使用 babel 转一下。

@qdlaoyao
Copy link

qdlaoyao commented Jul 31, 2019

用canvas实现文字渐变效果

var context = canvas.getContext('2d')
var g = context.createLinearGradient(0,0,canvas.width,0)
g.addColorStop(0, 'red')
g.addColorStop(0.5, 'blue')
g.addColorStop(1, 'purple')
context.fillStyle = g
context.font = '36px fantasy'
context.fillText('hello canvas', 0, 100)

效果动图

@TNTrocket
Copy link

TNTrocket commented Jul 31, 2019

7.31

es6 proxy 深度代理一个对象

function deepProxy(object, handler) {
    if (isComplexObject(object)) {
        addProxy(object, handler);
    }
    return new Proxy(object, handler);
}

function addProxy(obj, handler) {
    for (let i in obj) {
        if (typeof obj[i] === 'object') {
            if (isComplexObject(obj[i])) {
                addProxy(obj[i], handler);
            }
            obj[i] = new Proxy(obj[i], handler);
        }
    }
}

function isComplexObject(object) {
    if (typeof object !== 'object') {
        return false;
    } else {
        for (let prop in object) {
            if (typeof object[prop] == 'object') {
                return true;
            }
        }
    }
    return false;
}

let person = {
    txt: 123,
    name: 'tnt',
    age: 26,
    status: {
        money: 'less',
        fav: [1, 2, 3]
    }
};
let proxyObj = deepProxy(person, {
    get(target, key, receiver) {
        console.log(`get--${target}--${key}`);
        return Reflect.get(target, key);
    },
    set(target, key, value, receiver) {
        console.log(`set--${target}--${key}-${value}`);
        return Reflect.set(target, key, value);
    }
});
proxyObj.status.test = 13;
proxyObj.status.fav.push('33');

@GYueLong
Copy link

//string 构造函数
#include
#include
using namespace std;
int main()
{
string str1(5,'g');
string str2("gao yue long");
string str3(str2,3,3);//输出:空格yu
// string str3(str2,4,3);//输出:yue
cout<<str1<<endl;//输出5个g
cout<<str2<<endl;//输出gao yue long
cout<<str3<<endl;
return 0;
}
使用STL string连接字符串
#include
#include
using namespace std;
int main()
{
string strSample1("hello");
string strSample2(" string!");
strSample1+=strSample2;
cout<<strSample1<<endl<<endl;
string strSample3("Fun is not needing to use pointers!");
strSample1.append(strSample3);
cout<<strSample1<<endl<<endl;
const char* pszConstString="You however still can!";
strSample1.append(pszConstString);
cout<<strSample1<<endl;
return 0;
}

@jecyu
Copy link

jecyu commented Jul 31, 2019

7.31

获得纪念日的时间

 created() {
    this.pollingAction = new PollingAction(
      () => {
        this.getFormatTime();
      },
      1000,
      true
    );
    this.pollingAction.start();
    this.$once("hook:beforeDestory", () => {
      this.pollingAction.cancel();
    });
  },
  methods: {
    getFormatTime() {
      // 系统时间时间戳
      const currentTimeStamp = this.getUnix();
      this.timeRange = currentTimeStamp - this.specialTimeStamp;
      const oneDayTimeStamp = 1000 * 60 * 60 * 24; // 一天的毫秒数
      const oneHourTimeStamp = 1000 * 60 * 60; // 一小时的毫秒数
      const oneMinuteTimeStamp = 1000 * 60; // 一分钟的毫秒数
      const oneSecondTimeStamp = 1000; // 一分钟的毫秒数
      // 天数
      this.days = parseInt(this.timeRange / oneDayTimeStamp);
      // 时数
      this.hours = parseInt(
        (this.timeRange % oneDayTimeStamp) / oneHourTimeStamp
      );
      // 分数
      this.minutes = parseInt(
        ((this.timeRange % oneDayTimeStamp) % oneHourTimeStamp) /
          oneMinuteTimeStamp
      );
      // 秒数
      this.seconds = parseInt(
        (((this.timeRange % oneDayTimeStamp) % oneHourTimeStamp) %
          oneMinuteTimeStamp) /
          oneSecondTimeStamp
      );
    },
      // 获得当前时间戳
    getUnix() {
      return +new Date();
    },
    // 获得指定时间的时间戳
    getSpecialUnix(time) {
      const date = new Date(time);
      return date.getTime();
    }
  }
    

@Amecy
Copy link

Amecy commented Aug 1, 2019

20190729

提高你工作效率的位运算

请注意 位运算适用于 32 位整数,所以精度可能会丢失

  • 用 "|" 取整
let num=1.5
num=num|0; // 1
  • 用 ">>" 取半
let num=4;
num=num>>1; // 2
  • 用 ">>" 加倍
let num=2;
num=num<<1; / / 4
  • 用 "^" 两值交换
let a=1;
let b=2;

a^=b;
b^=a;
a^=b;

// a===2,b===1
  • 用 "&" 判断奇数
let n=3;
let m=4;

n&1===1; // true 奇数
m&1===1; // false 偶数
  • 用 "~" 判断项是否存在
let firstname="Ma";
let fullname="Jack Ma";

let isExist=!!~fullname.indexOf(firstname); // true

弊大于利吧,明明有简洁易懂的方式,写成这样别人可能看不懂

@yy523697597
Copy link

7月31号

  1. Array.reduce( ) 数组循环
Array.reduce(callback,[initialValue]);

reduce 方法,两个参数,第一个参数是回调函数 callback,会对数组的每一项执行。第二个参数是第一次调用 callback 时,第一个参数的值。

callback 接受4个参数(previousValue,currentValue,index,array

previousValue:上一次调用回调返回的值,或者是提供的初始值 initialValue,

currentValue:数组中当前被处理的元素,

index:当前元素在数组中的索引,

array:调用 reduce 的数组

// 处理收到的音乐地址
const renderListHTML = musicPathes => {
    const musicList = $('musicList');
  	// html 是上一次执行后获得的值,music 是当前正在被处理的数据
    const musicItemsHTML = musicPathes.reduce((html, music) => {
        html += `<li class="list-group-item">${path.basename(music)}</li>`;
        return html;
    }, '');
    musicList.innerHTML = musicItemsHTML;
};
  1. node 中 path 模块可以获取路径的很多东西

    path.basename(filePath) :获取路径中文件名

@yy523697597
Copy link

8月1号

1.Element.classList 是一个只读属性,返回一个元素的类属性的实时DOMTokenList 集合。

$("#musicContainer").addEventListener("click", event => {
  const { classList } = event.target;
  // 调换类名
  classList.replace("fa-play", "fa-pause");
  // 添加类名
  classList.replace("fa-thumb");
})
  1. 格式化秒为 04:19 类型的小函数

    const convertDuration = time => {
      const minutes = "0" + Math.floor(time / 60);
      const seconds = "0" + Math.floor(time - minutes * 60);
      return minutes.substr(-2) + ":" + seconds.substr(-2);
    };
    
    convertDuration(252); // "04:12"

@comeCU
Copy link

comeCU commented Aug 1, 2019

8月1号

  1. 最近新建了个repo,初窥JavaScript
  2. JavaScript组件化开发思想demo
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>js插件化</title>
		<script type="text/javascript">
			// 闭包
			;(function(win, doc, undefined) {
				// 插件名字
				var AddHtml = function(id) {
					// 针对属性做初始化
					this.div = document.getElementById(id);
					this.p = this.div.getElementsByTagName('p')[0];
					this.input = this.div.getElementsByTagName('input')[0];
					// 绑定事件
					this.init();
				};
				
				// 定义方法
				AddHtml.prototype = {
					constructor: AddHtml,
					init: function() {
						var _self = this;  // AddHtml
						this.input.onkeyup = function() {
							// 获取输入框的值,并设置到p标签
							var value = this.value;
							_self.p.innerHTML = value;
							// _self.setColor();
						}
					},
					// 设置p标签颜色
					setColor: function() {
						var colors = ['#FF0000','#00ff00','#0000FF','#FFFF00','#FFCC00','#00AAFF','#00FFCC'];
						var index = parseInt(Math.random() * (colors.length + 1));
						this.p.style.color = colors[index];
					}
				};
				
				// 将AddHtml暴露给外部的调用者
				// 参考:http://www.voidcn.com/article/p-zwonfeok-bsp.html
				var _globals;
				_globals = (function(){ return this || (0,eval)("this"); }());
				// Window.AddHtml = AddHtml;
				_globals.AddHtml = AddHtml;
			}(window, document));
			
			
			// 测试
			window.onload = function() {
				var myAddHtml = new AddHtml('ad');
				myAddHtml.setColor();
				
				var $ = new AddHtml('ad2');
				$.setColor();
			}
		</script>
	</head>
	<body>
		<div id="ad">
			<p>test</p>
			<input value="test" />
		</div>
		
		<div id="ad2">
			<p>test2</p>
			<input value="test2" />
		</div>
		
	</body>
</html>
  1. repo地址some-js

@LienJack
Copy link

LienJack commented Aug 2, 2019

8月2号

背景

由于公司项目不同部门使用的框架不同,有react和vue,而且vue-cli又分vue-cli2和vue-cli3。所以上个月7月份基本都在弄一套能快速生成vue,react,typscript,rollup项目的脚手架。思路是使用从git把项目模板拉下来后用模板引擎渲染项目的办法。

效果图

alice

  • 多套模板选择
  • 脚手架支持自动更新

安装使用

GitHub地址

https://github.com/LienJack/alice-cli

安装

npm/cnpm/yarn install alice-cli -g

使用

alice init <you project name>

目前提供模板

1. vue 2.0

自定义配置

  1. 是否使用移动端适配
  2. 是否兼容安卓4.4.0版本
  3. 是否配置微信sdk
  4. 是否使用vux
  5. 环境选择: 本地、开发、测试、生产、灰度、预发布

2. react 16.0

自定义配置

  1. 是否使用移动端适配
  2. 是否兼容安卓4.4.0版本
  3. 是否配置微信sdk
  4. 是否使用redux
  5. 环境选择: 本地、开发、测试、生产、灰度、预发布

3. 基于electron + react项目(todo)

TODO

4. 基于electron + vue(todo)

TODO

5. 使用rollup做构建工具,适用于编写组件或库

rollup是一款专业打包js的打包工具,比起webpack打包速度更快,体积更小。适用于组件和库的开发打包。

自定义配置

  • es – 将软件包保存为ES模块文件
  • cjs – CommonJS,适用于 Node 和 Browserify/Webpack
  • amd 异步模块定义,用于像RequireJS这样的模块加载器
  • umd – 通用模块定义,以amd,cjs 和 iife 为一体

插件选择:

  • rollup-plugin-node-resolve 插件可以告诉 Rollup 如何查找外部模块。 安装它
  • rollup-plugin-commonjs 们需要将CommonJS模块转换为 ES2015 供 Rollup 处理
  • rollup-plugin-babel 使用babel编译
  • rollup-plugin-uglify 压缩代码

6. 快速生成typscript环境

typscript是未来趋势,此模板快速生成typscript环境,用于各种实验

7. 快速生成es6+环境,用于做实验

使用ES6会出现兼容问题,此模板不仅能使用es6语法,甚至es7装饰器等草案都能使用。

8. 快速生成刷leetcode环境(自己私货)

虽然有leetcode的vscode插件,但是对于树,链表等题目时候每次修改都要提交一次很麻烦。所以想先在本地跑通一遍才提交leetcode。这模板除了能使用es6+还内嵌二叉树树,搜索二叉树,链表,堆等常用的数据结构和一些工具函数,方便刷题。

优点

比起官方提供脚手架模板,自己编写这套vue和react模板有以下优点

  • 构建速度快。利用DLL预先打包和happypack进行多线程打包。通过cache-loader进行缓存,加快本地开发。
  • 打包资源变小。对资源都进行压缩。
  • 配置容易上手。参考vue-cli配置和命名风格,把常用配置单独抽离。
  • 支持多环境 (本地、开发、测试、灰度、预发、生产环境)

学习到什么

其实编写脚手架从技术来说真的不难,难就是对于不同项目和框架如何结合业务配置。这脚手架可以看得出对于移动端的配置还是比较多,那是因为之前的项目大多数都是移动端,所以移动端的坑踩得比较多,编写这脚手架也算时对之前踩坑的总结吧。

还有就是更加深入认识前端工程化,在编写脚手架的同时看了

  • 《前端工程化:体系设计与实践》
  • 《深入浅出wepback》
  • 《前端架构:从入门到微前端》
  • vue-cli2 部分源码
  • create-react-app 部分源码

这种高强度的边看原理源码边实践使人成长飞快,就是有点累,要兼顾业务需求和自己项目确实不容易。

@ximendatie
Copy link

0.1+0.2!==0.3

这是浮点数误差产生的奇怪现象,想了解细节的话可以看下这篇文章
https://segmentfault.com/a/1190000013632163#articleHeader4

@zejunking
Copy link

https://zhuanlan.zhihu.com/p/28140450
let、const到底有没有变量提升

@dpgirl
Copy link

dpgirl commented Aug 2, 2019

参考文章:
配置: https://www.cnblogs.com/qirui/p/8421372.html
整合项目并调试: https://juejin.im/post/5b78e522f265da432144a3a6
遇到的坑:
1.主要是sdk环境配置问题。从官网下载最新的Android Studio,安装后,发现platform-tools和tools文件不存在,表示Android SDK没安装。这时打开Android Studio,file->setting->Android SDK->安装就行(路径最好是其他路径,不要和Android Studio放在一起)
6

整合vue项目和cordova项目,并安装模拟器进行调试
①在vue项目的同级创建cordova项目(cordova create cordova-app)
② 把打包目录更改为cordova的www目录下。在vue-cli3的配置文件vue.config.js中写入outputDir: './cordova-app/www/'
③打包步骤:
i 修改代码后,cd进入vue项目,npm run build 将vue项目编译打包到cordova-app的www目录;
ii cd进入cordova-app, cordova run android 就可以在模拟器查看了(前提:得先打开模拟器)
④ 安装的模拟器是google 模拟器(Android Sdk ->goole usb driver)
模拟器可以选择别的,或者用真机测试。真机尝试失败了,手机的开发者模式已经打开了,就是没办法连。
8
微信图片_20190802162353
clipboard

@soraliu
Copy link

soraliu commented Aug 2, 2019

简单的批处理命令

# 压缩当前文件夹内所有的文件
ls | grep -v '\.zip$' | xargs -n1 -I '{}' echo "zip -r {}.zip {}/*" | bash -C

管道|xargs提供了一种批量处理文件或者文件夹的方案,类似的例子还有很多

# 批量更新git branch
find `pwd` -type d -depth 1 | xargs -n1 -I '{}' echo "cd  {}; git fetch" | bash -C
# 批量删除本地git branchs
git branch | grep 'feature/*' | xargs git branch -d

@jecyu
Copy link

jecyu commented Aug 3, 2019

2019-08-02

输出指定时间段、作用的提交记录文件

场景:项目经理需要获取更新记录

git log --oneline --after="2019-06-01" --name-status --author="Jecyu" --no-merges 
 -->ChangeLog.txt

更多用法见:https://git-scm.com/book/zh/v1/Git-%E5%9F%BA%E7%A1%80-%E6%9F%A5%E7%9C%8B%E6%8F%90%E4%BA%A4%E5%8E%86%E5%8F%B2

@comeCU
Copy link

comeCU commented Aug 3, 2019

  • LeetCode刷题 【229_majority-element-ii 】medium
    Runtime: 1 ms, faster than 100.00% of Java online submissions for Majority Element II.
    Memory Usage: 40.8 MB, less than 96.52% of Java online submissions for Majority Element II.
class Solution {
    // Boyer-Moore majority vote algorithm
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> list = new ArrayList<Integer>();
        if(nums.length == 0) {
            return list;
        }
        int major1 = nums[0], major2 = nums[0];
        int count1 = 0, count2 = 0;
        for(int i = 0; i < nums.length; i ++) {
            if(major1 == nums[i]) {
                count1 ++;
            } else if(major2 == nums[i]) {
                count2 ++;
            } else if(count1 == 0) {
                major1 = nums[i];
                count1 = 1;
            } else if(count2 == 0) {
                major2 = nums[i];
                count2 = 1;
            } else {
                count1 --;
                count2 --;
            }
        }
        // Start counting below, there may be 1 or 2 eligible.
        count1 = 0;
        count2 = 0;
        for(int i = 0; i < nums.length; i ++) {
            if(nums[i] == major1) {
                count1 ++;
            } else if(nums[i] == major2) {
                count2 ++;
            }
        }
        if(count1 > nums.length / 3) {
            list.add(major1);
        }
        if(count2 > nums.length / 3) {
            list.add(major2);
        }
        
        return list;
    }
}

@KieSun
Copy link
Owner Author

KieSun commented Aug 3, 2019

之前把老的 React 项目升级成了最新版,在使用 hooks 的时候遇到了一个问题。当时通过谷歌找到了问题所在,升级了 react-hot-loader 包以后就顺便解决了问题,为了继续做工作就没有具体去了解原因。

今天有时间了就搜索了一番资料,总结了一下内容:

在正确使用 hooks 的情况下出现了以下报错:

Uncaught Error: Hooks can only be called inside the body of a function component.

Hooks 确实有限制必须在函数组件中使用,但是我确实正确的使用了。于是搜索了一波资料,发现了一个 issus 出现了与我一样的问题:Incompatibility with react-hot-loader

在阅读 issus 的过程中,发现 react-hot-loader 开发者给出了如下解答:

屏幕快照 2019-08-03 下午6.50.33.png

大致意思是无状态组件(也就是函数组件)会被转换成类组件,这是因为无状态组件没有更新的方法。

因此搜索了下 react-hot-loader 的工作原理,发现官方同样给出了一份文档:How React Hot Loader works

内容中有说到为了渲染 react-tree,不得不把所有的无状态组件都转换成了无状态的类组件。

屏幕快照 2019-08-03 下午6.50.51.png

@Yangfan2016
Copy link

Yangfan2016 commented Aug 3, 2019

20190803

写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么

  • 更新组件时判断两个节点是否相同。相同就复用,不相同就删除旧的创建新的
  • 解决在不带 key 的情况下 ,“就地复用” 造成的副作用

误解:写 key 的作用是提高 diff 速度

  • 带 key 反而没有提升性能,因为它会在更新组件时判断两个节点是否相同。相同就复用,不相同就删除旧的创建新的

阅读原文

@Amecy
Copy link

Amecy commented Aug 12, 2019

从掘金过来的,感觉这个项目挺有意思的,大家互相学习吧!
分享一下最近get到的一个小技巧。交换数组指定位置元素位置:

例如: [1 ,2, 3, 4] ===> [1, 2, 4, 3]

function arrIndexExchange(array, x, y){
    array.splice(x - 1, 1, ...array.splice(y - 1, 1, array[x - 1]));
    return array;
};

// x , y是要交换元素的位置(index+1)

function arrIndexExchange(array, x, y){
    let data = [...array];
    [ data[x], data[y] ] = [ data[y], data[x] ];
    return data;
}

这样多好记

@teachat8
Copy link

teachat8 commented Oct 4, 2019

20190729

提高你工作效率的位运算

请注意 位运算适用于 32 位整数,所以精度可能会丢失

  • 用 "|" 取整

let num=1.5
num=num|0; // 1

  • 用 ">>" 取半

let num=4;
num=num>>1; // 2

  • 用 ">>" 加倍

let num=2;
num=num<<1; / / 4

  • 用 "^" 两值交换

let a=1;
let b=2;

a^=b;
b^=a;
a^=b;

// a===2,b===1

  • 用 "&" 判断奇数

let n=3;
let m=4;

n&1===1; // true 奇数
m&1===1; // false 偶数

  • 用 "~" 判断项是否存在

let firstname="Ma";
let fullname="Jack Ma";

let isExist=!!~fullname.indexOf(firstname); // true

应该是用"<<" 表示加倍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests