2-19
1 搜狗输入法 Emoji 表情输入拼音
示例:
dagou,2=✅
chahao,2=❌
https://github.com/yuhangch/zhmoji/blob/master/PhraseEdit.quanpin.txt
2 form-creator 示例
// 使用 json对象 规则生成表单.!!json 不支持函数和正则
export default function jsonMock() {
// 以下是组件的生成规则及参数默认值
return [
// hidden 组件
{
type: 'hidden',
field: 'id',
value: '1',
},
// cascader 多级联动组件
{
type: 'cascader',
title: '所在区域',
field: 'address',
value: 'datunli',
props: {
options: [],
},
effect: {
address: 1,
},
},
// input 输入框组件
{
type: 'input',
title: '商品名称',
field: 'goods_name',
value: 'iphone',
props: {
type: 'search', // 输入框类型,text,textarea 和search
},
on: {
change(val) {
console.log(val);
},
},
validate: [
{ required: true, message: '请输入商品名称', trigger: 'blur' },
],
children: [],
},
// input 输入框组件
{
type: 'input',
title: '商品简介',
field: 'goods_info',
value: '1231231',
props: {
type: 'textarea', // 输入框类型,text,textarea 和其他 原生 input 的 type 值
maxLength: 100,
showWordLimit: true,
},
},
// autoComplete 自动选择组件
{
type: 'autoComplete',
title: '自动完成',
field: 'auto',
value: 'xaboy',
inject: true,
props: {
data: [],
placeholder: '请输入',
},
on: {
search(inject, value) {
inject.self.props.data = !value
? []
: [value, value + value, value + value + value];
},
},
},
{
type: 'object',
title: '对象组件',
field: 'object',
value: { date: '2121-12-12', field: 10, field2: '123123123' },
props: {
rule: [
{
type: 'row',
wrap: { show: true },
children: [
{
type: 'datePicker',
field: 'date',
title: 'date',
col: {
span: 12,
},
},
{
type: 'inputNumber',
field: 'field',
title: 'field',
props: {
disabled: false,
},
validate: [{ required: true, min: 10, type: 'number' }],
col: {
span: 12,
},
},
],
},
{
type: 'input',
field: 'field2',
title: 'field2',
props: {
disabled: false,
},
validate: [{ required: true }],
},
],
},
},
{
type: 'group',
title: '批量添加',
field: 'group',
value: [{ date: '2121-12-12', field: 10, field2: '123123123' }],
suffix: 'suffixsuffix',
props: {
// field: 'field',
rule: [
{
type: 'col',
wrap: { show: true },
children: [
{
type: 'DatePicker',
field: 'date',
title: 'date',
native: false,
// col: {span: 12}
},
{
type: 'inputNumber',
field: 'field',
title: 'field',
props: {
disabled: false,
},
validate: [{ required: true, min: 10, type: 'number' }],
// col: {
// span: 12
// }
},
],
},
{
type: 'input',
field: 'field2',
title: 'field2',
props: {
disabled: false,
},
validate: [{ required: true }],
},
],
},
validate: [
{
required: true,
min: 3,
type: 'array',
message: '最少增加3项',
trigger: 'change',
},
],
},
// radio 单选框组件
{
type: 'radio',
title: '是否包邮',
field: 'is_postage',
value: '0',
options: [
{ value: '0', label: '不包邮', disabled: false },
{ value: '1', label: '包邮', disabled: false },
{ value: '2', label: '未知', disabled: true },
],
props: {
disabled: false,
},
},
// checkbox 复选框付选择
{
type: 'checkbox',
title: '标签',
field: 'label',
value: ['1', '2', '3'],
options: [
{ value: '1', label: '好用', disabled: true },
{ value: '2', label: '方便', disabled: false },
{ value: '3', label: '实用', disabled: false },
{ value: '4', label: '有效', disabled: false },
],
props: {},
},
// switch 开关组件
{
type: 'switch',
title: '是否上架',
field: 'is_show',
value: false,
props: {},
},
// select 下拉选择组件
{
type: 'select',
field: 'cate_id',
title: '产品分类',
value: ['104', '105'],
props: {
multiple: true,
},
options: [
{ value: '104', label: '生态蔬菜', disabled: false },
{ value: '105', label: '新鲜水果105', disabled: false },
{ value: '106', label: '新鲜水果106', disabled: false },
{ value: '107', label: '新鲜水果107', disabled: false },
{ value: '108', label: '新鲜水果108', disabled: false },
],
},
// datePicker 日期选择组件
{
type: 'datePicker',
field: 'section_day',
title: '活动日期',
value: null,
props: {
mode: 'date',
showTime: true,
},
},
// timePicker 时间选择组件
{
type: 'timePicker',
field: 'section_time',
title: '活动时间',
value: '12:08:23',
props: {
type: 'time-range',
// format: 'HH:mm:ss'
},
},
// inputNumber 数组输入框组件
{
type: 'inputNumber',
field: 'sort',
title: '排序',
value: 0,
props: {
mode: 'button',
step: 0.1, // 计数器步长,
precision: 2, // 数值精度
},
},
// rate 评分组件
{
type: 'rate',
field: 'rate',
title: '推荐级别',
value: 3.5,
props: {
count: 10, // 最大分值
allowHalf: true,
},
},
// slider 滑块组件
{
type: 'slider',
field: 'slider',
title: '滑块',
value: [10, 50],
props: {
step: 10,
min: 0, // 最小值
max: 100, // 最大值
range: true, // 是否为范围选择
},
},
{
type: 'wangEditor',
field: 'txt',
title: '富文本框',
value:
'<h1 style="color: #419bf7;">form-create</h1><a href="https://github.com/xaboy/form-create">GitHub</a>',
},
// upload 上传组件
{
type: 'upload',
field: 'pic',
title: '轮播图',
value: [
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
], // input值
props: {
listType: 'picture-card',
action: 'http://192.168.10.10:8324/api/test', // "https://run.mocky.io/v3/e49207f6-4ea4-488a-81ab-01f264fccf63",
showUploadList: true,
onSuccess(file) {
console.log(file);
file.url =
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png';
},
},
},
// frame 框架组件
{
type: 'frame',
title: '素材',
field: 'fodder',
value: ['http://file.lotkk.com/form-create.jpeg'],
props: {
type: 'image', // frame类型,有input,file,image
src: '../iframe.html', // iframe地址
maxLength: 2, // value的最大数量
title: '请选择', // 弹出框标题
},
},
{
type: 'tree',
title: '权限',
field: 'tree',
value: [12, 13, 14],
props: {
data: [
{
title: 'parent 1',
id: 1,
children: [
{
title: 'parent 1-1',
id: 2,
children: [
{
title: 'leaf 1-1-1',
id: 11,
},
{
title: 'leaf 1-1-2',
id: 12,
},
],
},
{
title: 'parent 1-2',
id: 3,
children: [
{
title: 'leaf 1-2-1',
id: 13,
},
{
title: 'leaf 1-2-1',
id: 14,
},
],
},
],
},
], // 展示数据
},
},
];
}
3 表单生成器工作原理
TODO
- 核心原理
- 适配各种UI的原理
[1] https://github.com/xaboy/form-create/tree/3.0
[2] http://form-create.com/v3/designer
4 前端之巅
原因:每日都有更新文章,可以获取到最新前端资讯
5 windows 安装 nvm
[1][nodejs nvm 环境安装踩坑记录](https://blog.csdn.net/hfcaoguilin/article/details/124598084)
[2][win使用nvm安装npm报错的问题](https://www.cnblogs.com/fyjz/p/15945647.html)
6 连续点击事件(触发)
const TARGET_NUM = 5 // 目标值,连续点击5次触发
// 连续点击
function clickContinuity() {
const that = this as any
if (that.clickCountNow < TARGET_NUM - 1) {
if (that.timerContinuity) {
clearTimeout(that.timerContinuity)
that.timerContinuity = null
}
that.clickCountNow++
that.timerContinuity = setTimeout(() => {
that.clickCountNow = 0
}, 300)
} else {
that.clickCountNow++
// TODO 业务逻辑
if (that.timerContinuity) {
clearTimeout(that.timerContinuity)
that.timerContinuity = null
}
// 点击次数归零,重新计数
that.clickCountNow = 0
}
}
7 Jest 自动化测试前言
钩子函数的作用域
describe:分组用,内部可以写钩子函数,且作用域为该 describe
千万千万要注意!!不要在 describe 中写初始化的代码,避免踩坑,一定要写到钩子函数里
快照
使用快照做二次确认
[1][Jest 自动化测试前言](https://itxiaohao.github.io/passages/automated-testing-learn-introduction/#%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%B1%BB%E5%9E%8B)
8 去除van-button的点击效果
&::before {
background-color: transparent !important;
}
[1][Vant Weapp - 去除(清除)<van-button> 按钮组件点击出现灰色背景效果](https://blog.csdn.net/weixin_44198965/article/details/122926557)
9 小程序导入外部字体
// app.ts
fetchFont() {
const source = `url("${getPicturePath('assets/Poppins-Medium.ttf')}")`
const family = 'Poppins'
wx.loadFontFace({
family,
source,
global: true, // 注意加入global参数,否则加载无效
success: () => {
console.log('[字体加载成功]:', family)
},
fail: (err) => {
console.log('[字体加载失败]:', family, err)
},
})
}
10 前端+Nodejs视频传输方案
[1][前端+Nodejs视频传输方案](https://juejin.cn/post/6996844957772283935)
11 小程序区分环境最佳实践
可区分线上、体验、审核、开发环境
原理:wx.getAccountInfoSync方法 + packOptions.ignore选项
export enum EnvVersion {
// 注意:审核环境为开发环境
审核 = 'reviewing',
开发 = 'develop',
体验 = 'trial',
线上 = 'release',
}
export const EnvVersionMap: { [key: string]: string } = {
reviewing: '审核',
develop: '开发',
trial: '体验',
release: '线上',
}
/**
* 获取微信小程序环境
* @returns
*/
function getEnvVersion(): EnvVersion {
// 微信自带的信息,基础库2.2.2
// https://developers.weixin.qq.com/miniprogram/dev/api/open-api/account-info/wx.getAccountInfoSync.html
const accountInfo = wx.getAccountInfoSync()
let envVersion = accountInfo?.miniProgram?.envVersion as EnvVersion
// 审核环境可能值为 develop
// 其他环境也认为是审核环境
if (!envVersion || envVersion === EnvVersion.开发 || !EnvVersionMap[envVersion]) {
envVersion = EnvVersion.审核
}
// 开发环境以本地文件为准
try {
require('./local.env')
envVersion = EnvVersion.开发
} catch (e) {}
console.log('[envVersion]:', envVersion)
return envVersion
}
建立 miniprogram/env/local.env.ts
文件(空文件都可以),并在project.config.json中忽略该文件(不上传到微信上)
{
"packOptions": {
"ignore": [
{
"value": "miniprogram/env/local.env.ts",
"type": "file"
}
],
"include": []
},
}
12 小程序分享
原理:onShareAppMessage和onShareTimeline方法
// behavior
export function obj2query(data: AnyObject | undefined) {
if (!data) {
return ''
}
var _result = []
for (var key in data) {
var value = data[key]
if (value.constructor == Array) {
value.forEach(function (_value) {
_result.push(key + '=' + _value)
})
} else {
_result.push(key + '=' + value)
}
}
return _result.join('&')
}
export const shareBehavior = Behavior({
methods: {
onShareAppMessage: function () {
const { path } = this.getQueryPath()
// 支持自定义页面路径
return {
title: '分享标题',
desc: '分享内容描述',
path,
}
},
onShareTimeline: function () {
// 不支持自定义页面路径,只支持传参
// https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html#onShareTimeline
const { query } = this.getQueryPath()
return {
title: '分享标题',
desc: '分享内容描述',
query,
}
},
// 加上本页参数
getQueryPath() {
const that = this as any
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
const { shareParams } = that.data // 外部加入的query
let query = obj2query(currentPage.options)
query = query ? `${query}&${obj2query(shareParams)}` : obj2query(shareParams)
let path = `/${currentPage.route}`
if (query) {
path = `${path}?${query}`
}
return { query, path }
},
},
})
13 流下载
服务
const express = require("express");
const fs = require("fs");
const path = require("path");
const router = express.Router();
// Stream 传输
router.get("/excel", (req, res) => {
let videoPath = path.resolve(__dirname, "../assets/excel.xlsx");
let readStream = fs.createReadStream(videoPath);
readStream.pipe(res);
});
const app = express();
app.use(router);
app.listen(8000, () => {
console.log(`服务器运行于:http://127.0.0.1:8000`);
});
前端
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script>
</head>
<body></body>
<script>
const url = "http://127.0.0.1:8000/excel";
const requestType = "application/x-download";
const excelType = "application/vnd.ms-excel";
const filename = "file.xlsx";
axios
.get(url, {
headers: {
"Content-Type": requestType,
// token: sessionStorage.getItem("token"),
},
responseType: "blob",
})
.then(function (response) {
let blob = new Blob([response.data], {
type: excelType,
});
if (window.navigator.msSaveOrOpenBlob) {
// 兼容IE10
window.navigator.msSaveBlob(blob, filename);
} else {
// 兼容chrome/firefox
const aTag = document.createElement("a");
aTag.download = filename;
aTag.href = window.URL.createObjectURL(blob);
aTag.click();
URL.revokeObjectURL(aTag.href);
aTag.remove();
}
})
.catch(function () {
//如果不能正常下载给出对应提示
});
</script>
</html>
[1][前端+Nodejs视频传输方案](https://juejin.cn/post/6996844957772283935#heading-4)
[2][前端文件下载 vue实现文件流动态下载(案例详解)](https://blog.csdn.net/weixin_45393094/article/details/118282043)
14 微信小程序如何子组件改变父组件数据
[1][微信小程序如何子组件改变父组件数据](https://segmentfault.com/q/1010000021954313)
15 chatgpt
[1] https://platform.openai.com/account/api-keys
[2][5sim接码平台](https://5sim.net/zh)
[3][chatgpt-web](https://github.com/Chanzhaoyu/chatgpt-web)
[4][chatgpt-api](https://github.com/transitive-bullshit/chatgpt-api)
16 KeepAlive 中不能有杂项
正确✅
<RouterView v-slot="{ Component, route }">
<Transition
name="fade"
mode="out-in"
>
<KeepAlive :max="10">
<div :key="route.fullPath">
<component :is="Component"></component>
</div>
</KeepAlive>
</Transition>
</RouterView>
错误❌
<KeepAlive :max="10">
<component :is="Component"></component>
</KeepAlive>
<KeepAlive :max="10">
<!-- 写一段注释 -->
<component :is="Component"></component>
</KeepAlive>
17 vue3 动态设置 before
通过css变量实现
<div :style="{ '--bgColor': color }"></div>
div::before {
background-color: var(--bgColor);
}