Minimal and Clean blog theme for Hugo
用html字符串生成dom元素
https://stackoverflow.com/a/35385518/6021280
/**
* @param {String} HTML representing a single element
* @return {Element}
*/
function htmlToElement(html) {
var template = document.createElement('template');
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content.firstChild;
}
var td = htmlToElement('<td>foo</td>'),
div = htmlToElement('<div><span>nested</span> <span>stuff</span></div>');
/**
* @param {String} HTML representing any number of sibling elements
* @return {NodeList}
*/
function htmlToElements(html) {
var template = document.createElement('template');
template.innerHTML = html;
return template.content.childNodes;
}
var rows = htmlToElements('<tr><td>foo</td></tr><tr><td>bar</td></tr>');
监听dom元素的class值变化
参考资料:
MutationObserver
这个类可以监听指定 DOM
的变化。
下面的代码创建监听了一个元素,并在class变化时出发回调函数。
let targetNode = document.getElementById('test')
function workOnClassAdd() {
alert("I'm triggered when the class is added")
}
function workOnClassRemoval() {
alert("I'm triggered when the class is removed")
}
// watch for a specific class change
let classWatcher = new ClassWatcher(targetNode, 'trigger', workOnClassAdd, workOnClassRemoval)
// tests:
targetNode.classList.add('trigger') // triggers workOnClassAdd callback
targetNode.classList.add('trigger') // won't trigger (class is already exist)
targetNode.classList.add('another-class') // won't trigger (class is not watched)
targetNode.classList.remove('trigger') // triggers workOnClassRemoval callback
targetNode.classList.remove('trigger') // won't trigger (class was already removed)
targetNode.setAttribute('disabled', true) // won't trigger (the class is unchanged)
class ClassWatcher {
constructor(targetNode, classToWatch, classAddedCallback, classRemovedCallback) {
this.targetNode = targetNode
this.classToWatch = classToWatch
this.classAddedCallback = classAddedCallback
this.classRemovedCallback = classRemovedCallback
this.observer = null
this.lastClassState = targetNode.classList.contains(this.classToWatch)
this.init()
}
init() {
this.observer = new MutationObserver(this.mutationCallback)
this.observe()
}
observe() {
this.observer.observe(this.targetNode, { attributes: true })
}
disconnect() {
this.observer.disconnect()
}
mutationCallback = mutationsList => {
for(let mutation of mutationsList) {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
let currentClassState = mutation.target.classList.contains(this.classToWatch)
if(this.lastClassState !== currentClassState) {
this.lastClassState = currentClassState
if(currentClassState) {
this.classAddedCallback()
}
else {
this.classRemovedCallback()
}
}
}
}
}
}
调试proxy对象
当我们打了断点时,proxy对象的属性看到的都是...
,很不方便。
这些对象都可以在console中打印出来。利用这一点,我们可以先将lodash引入到console中,利用_.cloneDeep方法,将proxy对象的属性克隆一份,然后再打印出来。
fetch('https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js')
.then(response => response.text())
.then(text => eval(text))
_.cloneDeep(this.queryOptions)
正则表达式怎么用
reg, _ := regexp.Compile(`\s+`)
r := reg.ReplaceAll(resBody, []byte(""))
compile string to regexp, then replace all
…趣闻轶事
科技爱好者周刊(第 170 期)
已阅。总结:1. 用alpine(linux)不直接用node。2. 利用docker的缓存机制避免掉不必要的编译时间。
科技爱好者周刊(第 86 期)
科技爱好者周刊(第 67 期)
How to improve software design ability?
…protocol-buffer使用记录
参考资料:
- https://developers.google.com/protocol-buffers/docs/gotutorial
- https://developers.google.com/protocol-buffers/docs/reference/go-generated#package
内容
- 根据自己的需要,定义protocol buffer,定义请求、相应、service。
- protoc生成grpc.go和pb.go文件
- 实现grpc的service接口
- 调用service实现
syntax = "proto3";
package tutorial; // 定义报名,避免命名冲突
option go_package="/services";
import "google/protobuf/timestamp.proto";
message Person {
string name = 1; //
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
google.protobuf.Timestamp last_updated = 5;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person people = 1;
}
每个元素上的“= 1”、“= 2”标记标识字段在二进制编码中使用的唯一“标签”。标记数字 1-15 需要比更高数字少一个字节来编码,因此作为一种优化,您可以决定将这些标记用于常用或重复的元素,而将标记 16 和更高的标记用于不太常用的可选元素。重复字段中的每个元素都需要重新编码标签编号,因此重复字段特别适合这种优化。
…Uml
设置自动引入为单引号
Chrome插件开发
background-warp.js
background.js
// 监听页面的加载完成事件
chrome.webNavigation.onCompleted.addListener(
function (data) {
// 调用sotrage存放或设置一些数据
chrome.storage.local.set({ resolvedBuildValue }, function () {
console.log('Value is set to ' + resolvedBuildValue);
});
// 调用scripting执行插入脚本的操作
chrome.scripting.executeScript({
target: { tabId: data.tabId },
function: function(){
// 可以正常的调用document的相关api控制页面内的元素
},
// files: ['content-script.js'],
});
// 调用scripting执行插入css样式的操作
chrome.scripting.insertCSS(
{
target: { tabId: data.tabId },
css: 'body{background: red;}', // 一个css样式的字符串
}
);
}
)
interface data {
frameId: number
parentFrameId: number
processId: number
tabId: number
timeStamp: number
url: string
}
interface target {
tabId:;
allFrame?: boolean;
}
exceScript
…企业微信机器人
机器人
hover机器人,卡片右上角的编辑按钮可以看到机器人配置说明。 gitlab的webhook可以在mr时发一个请求。企业微信的机器人可以接受消息,但是两边的消息格式不同,需要有一个中间人进行翻译。
总体流程是:发生了mr,发请求到服务器,服务器根据mr消息中的user找到user所属的群,向该群的机器人发送一条消息,同时消息内容要根据mr的action应该不同,有些mr消息(更新,关闭等)不需要处理。
解析mr
mr的数据我们只需要其中几条信息。
{
"user": {
"name": "",
},
"object_attributes": {
"url":"",
"action":"",
}
}
人与机器人的映射
需要两个表来实现这个映射。
- user <-> group
- group <-> robot
因为关系比较简单,可以暂时不用数据库,就手动创建好变量,在代码中维护就行。但是如果数据多来还是需要用数据库。
给机器人的消息
发给机器人的消息格式(https://work.weixin.qq.com/api/doc/90000/90136/91770)
我们使用markdown格式,可以把长长的链接写成一个超链接的形式:
{
"msgtype": "markdown",
"text": {
"content": "【张三】【发起或合并】了mr【[编号](http://123456)】",
"mentioned_list":["wangqing","@all"]
}
}