//存储点击位置的数组。 var points = [];
canvas.addEventListener('click', e => { var x = e.pageX; var y = e.pageY; var color = { r: Math.floor(Math.random() * 256), g: Math.floor(Math.random() * 256), b: Math.floor(Math.random() * 256), a: 1 };
points.push({ x: x, y: y, color: color })
return ( <FitScreenwidth={1920}height={1080}mode="fit"> <divclassName="App"> <div> <ahref="https://vitejs.dev"target="_blank"rel="noreferrer"> <imgsrc="/vite.svg"className="logo"alt="Vite logo" /> </a> <ahref="https://reactjs.org"target="_blank"rel="noreferrer">
React logo </a> </div> <h1>Vite + React</h1> <divclassName="card"> <buttononClick={() => setCount(count => count + 1)}>
count is {count} </button> <p>
Edit <code>src/App.tsx</code> and save to test HMR </p> </div> <pclassName="read-the-docs">
Click on the Vite and React logos to learn more </p> </div> </FitScreen>
)
}
以上报文中就可以看到,使用了OPTIONS请求,浏览器根据上面的使用的请求参数来决定是否需要发送,这样服务器就可以回应是否可以接受用实际的请求参数来发送请求。Access-Control-Request-Method告知服务器,实际请求将使用 POST 方法。Access-Control-Request-Headers告知服务器,实际请求将携带两个自定义请求标头字段:X-PINGOTHER 与 Content-Type。服务器据此决定,该实际请求是否被允许。
exporttypeIListProps{ /**
* Custom suffix element.
* Used to append element after list
*/
suffix?: React.ReactNode; /**
* List column definition.
* This makes List acts like a Table, header depends on this property
* @default []
*/
columns?: IColumn[]; /**
* List dataSource.
* Used with renderRow
* @default []
*/
dataSource?: Array<Record<string, any>>;
}
exporttypeIVisibleProps = { /**
* The visible state of the component.
* If you want to control the visible state of the component, you can use this property.
* @defaultfalse
*/
visible?: boolean; /**
* The default visible state of the component.
* If you want to set the default visible state of the component, you can use this property.
* The component will be controlled by the visible property if it is set.
* @defaultfalse
*/
defaultVisible?: boolean; /**
* Callback when the visible state of the component changes.
*/
onVisibleChange?: (visible: boolean, ...args) =>void;
};
如果你正在封装一个表单类型的组件,未来可能会配合 antd/ fusion 等 Form 组件来消费,以下这些类型定义你可能会需要到:
exporttypeIFormProps = { /**
* Field name
*/
name?: string;
/**
* Field label
*/
label?: ReactNode;
/**
* The status of the field
*/
state?: "loading" | "success" | "error" | "warning";
/**
* Whether the field is disabled
* @defaultfalse
*/
disabled?: boolean;
/**
* Size of the field
*/
size?: "small" | "medium" | "large";
/**
* The min value of the field
*/
min?: number;
/**
* The max value of the field
*/
max?: number;
};
选择类型(⭐️⭐️⭐️⭐️)
如果你正在开发一个需要选择的组件,可能以下类型你会用到:
exportinterfaceISelectionextends object = Record<string, any>> { /**
* The mode of selection
* @default 'multiple'
*/
mode?: "single" | "multiple"; /**
* The selected keys
*/
selectedRowKeys?: string[]; /**
* The default selected keys
*/
defaultSelectedRowKeys?: string[]; /**
* Max count of selected keys
*/
maxSelection?: number; /**
* Whether take a snapshot of the selected records
* If true, the selected records will be stored in the state
*/
keepSelected?: boolean; /**
* You can get the selected records by this function
*/
getProps?: (
record: T,
index: number ) => { disabled?: boolean; [key: string]: any }; /**
* The callback when the selected keys changed
*/
onChange?: (
selectedRowKeys: string[],
records?: Array,
...args: any[] ) =>void; /**
* The callback when the selected records changed
* The difference between `onChange` is that this function will return the single record
*/
onSelect?: (
selected: boolean,
record: T,
records: Array,
...args: any[] ) =>void; /**
* The callback when the selected all records
*/
onSelectAll?: (
selected: boolean,
keys: string[],
records: Array,
...args: any[] ) =>void;
}
// 使用不存在的文件注册,失败回调(拒绝) navigator.serviceWorker.register('./doesNotExist.js') .then(console.log, console.error); // TypeError: Failed to register a ServiceWorker: // A bad HTTP response code (404) was received // when fetching the script. 复制代码
function deviceOnline() {
if (isShowTip) {
toast.showToast(1, "device online")
}
isShowTip = 0
}
function setData(data) {
// console.log("line:136 data==> ", data)
for (let i = data.length - 1; i >= 0; i--) {
let item = data[i]
// console.log("line:138 item==> ", item)
optionTemperature.series[0].data.push(item.temperature)
optionHumidity.series[0].data.push(item.humidity)
optionHumidity.xAxis.data.push(moment(item.updateDatetime).format("MM-DD/HH:mm:ss"))
optionTemperature.xAxis.data.push(moment(item.updateDatetime).format("MM-DD/HH:mm:ss"))
}
ChartTemperature.setOption(optionTemperature);
ChartHumidity.setOption(optionHumidity);
}
function onTimeout() {
$("#statusText").text("device offline")
toast.showToast(3, "device offline")
isShowTip = 1
document.getElementById("Temperature").innerHTML = "No data"
document.getElementById("Humidity").innerHTML = "No data"
$(".statusLight").removeClass("on")
$(".statusLight").addClass("off")
}
function generateRandomString() {
let result = '';
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let charactersLength = characters.length;
for (let i = 0; i < 6; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
});
DELIMITER $$ CREATE TRIGGER delete_oldest_data AFTER INSERTON wemosd1_dht11 FOR EACH ROW BEGIN -- 如果数据量超过43200(每两秒插入一条,这是一天的量)条,调用存储过程删除最早的一条数据 IF (SELECTCOUNT(*) FROM wemosd1_dht11) > 43200 THEN CALL delete_oldest(); END IF; END$$ DELIMITER ; -- 创建存储过程 CREATE PROCEDURE delete_oldest() BEGIN -- 删除最早的一条数据 deletefrom wemosd1_dht11 orderby id asclimit1 END$$ DELIMITER ;
$ yo eslint:rule
? What is your name? // guming-eslint-plugin-custom-lodash
? What is the plugin ID? // 插件名 (eslint-plugin-xxx)
? Type a short description of this plugin: // 描述你的插件是干啥的
? Does this plugin contain custom ESLint rules? Yes // 是否为自定义Eslint 校验规则
? Does this plugin contain one or more processors? No // 是否需要处理器
接下来我们为插件创建一条规则,执行如下命令:
$ npx yo eslint:rule
这也是一个交互式命令,如下:
? What is your name? // guming-eslint-plugin-custom-lodash
? Where will this rule be published? ESLint Plugin
? What is the rule ID? // 规则名称 lodash-auto-import
? Type a short description of this rule: // 规则的描述
? Type a short example of the code that will fail: // 这里写你这条规则校验不通过的案例代码
Nginx 是一款由俄罗斯的程序设计师 Igor Sysoev 所开发的高性能的 http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,它的主要功能有:
反向代理
负载均衡
HTTP 服务器
目前大部分运行的 Nginx 服务器都在使用其负载均衡的功能作为服务集群的系统架构。
功能说明
在上文中介绍了三种 Nginx 的主要功能,下面来讲讲具体每个功能的作用。
一、反向代理(Reverse Proxy)
介绍反向代理前,我们先理解下正向代理的概念。打个比方,你准备去看周杰伦的巡演,但是发现官方渠道的票已经卖完了,所以你只好托你神通广大的朋友A去内部购票,你如愿以偿地得到了这张门票。在这个过程中,朋友A就起到了一个正向代理的作用,即代理了客户端(你)去向服务端(售票方)发请求,但服务端(售票方)并不知道源头是谁发起的请求,只知道是代理服务(朋友A)向自己请求的。由这个例子,我们再去理解下反向代理,比如我们经常接到10086或者10000的电话,但是每次打过来的人都不一样,这是因为10086是中国移动的总机号,分机打给用户的时候,都是通过总机代理显示的号码,这个时候客户端(你)无法知道是谁发起的请求,只知道是代理服务(总机)向自己请求的。
而官方的解释说明就是,反向代理方式是指以代理服务器来接受 Internet 上 的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 Internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
下面贴一段简单实现反向代理的 Nginx 配置代码:
server {
listen 80;
server_name localhost;
client_max_body_size 1024M;
#!/bin/sh # husky # Hook created by Husky # Version: 2.7.0 # At: 2023/2/2 13:14:26 # See: https://github.com/typicode/husky#readme # From # Directory: /Users/frank/Documents/work/worktile/wt-cronus/projects/pc-flow-sky/node_modules/husky # Homepage: undefined scriptPath="node_modules/husky/run.js" hookName=`basename "$0"` gitParams="$*" debug() { if [ "${HUSKY_DEBUG}"="true" ] || [ "${HUSKY_DEBUG}"="1" ]; then echo"husky:debug $1" fi } debug "$hookName hook started" if [ "${HUSKY_SKIP_HOOKS}"="true" ] || [ "${HUSKY_SKIP_HOOKS}"="1" ]; then debug "HUSKY_SKIP_HOOKS is set to ${HUSKY_SKIP_HOOKS}, skipping hook" exit0 fi if ! command -vnode >/dev/null 2>&1; then echo"Info: can't find node in PATH, trying to find a node binary on your system" fi if [ -f"$scriptPath" ]; then # if [ -t 1 ]; then # exec < /dev/tty # fi if [ -f ~/.huskyrc ]; then debug "source ~/.huskyrc" . ~/.huskyrc fi node_modules/run-node/run-node "$scriptPath"$hookName"$gitParams" else echo"Can't find Husky, skipping $hookName hook" echo"You can reinstall it using 'npm install husky --save-dev' or delete this hook" fi
看了下,感觉没啥用,就是一个检测 husky 有没有安装的脚本。我们这里直接使用下面的替换掉:
#!/bin/sh errorForOnly() { result="" for FILE in`git diff --name-only --cached`; do # 忽略检查的文件 if [[ $FILE== *".html"* ]] ; then continue fi # 匹配不能上传的关键字 grep'serial.only\|console.log(\|alert('$FILE2>&1 >/dev/null if [ $?-eq0 ]; then # 将错误输出 echo'❌'$FILE'此文件中包含 [only]、[console]、[alert] 中的关键字, 删除后再次提交' # exit 1 result=0 else result=1 fi done if [[ ${result}==0 ]];then exit1 fi echo"✅ All files is OK!" } errorForOnly
switch (app.status) {
case LOAD_ERROR:
if (appShouldBeActive && currentTime - app.loadErrorTime >= 200) {
appsToLoad.push(app);
}
break;
case NOT_LOADED:
case LOADING_SOURCE_CODE:
if (appShouldBeActive) {
appsToLoad.push(app);
}
break;
case NOT_BOOTSTRAPPED:
case NOT_MOUNTED:
if (!appShouldBeActive && getAppUnloadInfo(toName(app))) {
appsToUnload.push(app);
} else if (appShouldBeActive) {
appsToMount.push(app);
}
break;
case MOUNTED:
if (!appShouldBeActive) {
appsToUnmount.push(app);
}
break;
// all other statuses are ignored
}
});
<scripttype="text/javascript"> function test(a) { console.log(a); var a = 10; console.log(a); function a() { consoel.log('这是函数a'); } } test(1); </script>
如果你心中的结果跟答案一致,说明已经清楚了局部函数预编译的四个步骤了
到test函数执行之前AO对象中a的值为a的函数体这个应该没有什么问题吧?所以第一个log打印出来的是a的函数体,第二个log之前由于有var a = 10;,这个经过变量的声明提升后可以看做是a = 10;,走到这里这里AO中的a被赋值为10,所以第二个log打印的就是10。
第一个log打印a函数的函数体没有问题吧?第二个log为什么会报错呢?因为GO对象中保存的a属性在第一次log的时候保存的是a的函数体,但是下面有个a=10;*的赋值,这个时候GO中的a就被修改成10了,后面调用*a(1)*函数的时候,找到GO中的a,这个时候a是number数字而不是函数,所以会报错说*a is not a function。
看看例子六的输出结果是不是符合自己的心里预期。我们都知道函数内部有变量会优先使用自身内部的变量,其实也可以转化成AO和GO来理解。 第一个log输出的时候找到自身的AO中有属性a,且这个值是实参传递过来的,所以是10。 第二个log由于前面有a=100所以a被赋值成了100。 第三个log会找自己的AO,发现自己的AO里没有这个b属性,就会去找到父函数的AO,由于这里父函数是全局函数了,所以就去找GO里有没有b属性,有的话就输出了GO里的b的值,所以是2。(如果这里GO中也没有b属性的话,就会报b is not defined的错误了) 第四个log输出的就是自身AO也就是GO中的a属性的值了。