# 丙升
# 每周收获
# 2021.12.03-2021.12.11
- 了解票据业务。
- 实现oss不使用sdk,policy接口方式上传。
- 了解electron项目结构。
# 2021.12.13-2021.12.17
- 配置bihu-element-ui环境并了解修改组件流程。
# 2021.12.20-2021.12.25
- 了解判断文本是否超出的方法:
clientWidth < scrollWidth
- scrollWidth:对象的实际内容的宽度,不包边线宽度,会随对象中内容超过可视区后而变大。
- clientWidth:对象内容的可视区的宽度,不包滚动条等边线,会随对象显示大小的变化而改变。
# 2022.01.03-2022.01.08
- 了解 Jest 测试框架的使用
# 2022.01.10-2022.01.16
- 了解 electron 在windows无法拖放文件,出现禁止标志的问题 - 在windows的操作系统上,管理员模式下没办法进行鼠标拖放等事件
# 2022.02.07-2022.02.11
- jest单元测试-关于触发emit的问题,使用 wrapper.emitted() (opens new window)
- jest单元测试-修改组件中setup的变量,使用 wrapper.vm.变量 = XXX
- jest单元测试-调用组件中setup的函数,使用 wrapper.vm.函数名
# 2022.02.14 - 2022.02.18
- 了解了
electron
的app.requestSingleInstanceLock()
:- 应用场景:实现应用不多开
https://www.electronjs.org/zh/docs/latest/api/app#apprequestsingleinstancelock
# 2022.02.28 - 2022.03.05
- 实现
Promise添加默认catch
:- 应用场景:为解决
element-confirm
关闭或取消弹窗会reject('close')
或reject('cancel')
,如果不catch会报Uncaught (in promise) cancel
,所以在全局封装默认catch。
- 应用场景:为解决
/**
* 为promise添加默认catch
* @param {Promise} originalPromise 原始promise
* @param {Function} catchFun 默认catch
*/
export function DefaultPromise(originalPromise, catchFun) {
this._promise = originalPromise
this._catchyPromise = Promise.resolve()
.then(() => this._promise)
.catch(err => catchFun(err))
const methods = ['then', 'catch', 'finally']
for (const method of methods) {
this[method] = function(...args) {
this._promise = this._promise[method](...args)
return this
}
}
}
// 调用
let confirmBox = Vue.prototype.$confirm
Vue.prototype.$confirm = (...args) => new DefaultPromise(confirmBox(...args), err => {
// eslint-disable-next-line no-console
['close', 'cancel'].includes(err) ? console.log(err) : console.error(err)
})
# 2022.03.07 - 2022.03.11
学习手写Promise (opens new window)
# 2022.03.21 - 2022.03.25
使用ElementUI报错:
[Violation] Added non-passive event listener to a scroll-blocking 'touchmove' event. Consider marking event handler as 'passive' to make the page more responsive.
- 具体原因是:
- 项目没有添加事件管理者
passive
,而在谷歌浏览器里面 Chrome51 版本以后,Chrome 增加了新的事件捕获机制Passive Event Listeners
passive
告诉前页面内的事件监听器内部是否会调用preventDefault函数
来阻止事件的默认行为,以便浏览器根据这个信息更好地做出决策来优化页面性能。- 当属性
passive的值为true
的时候,代表该监听器内部不会调用preventDefault函数
来阻止默认滑动行为,Chrome浏览器称这类型的监听器为被动(passive)监听器。目前Chrome主要利用该特性来优化页面的滑动性能,所以Passive Event Listeners特性当前仅支持mousewheel/touch相关事件。
- 项目没有添加事件管理者
- 解决方案是:引入default-passive-events
- 相关阅读:Passive Event Listeners (opens new window)
import { eventListenerOptionsSupported } from './util'
const defaultOptions = {
passive: true,
capture: false
};
const supportedPassiveTypes = [
'scroll', 'wheel',
'touchstart', 'touchmove', 'touchenter', 'touchend', 'touchleave',
'mouseout', 'mouseleave', 'mouseup', 'mousedown', 'mousemove', 'mouseenter', 'mousewheel', 'mouseover'
];
const getDefaultPassiveOption = (passive, eventName) => {
if (passive !== undefined) return passive;
return supportedPassiveTypes.indexOf(eventName) === -1 ? false : defaultOptions.passive;
};
const getWritableOptions = (options) => {
const passiveDescriptor = Object.getOwnPropertyDescriptor(options, 'passive');
return passiveDescriptor && passiveDescriptor.writable !== true && passiveDescriptor.set === undefined
? Object.assign({}, options)
: options;
};
const overwriteAddEvent = (superMethod) => {
EventTarget.prototype.addEventListener = function (type, listener, options) {
const usesListenerOptions = typeof options === 'object' && options !== null;
const useCapture = usesListenerOptions ? options.capture : options;
options = usesListenerOptions ? getWritableOptions(options) : {};
options.passive = getDefaultPassiveOption(options.passive, type);
options.capture = useCapture === undefined ? defaultOptions.capture : useCapture;
superMethod.call(this, type, listener, options);
};
EventTarget.prototype.addEventListener._original = superMethod;
};
const supportsPassive = eventListenerOptionsSupported();
if (supportsPassive) {
const addEvent = EventTarget.prototype.addEventListener;
overwriteAddEvent(addEvent);
}
# 2022.05.1 - 2022.05.06
实现 开机自启动 带超管权限的electron程序 :
app.setLoginItemSettings
- 带超管权限运行的程序,不适用
添加注册表
- 带超管权限运行的程序,在64位系统需要在特定的位置添加,但该位置不适用于32位系统
- 带超管权限运行的程序,在32位系统找不到符合的添加位置,360是用另一个非超管程序启动主程序
添加计划任务
- 可兼容任何程序任何系统
/**
* @file 开机自动启动
*/
// 超管权限执行命令库
const { exec } = require('sudo-prompt')
// 默认的自启动注册列表地址(由于客户端需要超管权限,而且是32位程序,用electron官方设置自启动无效,故自行添加注册表)
const START_DEFAULT_KEY = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\\'
/**
* 添加注册表
* @param {String} name 注册名称
* @param {String} value 注册值
* @param {String} keyPath 注册表位置
* @returns {Promise}
*/
export function addRegedit(name, value, keyPath = START_DEFAULT_KEY) {
return new Promise((resolve, reject) => {
try {
const addRegeditCmd = `reg add ${keyPath} /v ${name} /t REG_SZ /d "${value}" /f` // reg add HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run\ /v electron.app.Electron /t REG_SZ /d hello.exe /f
console.log('addRegeditCmd', addRegeditCmd)
exec(addRegeditCmd, { name: 'addRegedit' }, (error, stdout, stderr) => {
console.log('addRegedit', error, stdout, stderr)
if (error) {
reject(error)
}
resolve()
})
} catch (error) {
reject(error)
}
})
}
/**
* 删除注册表
* @param {String} name 注册名称
* @param {String} keyPath 注册表位置
* @returns {Promise}
*/
export function delRegedit(name, keyPath = START_DEFAULT_KEY) {
return new Promise((resolve, reject) => {
try {
const delRegeditCmd = `reg delete ${keyPath} /v ${name} /f` // reg delete HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run\ /v electron.app.Electron /f
console.log('delRegeditCmd', delRegeditCmd)
exec(delRegeditCmd, { name: 'delRegedit' }, (error, stdout, stderr) => {
console.log('delRegedit', error, stdout, stderr)
if (error) {
reject(error)
}
resolve()
})
} catch (error) {
reject(error)
}
})
}
/** 由于以上添加注册表的形式不适用于32位系统,故改用计划任务 */
/**
* 添加开机启动计划任务
* @param {String} name 计划名称
* @param {String} value 程序位置
* @returns {Promise}
*/
export function addSchTask(name, value) {
return new Promise((resolve, reject) => {
try {
const addSchTaskCmd = `schtasks /create /sc ONLOGON /tn "${name}" /tr """"${value}"""" /rl HIGHEST` // schtasks /create /sc ONLOGON /tn "Test Script" /tr """"经纪商.exe"""" /rl HIGHEST
console.log('addSchTaskCmd', addSchTaskCmd)
exec(addSchTaskCmd, { name: 'addSchTask' }, (error, stdout, stderr) => {
console.log('addSchTask', error, stdout, stderr)
if (error) {
reject(error)
}
resolve()
})
} catch (error) {
reject(error)
}
})
}
/**
* 删除计划任务
* @param {String} name 注册名称
* @param {String} keyPath 注册表位置
* @returns {Promise}
*/
export function delSchTask(name) {
return new Promise((resolve, reject) => {
try {
const delSchTaskCmd = `schtasks /delete /TN "${name}" /F` // schtasks /delete /TN "Test Script" /F
console.log('delSchTaskCmd', delSchTaskCmd)
exec(delSchTaskCmd, { name: 'delSchTask' }, (error, stdout, stderr) => {
console.log('delSchTask', error, stdout, stderr)
if (error) {
reject(error)
}
resolve()
})
} catch (error) {
reject(error)
}
})
}