首页
高清壁纸
统计
留言
推荐
Json工具
Search
1
通过iframe嵌套时,被302重定向怎么办?
2,262 阅读
2
关于 MySQL Binlog 权限
1,072 阅读
3
JS常用监听事件【监听键盘、触控、鼠标、多媒体、打印、剪贴板、表单等事件】
992 阅读
4
Windows安装PECL
963 阅读
5
JS实现Web应用或网站发送浏览器Notification通知
766 阅读
抽奖系统
tony爱编程
收藏分享
经验总结
其它杂类
常用工具
登录
Search
标签搜索
抽奖系统
html+JS
抽奖HTA
js
MySQL
HTA版
源码
hta属性
ecshop
Meta
拖动
javascript
MySQL函数
git提交慢
提交卡
laravel-admin
FSO
redis
文件操作
mysql备份
Tony哥
累计撰写
55
篇文章
累计收到
11
条评论
首页
栏目
抽奖系统
tony爱编程
收藏分享
经验总结
其它杂类
常用工具
页面
高清壁纸
统计
留言
推荐
Json工具
搜索到
49
篇与
的结果
2024-07-19
go文字生成图片的较靠谱的方法
我们经常会遇到一些情况,在转换昵称做图片海报的时候,出现字体库内资源不够导致字体无法转化的清理,搜遍全网也没有一个很好的解决办法,于是就自动动手封装了一个,原理还是逃脱不掉字体库,于是我封装了一些常用的字体库(且支持中日韩和一些常用的符号图形)使用说明引入扩展 go get gitee.com/archn/act-red-go加载依赖 go mod tidy导入方法 import "gitee.com/archn/act-red-go/text-to-img/toimage"使用方法:toimage.RenderTextToPNG(text string, fontPaths []string, outputOrFile any, args ...TextToPngArgs) error文字转换为图片方法,用于常规海报生成等fontPaths 默认使用内置字体 如果要新增请注意 排序靠前的优先匹配outputOrFile 可以是文件名称路径(绝对路径请已/开头)、也可以是文件句柄os.File用于内容写入args 为可选参数,用于配置文字的颜色大小图片大小等基本信息详情请关注对应结构体,(默认12px|黑色|自适应)toimage.ConvertRemoteImageToPNG(imageURL string, output *os.File) error任意图片转png方法使用例子package main import "gitee.com/archn/act-red-go/text-to-img/toimage" func main() { err := toimage.RenderTextToPNG("新ღღ你不认识吗?A中国🐂나사랑해요12abα🌸double 🇨🇳 🧧ৡღ ℒℴѵℯ依·訫ꦿ⸙ ঞ 不留遗憾 ོꦿ ࿐ ₅₂ₒ ꧁哥 ໊是ꕥ电ꦿ工꧂", nil, "abc.png", toimage.TextToPngArgs{Size: 30}) if err != nil { return } } 包共享地址act-red-go 如有需要请自行扩展或提供宝贵建议
2024年07月19日
36 阅读
0 评论
0 点赞
2023-10-20
go进程独占文件的实现,可用于单进程锁等其它逻辑
在网上搜了一大圈,找到了一个独占文件的逻辑用了下,发出来和大家分享一下,写的还是不错的,我试了其它的一些方法,比如说 _, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, os.ModeExclusive) 这些乱起八糟的说明还是不能行,结果这套代码可以,那么就分享一下吧!好吧直接上代码package main import ( "flag" "fmt" "os" "syscall" "time" ) var filename string var openSec int64 func main() { flag.Int64Var(&openSec, "openSec", 60, "独占的秒数") flag.StringVar(&filename, "filename", "D:/dd.txt", "需要独占打开得文件") flag.Parse() lockFile(filename, openSec) } func lockFile(filename string, openSec int64) error { _, err := os.Stat(filename) if err != nil { return fmt.Errorf("打开文件[%s]失败,%v", filename, err) } p, err := syscall.UTF16PtrFromString(filename) if err != nil { return err } fd, err := syscall.CreateFile(p, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, // syscall.CREATE_ALWAYS syscall.FILE_ATTRIBUTE_NORMAL, 0, ) if err != nil { return err } time.Sleep(time.Second * time.Duration(openSec)) syscall.Close(fd) return nil }以上代码是别的写的,那么我拿他来做了个函数封装,用于我的程序单进程锁其实下面这些封装是不够完美的,相当于跑了一个独立线程来锁死文件,由于go还是不怎么熟练先凑合用了,如果你有更合适的方案欢迎发过来一起学习一下func main() { executablePath, _ := os.Executable() path = filepath.Dir(executablePath) if !lockProcess() { s := "仅能执行一个进程" writeToLogFile(s) fmt.Println(s) return } // 业务逻辑... } // 判断是否与其它实例并行 func lockProcess() bool { filePath := filepath.Join(path, ".lock") file, err := os.OpenFile(filePath, os.O_CREATE, 0666) if err != nil { return false } file.Close() go func() { err := lockFile(filePath) if err != nil { return } for { time.Sleep(time.Hour * 1000) } }() return true } func lockFile(filename string) error { _, err := os.Stat(filename) if err != nil { return fmt.Errorf("打开文件[%s]失败,%v", filename, err) } p, err := syscall.UTF16PtrFromString(filename) if err != nil { return err } _, err = syscall.CreateFile(p, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, // syscall.CREATE_ALWAYS syscall.FILE_ATTRIBUTE_NORMAL, 0, ) if err != nil { return err } return nil }
2023年10月20日
302 阅读
1 评论
0 点赞
2023-10-13
php swoole的并发查询封装
说明:这是基于swoole_process封装的一个并发执行类,代码实现您可以做下参考! 个人在项目上用还是有挺好用的,使用时需要注意的是如果您使用的不是laravels框架,那么要注意以下两个地址根据您的框架做下调整:DB::disconnect(); 看您的框架使用哪个方法,意思是每创建一个进程需要断开重连一个mysql否则可能会造成报错,当然如果你的并发中不牵扯到sql查询可以注释掉这个Cache:: 缓存支持,由于通道支持处理的字符有限,我们通过缓存来实现数据的交换,根据您的框架支持或干脆使用redis实现数据交换即可,这里您可以自行改造。好了我们直接上代码: /** * 并发请求类 - 不支持并发将自动使用串行 * @return object {"getKey":"获取key",“getCount”:"获取并发数","add":"添加并发任务","run":"开始运行任务并返回结果","onError":"监听错误信息","onSuccess":"监听成功信息"} * @example $P = cdpProcess(); * $P->add( * function(){ * return 任务结果 * }, * "[可选]自定义id" //返回任务结果键名将为此值 * ); * $data = $P->run(); //开始任务 */ function cdpProcess() { return new class { private $uuid; private $installed = 0; private $worker = []; private $errCall = []; private $dataCall = []; private $index = 0; public function __construct() { if (function_exists("swoole_version")) { $this->installed = 1; } $this->uuid = uniqid(mt_rand(1, 100)); } public function getKey(): string { return $this->uuid; } public function getCount(): int { return count($this->worker); } /** * 添加执行方法进入队列 * @param callable $callback 任务逻辑回调 * @param int|string $index_name 可选任务自定义id否则 * @return $this */ public function Add(callable $callback, $index_name = null) { $key = $this->getKey()."_".$this->index; if ($this->installed) { $pro = new \swoole_process(function (\swoole_process $work) use ($callback, $index_name, $key) { try { DB::disconnect(); //始终使用新连接规避并发冲突 $d = $callback($index_name); Cache::put( $index = 'Process:' . $key, json_encode($d, 320), 5 ); $work->write('{"key":"' . $index . '","index_name":"' . $index_name . '"}'); } catch (\Exception $e) { $work->write(json_encode(['err' => $e->getMessage()])); } $work->exit(0); }, true); $this->worker[] = $pro; } else { $this->worker[] = new class($callback, $index_name) { private $callback; private $index_name; public function __construct(callable $callback, $index_name = null) { $this->callback = $callback; $this->index_name = $index_name; } public function start() { try { $d = ($this->callback)($this->index_name); } catch (\Exception $e) { $d = ['err' => $e->getMessage()]; } return [$d, $this->index_name]; } }; } $this->index++; return $this; } /** * 错误回调 * @param callable $errCallBack * @return $this */ public function onError(callable $errCallBack) { $this->errCall[] = $errCallBack; return $this; } /** * 完成数据回调 * @param callable $dataCallBack * @return $this */ public function onSuccess(callable $dataCallBack) { $this->dataCall[] = $dataCallBack; return $this; } /** * 启动并返回结果 * @return array */ public function run(): array { $data = $err = []; foreach ($this->worker as $i => $pro) { $s = $pro->start(); if (!$this->installed) { empty($s[1]) || $i = $s[1]; if (!empty($s[0]['err'])) $err[$i] = $s[0]['err']; else $data[$i] = $s[0]; } } if ($this->installed) { foreach ($this->worker as $i => $pro) { if (!empty($d = $pro->read())) { $d = json_decode($d, 1); empty($d["index_name"]) || $i = $d["index_name"]; if (!empty($d['err'])) $err[$i] = $d['err']; else { $data[$i] = json_decode(Cache::pull($d['key'], null), 1); } } unset($this->worker[$i]); } while (\swoole_process::wait()); } empty($err) && $this->ErrCallback($err); $this->DataCallback($data); return $data; } private function ErrCallback(array $err) { foreach ($this->errCall as $fun) { try { $fun($err); } catch (\Exception $e) { } } } private function DataCallback(array $data) { foreach ($this->dataCall as $fun) { try { $fun($data); } catch (\Exception $e) { } } } }; }
2023年10月13日
199 阅读
0 评论
0 点赞
2023-08-25
HTML 屏蔽F12及右键的通用方法
<h1>HTML 屏蔽F12及右键的通用方法</h1> <script type="text/javascript"> //禁用F12 window.onkeydown = window.onkeyup = window.onkeypress = function (event) { // 判断是否按下F12,F12键码为123 if (event.keyCode == 123) { event.preventDefault(); // 阻止默认事件行为 window.event.returnValue = false; } } //屏蔽右键菜单 document.oncontextmenu = function (event) { if (window.event) { event = window.event; } try { var the = event.srcElement; if (!((the.tagName == "INPUT" && the.type.toLowerCase() == "text") || the.tagName == "TEXTAREA")) { return false; } return true; } catch (e) { return false; } } </script>
2023年08月25日
247 阅读
0 评论
1 点赞
2023-08-22
go实现的SSE长连接封装
此方法自己尝试过可以借鉴参考,升级改造请自便package sse import ( "fmt" "github.com/gin-gonic/gin" "net/http" "time" ) // - SSE 相关封装 ----------------------- /* 输出说明: 1. Data等于空 不输出 2. Data+Event与上一个输出一致 不重复输出 3. 业务逻辑报错会向前端发出发送一个close事件 需要前端收到后主动close()请求 前端示例: const es = new EventSource(url+'auth-token='+token), listener = function (event) { console.log(event); var div = document.createElement("div");var type = event.type; div.appendChild(document.createTextNode(type + ": " + (type === "message" ? event.data : es.url)));document.body.appendChild(div); }; es.addEventListener("open", listener); es.addEventListener("message", listener); es.addEventListener("error", listener); es.addEventListener("close", function(ret){ es.close(); listener(ret) }); */ // MessageEvent 定义 SSE 事件 type MessageEvent struct { Id string Event string // Data+Event与前一个输出一致 不输出 Data string // Data等于空 不输出 } // 实现 SSE 事件的 String() 方法 func (e MessageEvent) String() string { s := "" if e.Id != "" { s += "id:" + e.Id + "\n" } if e.Event != "" { s += "event:" + e.Event + "\n" } s += fmt.Sprintf("data:%s\n\n", e.Data) return s } // SseOut see协议输出 // // fun(i 循环计数器)(事件结构体,下一个循环延迟时间) 该函数执行业务逻辑并将结果写入通道 func SseOut(c *gin.Context, T func(i int64) (MessageEvent, time.Duration, error)) { defer func(){}() messageChan := make(chan MessageEvent, 5) c.Header("Content-Type", "text/event-stream") c.Header("Cache-Control", "no-cache") c.Header("Connection", "keep-alive") w := c.Writer w.WriteHeader(http.StatusOK) flusher, _ := w.(http.Flusher) temp := "" //结果比对临时变量 var Err error // 监听客户端信号 closeNotify := c.Request.Context().Done() go func() { defer func() { if err := recover(); err != nil { // 捕获到 panic return } }() <-closeNotify close(messageChan) return }() // 执行业务逻辑 go func() { defer func() { if Err != nil { close(messageChan) return } if err := recover(); err != nil { // 捕获到 panic return } }() // 通道活性探测利用业务空闲时间独立执行 i := int64(0) for { e, t, err := T(i) if err != nil { Err = err break } //--两次结果一致的数据阻止输出 if temp != e.Data+e.Event { temp = e.Data + e.Event } else { e.Data = "" } if e.Data != "" { i++ messageChan <- e } else { messageChan <- MessageEvent{ Event: "__ping__", } } if t != 0 { time.Sleep(t) } } }() // SSE 监听并输出 for { if message, ok := <-messageChan; ok && Err == nil { if message.Event == "__ping__" { continue } fmt.Fprintf(w, "%s", &message) flusher.Flush() } else { if Err != nil { // 向客户端发送 SSE 事件 fmt.Fprintf(w, "%s", &MessageEvent{ Id: "-500", Event: "close", Data: Err.Error(), }) // 刷新 response buffer flusher.Flush() } break } } } 引用其它业务逻辑自行根据业务需求写入.... sse.SseOut(c, func(index int64) (Row sse.MessageEvent, Sleep time.Duration, Err error) { // 下一轮循环延迟时间 Sleep = time.Second * 3 // 数据 Row.Data = "" Row.Id = fmt.Sprintf("%d", index) Row.Event = action //--登录状态事件 if index > 0 { return } return }) ....
2023年08月22日
345 阅读
0 评论
0 点赞
2023-05-08
laravel-admin 提交表单时遇到 “Call to a member function getAttribute() on null” 报错的解决
先看下报错内容:{ "message": "Call to a member function getAttribute() on null", "exception": "Error", "file": "D:\\WWW\\src\\vendor\\encore\\laravel-admin\\src\\Form.php", "line": 413, "trace": [ { "file": "D:\\WWW\\src\\vendor\\encore\\laravel-admin\\src\\Form.php", "line": 393, "function": "applayFieldDisplay", "class": "Encore\\Admin\\Form", "type": "->" }, { "file": "D:\\WWW\\src\\vendor\\encore\\laravel-admin\\src\\Form.php", "line": 352, "function": "ajaxResponse", "class": "Encore\\Admin\\Form", "type": "->" }, ... }这是一个快捷表单提交问题的报错问题,问题困扰了我好长时间,起初以为是我哪里我弄错类型了,反复尝试无果,最终顺着错误来源去撸了一遍,发现“src/vendor/encore/laravel-admin/src/Form.php”的 413行 $newValue = $this->model->fresh()->getAttribute($field->column());的fresh返回null 所以导致 “getAttribute” 报错,好了我们寻找下 fresh 看是做啥用的Reload a fresh model instance from the database.这么一看没问题,这是从数据库加载实例用的,那我就无解了,只能怀疑是 “$this->exists” 了,继续撸,于是我找到了这个方法,马上顿悟!报错是因为没有执行到 $this->exists = true; 导致实例为空,我看了下注释解决思路来了,原来表设计的时候我的id主键是非自增的,需要我在模型中明确为非自增解决:找到我的model,新增一行 public $incrementing=false; 搞定
2023年05月08日
503 阅读
0 评论
0 点赞
2023-04-14
laravel-admin中单独定义某页面模板 如“footer.blade.php”
关于laravel-admin仅仅修改个版权的事儿在网上搜了一圈,想只想改改版权,不想动别的,但是结果基本上都是官网提供的帮助文档的方法直接修改所有模板的路径copy模板,后面再升级了万一遇上个啥结构变化都要再改一遍属实有些坑啊,于是咱们就找到了laravel的视图的基本监听方法composer,结果解决了问题。好了直接上代码:还是老办法 打开/app/Admin/bootstrap.php,添加下面代码/** * 定制单页面模板 */ app('view')->composer('admin::*', function (Illuminate\View\View $view) { $views=[ 'admin::partials.footer'=>[ 'path' => resource_path('views/footer.blade.php') ] ]; if(!empty($views[$index=$view->getName()])){ $view->setPath($views[$index]['path']); } });搞个模板/resources/views/footer.blade.phpp<!-- Main Footer --> <footer class="main-footer"> <!-- To the right --> <div class="pull-right hidden-xs"> @if(config('admin.show_environment')) <strong>Env</strong> {!! config('app.env') !!} @endif @if(config('admin.show_version')) <strong>Version</strong> {!! \Encore\Admin\Admin::VERSION !!} @endif </div> <!-- Default to the left --> <strong>Powered by <a href="http://www.archn.cn" target="_blank">技术支持</a></strong> </footer> 大功告成 ::(茶杯)
2023年04月14日
178 阅读
0 评论
0 点赞
2023-02-24
laravel或lumen将日志上报至kafka
lumen或laravel 将日志上报至kafka大家都清楚 Lumen 算是一个精简版的 Laravel,针对速度优化了框架的加载方式,多余的功能需要自行开启。那么在精简版中日志的上报配置方面lumen也做了精简,本文中将分别介绍这两者日志上报的基本方法,咱们主要还是依赖hhxsv5/laravel-kafka-logger,下面是方法和步骤(Laravel 和 lumen的安装咱们就略过了)咱们先安装php的rdkafka扩展要求依赖要求php-rdkafka>=4.0.0安装方法git clone --depth 1 https://github.com/edenhill/librdkafka.git /tmp/librdkafka && cd /tmp/librdkafka && ./configure && make -j$(nproc) && make install && rm -rf /tmp/librdkafka pecl install rdkafka安装 laravel-kafka-logger在项目目录,根据您的项目版本运行如下脚本# Laravel 5.x composer require "hhxsv5/laravel-kafka-logger:~1.0.0" # Laravel 6.x & 7.x composer require "hhxsv5/laravel-kafka-logger:~2.0.0"lavael 上配置修改配置文件 config/logging.phpreturn [ 'channels' => [ //..., 'kafka' => Hhxsv5\LKL\KafkaLogger::getDefinition(['topic' => env('LOG_KAFKA_TOPIC', 'laravel-logs')]), ], ];lumen 上配置在app/Providers目录新增日志扩展类LogServiceProvider.php<?php namespace App\Providers; use Hhxsv5\LKL\KafkaLogHandler; use Illuminate\Support\ServiceProvider; use RdKafka\Conf; use Monolog\Logger; class LogServiceProvider extends ServiceProvider { /** * Configure logging on boot. * * @return void */ public function boot() { $this->createLogger([ 'driver' => 'custom', 'via' => static::class, 'name' => config('app.name'), 'topic' => env('LOG_KAFKA_TOPIC', 'php-logs'), 'fallback' => 'daily', 'flush_timeout_ms' => 5000, 'settings' => [ // see https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md 'metadata.broker.list' => env('LOG_KAFKA_BROKER_LIST', '127.0.0.1:9092'), 'queue.buffering.max.ms' => 3000, // < flush_timeout_ms, send messages ASAP 'socket.keepalive.enable' => true, 'log_level' => LOG_WARNING, ], // 'tap' => [App\Library\LogFormatter::class], //--格式化日志 ]); } /** * Register the log service. * * @return void */ public function register() { } private function createLogger($config){ if (!isset($config['fallback'])) { $config['fallback'] = 'daily'; } if (!isset($config['flush_timeout_ms'])) { $config['flush_timeout_ms'] = 60000; } if (!isset($config['level'])) { $config['level'] = Logger::DEBUG; } if (!isset($config['bubble'])) { $config['bubble'] = true; } $producerConf = new Conf(); foreach ($config['settings'] as $key => $value) { $producerConf->set($key, $value); } $producerConf->setLogCb(function ($kafka, $level, $facility, $message) use ($config) { app('log')->channel($config['fallback'])->info(sprintf('KafkaLogger %s: %s (level: %d)', $facility, $message, $level)); }); $producerConf->setErrorCb(function ($kafka, $err, $reason) use ($config) { app('log')->channel($config['fallback'])->error(sprintf('KafkaLogger error: %s (reason: %s)', rd_kafka_err2str($err), $reason)); }); $producerConf->setDrMsgCb(function ($kafka, $message) use ($config) { if ($message->err) { app('log')->channel($config['fallback'])->error(sprintf('KafkaLogger delivery fail: %s', $message->errstr())); } }); $handler = new KafkaLogHandler($config['name'], $producerConf, $config['topic'], null, $config['fallback'], $config['flush_timeout_ms'], $config['level'], $config['bubble']); $this->app['log']->setHandlers([$handler]); return $this->app['log']; } }注册类到bootstrap/app.php$app->register(\App\Providers\LogServiceProvider::class);最后步骤修改或新增.env配置文件如下内容LOG_CHANNEL=kafka # 注意:这一行lumen不要加的,否则白给 LOG_KAFKA_BROKER_LIST=kafka:9092 # 多个用英文逗号间隔 LOG_KAFKA_TOPIC=laravel-logs测试Log::info('测试日志', ['ok-uid-hhxsv5']);{dotted startColor="#ff6c6c" endColor="#1989fa"/}大功告成,祝顺利!
2023年02月24日
227 阅读
0 评论
0 点赞
2023-02-01
js计算字符串的hash值getHashCode
在网上搜集到的一个很实用的js版本的类hahs算法,无论多少字符串,计算其为唯一的id的取值用非常实用,分享给大家 /** * 计算字符串的hash值 * @param {string} str 字符串 * @param {boolean} caseSensitive [可选]忽略大小写 * @returns */ const getHashCode = function (str,caseSensitive) { str = str.toString(); if(!caseSensitive){ str = str.toLowerCase(); } var hash = 1315423911, i, ch; for (i = str.length - 1; i >= 0; i--) { ch = str.charCodeAt(i); hash ^= ((hash << 5) + ch + (hash >> 2)); } return (hash & 0x7FFFFFFF); }
2023年02月01日
327 阅读
0 评论
0 点赞
2023-01-12
JS实现Web应用或网站发送浏览器Notification通知
在开发一个Web应用系统或者一个网站时,当用户触发了某个事件,或者系统想通知用户某个事件,比如有一条新的消息、其他人点赞或者评论了文章、系统流程被审核通过了等等诸如此类的场景,通常可能会想到 应用内通知 的方式,但是这种方式有一个局限,就是如果用户切换到浏览器其他页签或者其他应用程序时,可能无法及时看到应用系统的通知,那么这个时候就可以借助于浏览器的 Notification 通知功能了。1、什么是浏览器的 Notification ?Notification 是浏览器提供的一种允许网页向用户显示系统通知的机制,这种系统通知是在顶级浏览上下文视口之外,因此即使用户已经切换标签页或移动到不同的应用程序,也可以显示,并且 Notification 相关的 API 被设计成与不同平台上的现有通知系统兼容。首先来看看浏览器的 Notification 通知是什么样的,这里以 SegmentFault 网站为例,只要有新用户关注或者文章被点赞收藏,SegmentFault 网站都会自动发送 Notification 通知(能看到通知的前提是要允许网站发送通知),具体通知如下:除了 SegmentFault 网站外,还可以看看网页版微信的系统通知,也是类似的。2、如何使用 Notification ?要显示一个系统通知,一般需要分成两步:用户授予显示通知的权限、发送系统通知。(1)用户授予显示通知的权限系统要给用户发送通知,如果用户不想查看这个通知,即没有授予相应的权限,那么即使通知发出了,用户也是无法看到的。如何向用户询问是否允许查看系统通知的权限呢?可以使用下面的方法Notification.requestPermission()该方法的返回值有三个:granted、denied、default,最新的规范已将此方法更新为基于 promise 的语法,工作原理如下:Notification.requestPermission().then(function(permission) { ... });下面来看一个具体的实例,在 localhost 上询问显示系统通知的权限,根据不同的选择结果,打印相应的日志信息,代码如下:Notification.requestPermission().then(function(result) { if (result === 'denied') { console.log('拒绝显示系统通知'); return; } if (result === 'default') { console.log('默认'); return; } console.log('允许显示系统通知') });按下F12,打开 Chrome 的控制台,复制上面的代码运行后,可以看到浏览器会弹出一个询问框,如下:不同的选择,控制台会输出不同的结果允许:控制台会输出 允许显示系统通知,如果选择了允许,再次请求权限时,不会再弹出选择框,而是在控制台直接输出允许显示系统通知;禁止:控制台会输出 拒绝显示系统通知,如果选择了拒绝,再次请求权限时,不会再弹出选择框,而是在控制台直接输出拒绝显示系统通知;;x关闭:控制台会输出 默认,如果直接关闭了,再次请求权限时,依然会弹出选择框;选择【允许】后,此时再点击地址栏的信息按钮,可以看到通知已开启了,如下:如果不想显示通知了,可以直接在此处关闭通知即可,也可以使用下面的语句来查看当前用户的授权情况,如下:Notification.permission运行后,输出结果'granted'(2)发送系统通知当用户允许显示系统通知后,就可以发送通知了,这时可以使用 Notification() 构造函数创建一个新通知,这个方法可以传入两个参数,具体如下:title(必传)定义一个通知的标题,当它被触发时,它将显示在通知窗口的顶部。options(可选)options 对象包含应用于通知的任何自定义设置选项,常用的选项有:dir : 文字的方向;它的值可以是 auto(自动), ltr(从左到右), or rtl(从右到左);lang: 指定通知中所使用的语言。这个字符串必须在 BCP 47 language tag 文档中是有效的;body: 通知中额外显示的字符串;tag: 赋予通知一个 ID,以便在必要的时候对通知进行刷新、替换或移除;icon: 一个图片的 URL,将被用于显示通知的图标;除了上述5个常用选项外,还有其他的 badge、image、data、vibrate、renotify、requireInteraction 等,具体可查看官方网站的介绍 https://developer.mozilla.org/zh-CN/docs/Web/API/notification/Notification下面来测试一个简单的通知,代码如下:let notification = new Notification('有一条新通知');这个通知只有标题,运行后,可以看到增加一些 options 选项,再次来测试一下系统通知,修改后的代码如下:let notification = new Notification('有一条新通知', { dir: 'ltr', lang: 'zh-CN', body: '通知的正文内容:你的请假流程已批准', icon: 'http://localhost/coder/favicon.ico' });运行后,可以看到通知如下 (3)通知事件Notification 通知有四种事件,可以通过监听通知事件来执行不同的操作,具体事件如下:Notification.onclick:对 click 事件的处理,每当用户点击通知时被触发;Notification.onshow:对 show 事件的处理,当通知显示的时候被触发;Notification.onerror:对 error 事件的处理,每当通知遇到错误时被触发;Notification.onclose:对 close 事件的处理,当用户关闭通知时被触发。下面来测试一下通知事件的监听,代码如下:let notification = new Notification('有一条新通知', { dir: 'ltr', lang: 'zh-CN', body: '通知的正文内容:你的请假流程已批准', icon: 'http://localhost/coder/favicon.ico' }); // 监听通知显示事件 notification.onshow = () => console.log('通知已显示'); // 监听通知点击事件 notification.onclick = () => console.log('通知被点击'); // 监听通知被关闭事件 notification.onclose = () => console.log('通知被关闭'); // 监听通知错误事件 notification.onerror = () => console.log('通知出现错误');运行时,控制台会直接输出如下信息通知已显示点击通知时,会输出通知被点击当通知关闭时,会输出通知被关闭3、发送Notification通知代码结合上面的介绍,下面给出发送通知的参考代码,具体如下:function sendNotification(title, body, icon, callback) { // 先检查浏览器是否支持 if (!('Notification' in window)) { // IE浏览器不支持发送Notification通知! return; } if (Notification.permission === 'denied') { // 如果用户已拒绝显示通知 return; } if (Notification.permission === 'granted') { //用户已授权,直接发送通知 notify(); } else { // 默认,先向用户询问是否允许显示通知 Notification.requestPermission(function(permission) { // 如果用户同意,就可以直接发送通知 if (permission === 'granted') { notify(); } }); } function notify() { let notification = new Notification(title, { icon: icon, body: body }); notification.onclick = function() { callback && callback(); console.log('单击通知框') } notification.onclose = function() { console.log('关闭通知框'); }; } }下面来测试一下:sendNotification('下班通知', '今天周五,还有十分钟下班', 'http://localhost/coder/favicon.ico');运行后,通知的效果如下:参考资料:https://developer.mozilla.org/zh-CN/docs/Web/API/notificationhttps://developer.mozilla.org/zh-CN/docs/Web/API/Notifications_API
2023年01月12日
766 阅读
0 评论
0 点赞
2023-01-12
JS常用监听事件【监听键盘、触控、鼠标、多媒体、打印、剪贴板、表单等事件】
下文中按照监听类型列举了js支持的监听事件名称及解释,内容来源于网络,如有缺失或错误欢迎各位留言指正。鼠标事件click 当用户点击某个对象时调用的事件句柄。contextmenu 在用户点击鼠标右键打开上下文菜单时触发dblclick 当用户双击某个对象时调用的事件句柄。mousedown 鼠标按钮被按下。mouseenter 当鼠标指针移动到元素上时触发。mouseleave 当鼠标指针移出元素时触发mousemove 鼠标被移动。mouseover 鼠标移到某元素之上。mouseout 鼠标从某元素移开。mouseup 鼠标按键被松开。键盘事件keydown 某个键盘按键被按下。keypress 某个键盘按键被按下并松开。keyup 某个键盘按键被松开。触控事件touchstart 用户开始触摸时触发,它的target属性返回发生触摸的元素节点。touchend 用户不再接触触摸屏时(或者移出屏幕边缘时)触发,它的target属性与touchstart事件一致的,就是开始触摸时所在的元素节点。它的changedTouches属性返回一个TouchList实例,包含所有不再触摸的触摸点(即Touch实例对象)。touchmove 用户移动触摸点时触发,它的target属性与touchstart事件一致。如果触摸的半径、角度、力度发生变化,也会触发该事件。touchcancel 触摸点取消时触发,比如在触摸区域跳出一个模态窗口(modal window)、触摸点离开了文档区域(进入浏览器菜单栏)、用户的触摸点太多,超过了支持的上限(自动取消早先的触摸点)。框架/对象(Frame/Object)事件abort 图像的加载被中断。 beforeunload 该事件在即将离开页面(刷新或关闭)时触发error 在加载文档或图像时发生错误。hashchange 该事件在当前 URL 的锚部分发生修改时触发。load 一张页面或一幅图像完成加载。pageshow 该事件在用户访问页面时触发pagehide 该事件在用户离开当前网页跳转到另外一个页面时触发resize 窗口或框架被重新调整大小。scroll 当文档被滚动时发生的事件。unload 用户退出页面。表单事件blur 元素失去焦点时触发change 该事件在表单元素的内容改变时触发focus 元素获取焦点时触发focusin 元素即将获取焦点是触发focusout 元素即将失去焦点是触发input 元素获取用户输入是触发reset 表单重置时触发search 用户向搜索域输入文本时触发剪贴板事件copy 该事件在用户拷贝元素内容时触发cut 该事件在用户剪切元素内容时触发paste 该事件在用户粘贴元素内容时触发打印事件afterprint 该事件在页面已经开始打印,或者打印窗口已经关闭时触发beforeprint 该事件在页面即将开始打印时触发拖动事件drag 该事件在元素正在拖动时触发dragend 该事件在用户完成元素的拖动时触发dragenter 该事件在拖动的元素进入放置目标时触发dragleave 该事件在拖动元素离开放置目标时触发dragover 该事件在拖动元素在放置目标上时触发dragstart 该事件在用户开始拖动元素时触发drop 该事件在拖动元素放置在目标区域时触发多媒体(Media)事件abort 事件在视频/音频(audio/video)终止加载时触发。canplay 事件在用户可以开始播放视频/音频(audio/video)时触发。canplaythrough 事件在视频/音频(audio/video)可以正常播放且无需停顿和缓冲时触发。durationchange 事件在视频/音频(audio/video)的时长发生变化时触发。emptied 当前播放列表为空时发生事件ended 事件在视频/音频(audio/video)播放结束时触发。error 事件在视频/音频(audio/video)数据加载期间发生错误时触发。loadeddata 事件在浏览器加载视频/音频(audio/video)当前帧时触发触发。loadedmetadata 事件在指定视频/音频(audio/video)的元数据加载后触发。loadstart 事件在浏览器开始寻找指定视频/音频(audio/video)触发。pause 事件在视频/音频(audio/video)暂停时触发。play 事件在视频/音频(audio/video)开始播放时触发。playing 事件在视频/音频(audio/video)暂停或者在缓冲后准备重新开始播放时触发。progress 事件在浏览器下载指定的视频/音频(audio/video)时触发。ratechange 事件在视频/音频(audio/video)的播放速度发送改变时触发。seeked 事件在用户重新定位视频/音频(audio/video)的播放位置后触发。seeking 事件在用户开始重新定位视频/音频(audio/video)时触发。stalled 事件在浏览器获取媒体数据,但媒体数据不可用时触发。suspend 事件在浏览器读取媒体数据中止时触发。timeupdate 事件在当前的播放位置发送改变时触发。volumechange 事件在音量发生改变时触发。waiting 事件在视频由于要播放下一帧而需要缓冲时触发。动画事件animationend 该事件在 CSS 动画结束播放时触发animationiteration 该事件在 CSS 动画重复播放时触发animationstart 该事件在 CSS 动画开始播放时触发过渡事件transitionend 该事件在 CSS 完成过渡后触发。其他事件message 该事件通过或者从对象(WebSocket, Web Worker, Event Source 或者子 frame 或父窗口)接收到消息时触发online 该事件在浏览器开始在线工作时触发。offline 该事件在浏览器开始离线工作时触发。popstate 该事件在窗口的浏览历史(history` 对象)发生改变时触发。 show 该事件当元素在上下文菜单显示时触发storage 该事件在 Web Storage(HTML 5 Web 存储)更新时触发toggle 该事件在用户打开或关闭 元素时触发wheel 该事件在鼠标滚轮在元素上下滚动时触发
2023年01月12日
992 阅读
0 评论
0 点赞
2023-01-12
js中的prototype、__proto__、constructor方法详解
提示:不要排斥,静下心来,认真读完,你就搞懂了!(可以先看一下最后的总结部分再回过头来完整看完)1. 前言 作为一名前端工程师,必须搞懂JS中的prototype、__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞懂它们。这里说明一点,__proto__属性的两边是各由两个下划线构成(这里为了方便大家看清,在两下划线之间加入了一个空格:_ _proto_ _,读作“dunder proto”,“double underscore proto”的缩写),实际上,该属性在ES标准定义中的名字应该是[[Prototype]],具体实现是由浏览器代理自己实现,谷歌浏览器的实现就是将[[Prototype]]命名为__proto__,大家清楚这个标准定义与具体实现的区别即可(名字有所差异,功能是一样的),可以通过该方式检测引擎是否支持这个属性:Object.getPrototypeOf({__proto__: null}) === null。本文基于谷歌浏览器(版本 72.0.3626.121)的实验结果所得。 现在正式开始! 让我们从如下一个简单的例子展开讨论,并配以相关的图帮助理解:function Foo() {...}; let f1 = new Foo(); 以上代码表示创建一个构造函数Foo(),并用new关键字实例化该构造函数得到一个实例化对象f1。这里稍微补充一下new操作符将函数作为构造器进行调用时的过程:函数被调用,然后新创建一个对象,并且成了函数的上下文(也就是此时函数内部的this是指向该新创建的对象,这意味着我们可以在构造器函数内部通过this参数初始化值),最后返回该新对象的引用,详细请看:详解JavaScript中的new操作符。虽然是简简单单的两行代码,然而它们背后的关系却是错综复杂的,如下图所示: 看到这图别怕,让我们一步步剖析,彻底搞懂它们! 图的说明:右下角为图例,红色箭头表示__proto__属性指向、绿色箭头表示prototype属性的指向、棕色实线箭头表示本身具有的constructor属性的指向,棕色虚线箭头表示继承而来的constructor属性的指向;蓝色方块表示对象,浅绿色方块表示函数(这里为了更好看清,Foo()仅代表是函数,并不是指执行函数Foo后得到的结果,图中的其他函数同理)。图的中间部分即为它们之间的联系,图的最左边即为例子代码。2. __proto__ 属性 首先,我们需要牢记两点:①__proto__和constructor属性是对象所独有的;② prototype属性是函数所独有的。但是由于JS中函数也是一种对象,所以函数也拥有__proto__和constructor属性,这点是致使我们产生困惑的很大原因之一。上图有点复杂,我们把它按照属性分别拆开,然后进行分析: 第一,这里我们仅留下 __proto__ 属性,它是对象所独有的,可以看到__proto__属性都是由一个对象指向一个对象,即指向它们的原型对象(也可以理解为父对象),那么这个属性的作用是什么呢?它的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(可以理解为父对象)里找,如果父对象也不存在这个属性,则继续往父对象的__proto__属性所指向的那个对象(可以理解为爷爷对象)里找,如果还没找到,则继续往上找…直到原型链顶端null(可以理解为原始人。。。),再往上找就相当于在null上取值,会报错(可以理解为,再往上就已经不是“人”的范畴了,找不到了,到此结束,null为原型链的终点),由以上这种通过__proto__属性来连接对象直到null的一条链即为我们所谓的原型链。 其实我们平时调用的字符串方法、数组方法、对象方法、函数方法等都是靠__proto__继承而来的。3. prototype属性 第二,接下来我们看 prototype 属性: prototype属性,别忘了一点,就是我们前面提到要牢记的两点中的第二点,它是函数所独有的,它是从一个函数指向一个对象。它的含义是函数的原型对象,也就是这个函数(其实所有函数都可以作为构造函数)所创建的实例的原型对象,由此可知:f1.__proto__ === Foo.prototype,它们两个完全一样。那prototype属性的作用又是什么呢?它的作用就是包含可以由特定类型的所有实例共享的属性和方法,也就是让该函数所实例化的对象们都可以找到公用的属性和方法。任何函数在创建的时候,其实会默认同时创建该函数的prototype对象。4. constructor属性 最后,我们来看一下 constructor 属性: constructor属性也是对象才拥有的,它是从一个对象指向一个函数,含义就是指向该对象的构造函数,每个对象都有构造函数(本身拥有或继承而来,继承而来的要结合__proto__属性查看会更清楚点,如下图所示),从上图中可以看出Function这个对象比较特殊,它的构造函数就是它自己(因为Function可以看成是一个函数,也可以是一个对象),所有函数和对象最终都是由Function构造函数得来,所以constructor属性的终点就是Function这个函数。 感谢网友的指出,这里解释一下上段中“每个对象都有构造函数”这句话。这里的意思是每个对象都可以找到其对应的constructor,因为创建对象的前提是需要有constructor,而这个constructor可能是对象自己本身显式定义的或者通过__proto__在原型链中找到的。而单从constructor这个属性来讲,只有prototype对象才有。每个函数在创建的时候,JS会同时创建一个该函数对应的prototype对象,而函数创建的对象.__proto__ === 该函数.prototype,该函数.prototype.constructor===该函数本身,故通过函数创建的对象即使自己没有constructor属性,它也能通过__proto__找到对应的constructor,所以任何对象最终都可以找到其构造函数(null如果当成对象的话,将null除外)。如下: 5. 总结 总结一下:我们需要牢记两点:①__proto__和constructor属性是对象所独有的;② prototype属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__和constructor属性。__proto__属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链。prototype属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype。constructor属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function。 本文就此结束了,希望对那些对JS中的prototype、__proto__与constructor属性有困惑的同学有所帮助。 最后,感谢这两篇博文,本文中的部分内容参考自这两篇博文:一张图理解prototype、proto和constructor的三角关系prototype和__proto__的关系是什么?小彩蛋:实现继承(相对完美、优雅)function inherit(Child, Parent) { // 继承原型上的属性 Child.prototype = Object.create(Parent.prototype) // 修复 constructor Child.prototype.constructor = Child // 存储超类 Child.super = Parent // 静态属性继承 if (Object.setPrototypeOf) { // setPrototypeOf es6 Object.setPrototypeOf(Child, Parent) } else if (Child.__proto__) { // __proto__ es6 引入,但是部分浏览器早已支持 Child.__proto__ = Parent } else { // 兼容 IE10 等陈旧浏览器 // 将 Parent 上的静态属性和方法拷贝一份到 Child 上,不会覆盖 Child 上的方法 for (var k in Parent) { if (Parent.hasOwnProperty(k) && !(k in Child)) { Child[k] = Parent[k] } } } }
2023年01月12日
325 阅读
0 评论
0 点赞
2023-01-12
在JS中利用for...in循环遍历对象【踩坑】
for...in循环可以在js中遍历对象或者数组,比如当我们想要输出内容中的所有对象,就可以使用for...in循环//使用方法 for(键 in 对象) var obj={ name:'Zhang', score:60, result:'及格' } for(var ergodic in obj){ console.log(obj[ergodic]); }运行结果如果我们想隐藏(删除)部分内容,可以使用delete进行操作<!DOCTYPE HTML> <html> <head> <meta charset=utf-8" /> <title>CSDN Wellfancy</title> </head> <body> <div></div> <script> //使用方法 for(键 in 对象) var obj={ name:'Zhang', score:60, result:'及格' } delete obj.score;//隐藏obj中score的值 for(var ergodic in obj){ console.log(obj[ergodic]); } </script> </body> </html>运行结果:for in 的踩坑但实际上往往再引用了很多其它框架后,由于每个库写法的不确定性可能会用到一些影响对象特有属性的一些写法如:prototype、__proto__与constructor等,那么for in 去遍历时就出现了一些事情举例:某个js类中声明了一个:window.xyz={};window.xyz.__proto__.abcd=1123;那么您的所有对象中都会被新增了一个abcd,那么循环出来的结果将是Zhang 60 及格 1123我们来看下影响对象属性的一些属性定义首先,我们需要牢记两点:①__proto__和constructor属性是对象所独有的;② prototype属性是函数所独有的。但是由于JS中函数也是一种对象,所以函数也拥有__proto__和constructor属性,这点是致使我们产生困惑的很大原因之一。举个例子:function Foo() {...}; let f1 = new Foo();以上代码表示创建一个构造函数Foo(),并用new关键字实例化该构造函数得到一个实例化对象f1。这里稍微补充一下new操作符将函数作为构造器进行调用时的过程:函数被调用,然后新创建一个对象,并且成了函数的上下文(也就是此时函数内部的this是指向该新创建的对象,这意味着我们可以在构造器函数内部通过this参数初始化值),最后返回该新对象的引用 虽然是简简单单的两行代码,然而它们背后的关系却是错综复杂的,如下图所示: 上图有些复杂,如果不理解可以略过...详细了解...其实您知道"abcd"不是我们要的解决方案如下:<!DOCTYPE HTML> <html> <head> <meta charset=utf-8" /> <title>CSDN Wellfancy</title> </head> <body> <div></div> <script> //使用方法 for(键 in 对象) window.xyz={}; window.xyz.__proto__.abcd=1123; var obj={ name:'Zhang', score:60, result:'及格' } delete obj.score;//隐藏obj中score的值 for(var ergodic in obj){ if (obj.hasOwnProperty(ergodic)) { console.log(obj[ergodic]); } } </script> </body> </html>综上所属,建议我们采用for in遍历对象时都加入hasOwnProperty的判断,以免后续逻辑被未知框架声明所污染
2023年01月12日
352 阅读
0 评论
1 点赞
2023-01-12
你不知道的JavaScript事件总结(详细)
JavaScript操作css称为脚本化CSS,而JavaScript与HTML的交互是通过事件实现的。事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,而事件流(又叫事件传播)描述的是从页面中接收事件的顺序。...
2023年01月12日
240 阅读
0 评论
0 点赞
2023-01-09
通过iframe嵌套时,被302重定向怎么办?
项目中发现,多系统通过iframe嵌套时,如果iframe的请求是重定向会导致父级页面重定向,怎么破?最终的设置(不包含allow-top-navigation即可){mtitle title="实现代码如下"/}1、在 PC 端你可以这样设置 iframe, 来防止父级页面被重定向, 产生重定向结果的链接会以 _blank 的形式打开<iframe src="page-b.html" sandbox="allow-forms allow-scripts allow-same-origin allow-popups"></iframe>2、在移动端你需要这样设置 iframe, 让产生重定向结果的链接失效, 来达到防止父级页面被重定向的目的<iframe src="page-b.html" sandbox="allow-forms allow-scripts allow-same-origin"></iframe>
2023年01月09日
2,262 阅读
0 评论
2 点赞
2023-01-09
在线运行html转markdown
点击以下按钮在线运行html转markdown 退出 box.full_div{ position: absolute; left: 0; right: 0; width:100%; height:100%; top:0; background: rgba(0,0,0,0.3);z-index:10000; } box a.close_win{position: absolute; right:5px; top:5px; z-index:1000; color: #ffd45e;text-shadow: 0 0 2px #000000, 0 0 2px #000000;} box.show{display: block;} box.hidden{display: none;} $(document).on('click','[type="run-html-m"],.close_win', function (e) { $('body,html').animate({scrollTop: 0}, 100); if($('box.full_div').hasClass('hidden')) { $('box.full_div iframe').attr('src',$(this).attr('href')); $('body').css({overflow: 'hidden'}); $('box.full_div').addClass('show').removeClass('hidden'); } else { $('body').css({overflow: 'auto'}); $('.full_div').addClass('hidden').removeClass('show'); $('box.full_div iframe').attr('src',''); } return false; }); {anote icon="fa-code" href="//www.archn.cn/_M/html-markdown.html" type="run-html-m" content="在线html转markdown"/}
2023年01月09日
515 阅读
0 评论
0 点赞
2023-01-06
JS使用正则表达式获取小括号、中括号及花括号内容的方法示例
本文实例讲述了JS使用正则表达式获取小括号、中括号及花括号内容的方法。分享给大家供大家参考,具体如下:正则表达式的() [] {}有不同的意思() 是为了提取匹配的字符串。表达式中有几个()就有几个相应的匹配字符串。(\s*)表示连续空格的字符串。[]是定义匹配的字符范围。比如 [a-zA-Z0-9] 表示相应位置的字符要匹配英文字符和数字。[\s]表示空格或者号。{}一般用来表示匹配的长度,比如 \s{3} 表示匹配三个空格,\s[1,3]表示匹配一到三个空格。(0-9) 匹配 '0-9′ 本身。 [0-9] 匹配数字(注意后面有 ,可以为空)[0-9]+ 匹配数字(注意后面有 +,不可以为空){1-9} 写法错误。[0-9]{0,9} 表示长度为 0 到 9 的数字字符串。小括号是用于将基本的单元合成一个大的单元,而中括号就是将多个基本单元组成一个选择域,表示其中一个的意思。例子:小括号例子1、我们想匹配123这个整体(123)就是匹配"123"这个整体,大括号而[123]就是匹配1/2/3(1或者2或者3)再举个面圈教程小编碰到的一个问题例如我们想匹配 多个替换 中间多个 的时候先用中括号[]<p>[ ]*</p>匹配内容的就如下图所示那下面用小括号试试()<p>( )*</p>JS 正则表达式 获取小括号 中括号 花括号内的内容<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>www.nhooo.com JS获取括号内容</title> </head> <body> <script type="text/javascript"> var str="123{xxxx}456[我的]789123[你的]456(1389090)789"; var regex1 = /\((.+?)\)/g; // () 小括号 var regex2 = /\[(.+?)\]/g; // [] 中括号 var regex3 = /\{(.+?)\}/g; // {} 花括号,大括号 // 输出是一个数组 console.log(str.match(regex1)); console.log(str.match(regex2)); console.log(str.match(regex3)); </script> </body> </html>使用在线HTML/CSS/JavaScript代码运行工具http://tools.jb51.net/code/HtmlJsRun测试运行结果如下:附:JAVA正则匹配语句regex =PS:这里再为大家提供2款非常方便的正则表达式工具供大家参考使用:JavaScript正则表达式在线测试工具:http://tools.jb51.net/regex/javascript正则表达式在线生成工具:http://tools.jb51.net/regex/create_reg更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript正则表达式技巧大全》、《JavaScript替换操作技巧总结》、《JavaScript查找算法技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》、《JavaScript中json操作技巧总结》、《JavaScript错误与调试技巧总结》及《JavaScript数学运算用法总结》希望本文所述对大家JavaScript程序设计有所帮助。
2023年01月06日
438 阅读
0 评论
0 点赞
2023-01-05
JS正则常用校验大全
手机号(mobile phone)中国(严谨), 根据工信部2019年最新公布的手机号段const reg = /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/; const str = "19119255642"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);Email(邮箱)const reg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; const str = "90203918@qq.com"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);座机(Tel Phone)电话(国内) 如: 0341-86091234const reg = /^(?:(?:\d{3}-)?\d{8}|^(?:\d{4}-)?\d{7,8})(?:-\d+)?$/; const str = "0936-4211235"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);身份证号(2代,18位数字),最后一位是校验位,可能为数字或字符Xconst reg = /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/; const str = "12345619991205131x"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文姓名const reg = /^(?:[\u4e00-\u9fa5·]{2,16})$/; const str = "韩小韩"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);英文姓名const reg = /(^[a-zA-Z][a-zA-Z\s]{0,20}[a-zA-Z]$)/; const str = "James Han"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);网址(URL)const reg = /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/; const str = "https://www.vvhan.com"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);必须带端口号的网址(或IP)const reg = /^((ht|f)tps?:\/\/)?[\w-]+(\.[\w-]+)+:\d{1,5}\/?$/; const str = "https://www.vvhan.com:80"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);银行卡号(10到30位, 覆盖对公/私账户)const reg = /^[1-9]\d{9,29}$/; const str = "6222026006705354000"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线组合)const reg = /^[a-zA-Z]\w{4,15}$/; const str = "han_666666"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文/汉字const reg = /^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/; const str = "易航博客"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);密码强度校验,最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符const reg = /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/; const str = "han@666vvx,"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);微信号(wx),6至20位,以字母开头,字母,数字,减号,下划线const reg = /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/; const str = "kd_-666"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);邮政编码(中国)const reg = /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/; const str = "734500"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文和数字const reg = /^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$/; const str = "易航好6啊"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);匹配连续重复的字符const reg = /(.)\1+/; const str = "112233"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);统一社会信用代码const reg = /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/; const str = "91110108772551611J"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);子网掩码(不包含 0.0.0.0)const reg = /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(255|254|252|248|240|224|192|128|0)$/; const str = "255.255.255.0"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(新能源)const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z](?:((\d{5}[A-HJK])|([A-HJK][A-HJ-NP-Z0-9][0-9]{4}))|[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳])$/; const str = "京AD92035"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(非新能源)const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]$/; const str = "京A00599"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(新能源+非新能源)const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/; const str = "京A12345D"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);护照(包含香港、澳门)const reg = /(^[EeKkGgDdSsPpHh]\d{8}$)|(^(([Ee][a-fA-F])|([DdSsPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))\d{7}$)/; const str = "s28233515"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);
2023年01月05日
278 阅读
0 评论
0 点赞
2023-01-03
json在线转换Swagger/OpenAPI文档的注释文本格式
点击以下按钮在线转换格式 退出 box.full_div{ position: absolute; left: 0; right: 0; width:100%; height:100%; top:0; background: rgba(0,0,0,0.3);z-index:10000; } box a.close_win{position: absolute; right:5px; top:5px; z-index:1000; color: #ffd45e;text-shadow: 0 0 2px #000000, 0 0 2px #000000;} box.show{display: block;} box.hidden{display: none;} $(document).on('click','[type="json-to-php"],.close_win', function (e) { $('body,html').animate({scrollTop: 0}, 100); if($('box.full_div').hasClass('hidden')) { $('box.full_div iframe').attr('src',$(this).attr('href')); $('body').css({overflow: 'hidden'}); $('box.full_div').addClass('show').removeClass('hidden'); } else { $('body').css({overflow: 'auto'}); $('.full_div').addClass('hidden').removeClass('show'); $('box.full_div iframe').attr('src',''); } return false; }); {anote icon="fa-code" href="http://arc.archn.cn/_M/json-openapi-php.html" type="json-to-php" content="在线运行"/} 实现类似转换
2023年01月03日
706 阅读
0 评论
0 点赞
2022-09-16
Windows安装PECL
安装步骤PECL是 The PHP Extension Community Library 缩写。下载go-pear.phar 到 d:/tool/go-pear.phar执行 php d:/tool/go-pear.phar下载地址:http://pear.php.net/go-pear.phar官方文档:https://pear.php.net/manual/en/installation.getting.php关键事项注意事项:第一个一定是选择 local。第一次执行的时候一定要指定 php的路径,输入13弹出对话框选择PHP的目录。之后直接按 Enter 继续。完成!安装过程D:\pear>php d:/tool/go-pear.phar Are you installing a system-wide PEAR or a local copy? (system|local) [system] : local Please confirm local copy by typing 'yes' : yes Below is a suggested file layout for your new PEAR installation. To change individual locations, type the number in front of the directory. Type 'all' to change all of them or simply press Enter to accept these locations. 1. Installation base ($prefix) : D:\pear 2. Temporary directory for processing : D:\pear\tmp 3. Temporary directory for downloads : D:\pear\tmp 4. Binaries directory : D:\pear 5. PHP code directory ($php_dir) : D:\pear\pear 6. Documentation directory : D:\pear\docs 7. Data directory : D:\pear\data 8. User-modifiable configuration files directory : D:\pear\cfg 9. Public Web Files directory : D:\pear\www 10. System manual pages directory : D:\pear\man 11. Tests directory : D:\pear\tests 12. Name of configuration file : D:\pear\pear.ini 13. Path to CLI php.exe : 1-13, 'all' or Enter to continue: 13 php.exe (sapi: cli) found. Below is a suggested file layout for your new PEAR installation. To change individual locations, type the number in front of the directory. Type 'all' to change all of them or simply press Enter to accept these locations. 1. Installation base ($prefix) : D:\pear\ 2. Temporary directory for processing : D:\pear\\tmp 3. Temporary directory for downloads : D:\pear\\tmp 4. Binaries directory : D:\pear\ 5. PHP code directory ($php_dir) : D:\pear\\pear 6. Documentation directory : D:\pear\\docs 7. Data directory : D:\pear\\data 8. User-modifiable configuration files directory : D:\pear\\cfg 9. Public Web Files directory : D:\pear\\www 10. System manual pages directory : D:\pear\\man 11. Tests directory : D:\pear\\tests 12. Name of configuration file : D:\pear\\pear.ini 13. Path to CLI php.exe : D:\php73\ 1-13, 'all' or Enter to continue: Beginning install... Configuration written to D:\pear\\pear.ini... Initialized registry... Preparing to install... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/Archive_Tar-1.4.7.t ar... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/Console_Getopt-1.4. 2.tar... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/PEAR-1.10.9.tar... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/Structures_Graph-1. 1.1.tar... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/XML_Util-1.4.3.tar. .. install ok: channel://pear.php.net/Archive_Tar-1.4.7 install ok: channel://pear.php.net/Console_Getopt-1.4.2 install ok: channel://pear.php.net/Structures_Graph-1.1.1 install ok: channel://pear.php.net/XML_Util-1.4.3 install ok: channel://pear.php.net/PEAR-1.10.9 PEAR: Optional feature webinstaller available (PEAR's web-based installer) PEAR: Optional feature gtkinstaller available (PEAR's PHP-GTK-based installer) PEAR: Optional feature gtk2installer available (PEAR's PHP-GTK2-based installer) PEAR: To install optional features use "pear install pear/PEAR#featurename" ****************************************************************************** WARNING! The include_path defined in the currently used php.ini does not contain the PEAR PHP directory you just specified: <D:\pear\\pear> If the specified directory is also not in the include_path used by your scripts, you will have problems getting any PEAR packages working. Would you like to alter php.ini <D:\PHP73\php.ini>? [Y/n] : Y php.ini <D:\PHP73\php.ini> include_path updated. Current include path : .;C:\php\pear Configured directory : D:\pear\\pear Currently used php.ini (guess) : D:\PHP73\php.ini Press Enter to continue: ** WARNING! Old version found at C:\Program Files (x86)\Common Files\Oracle\Java \javapath\pear.bat, please remove it or be sure to use the new d:\pear\\pear.bat command The 'pear' command is now at your service at d:\pear\\pear.bat ** The 'pear' command is not currently in your PATH, so you need to ** use 'd:\pear\\pear.bat' until you have added ** 'D:\pear\' to your PATH environment variable. Run it without parameters to see the available actions, try 'pear list' to see what packages are installed, or 'pear help' for help. For more information about PEAR, see: http://pear.php.net/faq.php http://pear.php.net/manual/ Thanks for using go-pear!
2022年09月16日
963 阅读
1 评论
0 点赞
1
2
3