Skip to content

2023年12月随笔

Window IDEA开发工具 杀死指定端口 cmd 命令行 taskkill

两步方法 : 1 查询端口占用,2 强行杀死进程

bash
netstat -aon|findstr 8080
bash
taskkill /pid 4136 -t -f

如果杀死端口失败,可使用管理员打开cmd窗口,然后关闭其端口

查看当前最大连接数(通常默认最大连接数是100,此处我的已经修改完毕)

show variables like '%max_connections%';

修改最大连接数

set global max_connections = 10000;

require和import的区别,哪个运行更快?

  • 1、import是es6规范语法,require是AMD规范引入方式

  • 2、import是在编译时被加载,所以放在文件开头。require在代码运行时被加载,所以require理论上可以运用在代码任何地方。import性能更好。

  • 3、import引入的对象被修改时,源对象也会被修改,相当于浅拷贝,require引入的对象被修改时,源对象不会被修改,官网称值拷贝,我们可以理解为深拷贝。

* 4、import有利于tree-shaking(移除JavaScript上下文中未引用的代码),require对tree-shaking不友好。 import 虽然是 es6 中的语法,但就目前来说,所有的引擎都还没有实现import。2022-09-28查询 我们在 node 中使用 babel 支持ES6(在 node 当中,比如 node.js 代码,也不能直接使用 import 来导入,必须使用 babel 支持才能使用语法),实际上也是将 ES6 转码为 ES5 再执行,import 语法实际上会被转码为 require。这也是为什么在模块导出时使 module.exports,在引入模块时使用 import 仍然起效,因为本质上,import 会被转码为 require 去执行。

Object.assign到底是深拷贝还是浅拷贝?

Object.assign是浅拷贝而不是深拷贝,浅拷贝意味着只有对象的属性被复制,如果源对象的属性值是对象或数组,那么目标对象对象属性将保持相同对象的引用,而不是复制这些内容

总结: 是浅拷贝,只会复制对象的属性和数组的元素的引用,不会复制嵌套对象的内容。

示例代码如下

js
const source = { a: 1, b: { c: 2 } };
const target = Object.assign({}, source);
 
source.a = 10; // 修改 source 的属性
console.log(target.a); // 输出 1,因为 target.a 并不受 source 的影响
 
source.b.c = 20; // 修改 source.b.c,会影响 target.b.c
console.log(target.b.c); // 输出 20,因为 target.b.c 和 source.b.c 引用同一个对象

地图Api数量为万级以上的点标记的解决方案?

以高德地图为例,介绍在图面添加数量为万级以上的点标记的解决方案。包括:

  1. 海量点标记

当需要在地图展示数量为十万以内的点并且需要较好的性能表现时,可以使用 AMap.MassMarks 类。AMap.MassMarks 并不是普通的覆盖物,它实际上是由海量点组成的一个地图图层, 目前仅适用于html5浏览器。

  1. 点聚合

在不同的地图缩放级别对海量的数据点进行聚合展示。目前点聚合插件在点的数量在10万以内时可以保持较好的性能。点聚合支持用户自定义点标记。

一道转为树形结构的题目

将下面结构转化为树形结构

下面是我的一实现方式,方式很多,后面会逐渐优化

js
const areaArr = [
  { id: 10000, name: '中国'},
  { pid: 10000, id: 11000, name: '浙江省' },
  { pid: 11000, id: 11100, name: '杭州市' },
  { pid: 11100, id: 11101, name: '西湖区' },
  { pid: 11100, id: 11102, name: '萧山区' },
  { pid: 11000, id: 11200, name: '金华市' },
  { pid: 11200, id: 11201, name: '京东区' },
  { pid: 11200, id: 11202, name: '婺城区' },
  { pid: 10000, id: 12000, name: '湖南省' },
  { pid: 12000, id: 12100, name: '长沙市' },
  { pid: 12100, id: 12101, name: '长沙市区1' },
  { pid: 12100, id: 12102, name: '长沙市区2' },
  { pid: 12000, id: 12200, name: '岳阳市' },
  { pid: 12200, id: 12201, name: '岳阳市区1' },
  { pid: 12200, id: 12202, name: '岳阳市区2' }
];

 function listTotree(arr){
    let list = JSON.parse(JSON.stringify(arr))

    // pid排序
    const tempList = list.sort((a,b)=>{return a.pid -b.pid})

    getChildrenListById(tempList)

    return tempList

  }

  // 获取当前节点的所有子节点
  function getChildrenById(list,id){
      return list.filter(k => k.pid == id)
  }

  // 根据id获取下面的所有子孙节点,自动拼接
  function getChildrenListById(list,id){
      for(let item of list){
        if(!item.hasOwnProperty('pid')){
          console.log("item===>",item)
          item.children = getChildrenById(list,item.id)

          for(let sitem of item.children){
            getChildrenListById(item.children,sitem.id)
          }      
        }
      }
  }

  const result = listTotree(areaArr)

记一道var加定时器的题目

js
for(var i=1;i<=5;i++){ 
     setTimeout(() => {  console.log(i) })
}

以下代码能否实现上述功能?答案是不能。 因为 setTimeout 的 console.log(i); 的 i 是var 定义的,所以是函数级的作用域,不属于 for 循环体,属于 global。等到 for 循环结束,i 已经等于3了,这个时候再执行 setTimeout 的回调函数,里面的 console.log(i);的 i 去向上找作用域,只能找到 global下 的 i,即 6。所以输出都是 6。

解决方案:

闭包

js
for(var i = 1 ;i<=2;i++){
    (function(i){ //立即执行函数
      setTimeout(()=>{
      console.log(i);
      },i*1000)
     })(i)
}

人为给 console.log(i); 创造作用域,保存i的值。这里用到立刻执行函数。这样 console.log(i); 中的i就保存在每一次循环生成的立刻执行函数中的作用域里了

let声明

js
for (let i = 1;i<=2;i++){
    setTimeout(()=>{
        console.log(i);
    },i*1000)
}

Promise Promise构造函数同步执行,设置定时器,等待定时器回调发生后,输出1,返回一个成功的promise。此时.then方法处理成功的promise,再次开启一个定时,定时器回调发生后,输出2。

js
const pinrtFn = () => {
    return new Promise((resolve)=>{
        setTimeout(()=>{
            console.log(1);
            resolve()
        },1000)
    }).then(()=>{
        setTimeout(()=>{
            console.log(2);
        },1000) //过了1s后才开启的,再等1s就是2s
    })
}
pinrtFn()

这样虽然可以实现,但如果数字过多,会出现很多的.then链式调用,可以改写成下面的for循环形式。 for循环是同步的,那么4个成功的promise对象几乎在同一时刻生成,同时触发.then方法。由于传入的i不同,定时器触发的时间不同,输出则不是同时的。

js
function sleep(time){
    for(var i =0;i<5;i++){
        Promise.resolve(i).then((result)=>{
            setTimeout(()=>{
                console.log(result);
            },time*result)
        })
    }
}
sleep(1000)

async与await 封装一个sleep作为阻塞,直到定时器触发,返回一个成功的promise,才会执行await后面的console.log(i)

js
(async ()=>{
    const sleep = (timeoutMS) =>
        new Promise((resolve)=>{
            setTimeout(resolve,timeoutMS);
        })
    for (var i=0;i<5;i++){
        await sleep(1000)
        console.log(i);
    }
})()

git报错记录

fatal: refusing to merge unrelated histories 描述:如果项目中存在readme.md,本地项目是有目录的,在git pull 的时候会报如上错误

解决步骤: 在你操作命令后面加--allow-unrelated-histories 例如git merge master --allow-unrelated-historiesgit pull origin master --allow-unrelated-histories

PostCss版本过高导致报错

vue Syntax Error: Error: PostCSS plugin postcss-pxtorem requires PostCSS 8.Migration guide for end-users:

解决步骤: postcss-pxtorem版本过高,降到5.1.1发现还是报错,降低到5.0.0正常运行 解决步骤

遮罩层穿透如何解决?

滑动穿透是一个常见的问题,当我们打开一个遮罩层,进行滚动(滑动)操作时,可能会出现这个问题。这是因为遮罩层的position尽管设置成了fixed,但它仍然是属于父级元素内容的一部分,这并不影响页面中的其余部分按照正常情况对滚动这一操作进行响应1。

以下是一些解决滑动穿透的方法:

  • 使用CSS属性overscroll-behavior:contain;:这个属性可以阻止滚动链,即当一个元素的滚动区域滚动到顶部或底部时,滚动事件不会传递到祖先元素1。但是在某些浏览器或者某些环境下,如果modal没有滚动条,那么滚动穿透现象还是会触发1。

  • 限制浏览器默认行为:判断modal滚动距离,如果触底或者到达顶部的时候,给父元素的滚动事件添加preventDefault;然后在modal消失的时候,移除preventDefault行为1。

  • 限制父级元素滚动:判断modal是否存在,存在的情况下将父元素设置为postion:fixed;top:$ {已经滚动的高度}overflow:hidden;这样就能保证打开modal的时候,父元素的滚动高度不会突变为0,同时在modal消失的时候,取消fixed定位,手动将父元素再滚动到modal打开前的距离1。

  • 使用vue的阻止默认事件 @touchmove.prevent:给遮罩层一个阻止默认事件2。

Git配置、缓存用户名密码和清除缓存

只要是加-- global的都是设置全局的,建议不要这样设置。下面的所有的操作都是编辑的 .git/config的内容,也可以找到这个文件,直接添加内容。

1.配置用户名和邮箱,分为全局和项目两种:

    1)此处内容为全局设置用户名和邮箱 
bash
git config --global user.name "username"
git config --global user.email "useremail@qq.com"
  1. 此处为单个项目设置用户名和密码
bash
git config user.name "username"
git config user.email "useremail@qq.com"

2.清除配置中纪录的用户名和密码,下次提交代码时会让重新输入账号密码

bash
git config --system --unset credential.helper

3.执行下面命令之后,再次pull或push时会缓存输入的用户名和密码

bash
git config --global credential.helper store        #全局
git config credential.helper store        #单个项目

4.清除git缓存中的用户名的密码

bash
git credential-manager uninstall
#如果电脑是macos提示 git: 'credential-wincred' is not a git command. See 'git --help'
#第一步:git config --unset-all credential.helper
#第二步:git config --global credential.helper osxkeychain

Echart如何配置鼠标选中时的提示框内容?

在 ECharts 中,当鼠标移动到图表上时,显示当前值的功能是由 tooltip 属性控制的。tooltip 是提示框组件,它可以配置多种触发类型和格式化方式。

例如,以下是一些基本的配置:

javascript
tooltip: {
    trigger: 'item', // 触发类型,'item' 数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用
    axisPointer: { // 坐标轴指示器,坐标轴触发有效
        type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
    },
    formatter: '{a} <br/>{b} : {c} <br/>百分比 : {d}%' // {a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比)
}

此外,你还可以通过 formatter 属性自定义提示框的内容,甚至可以使用 HTML¹。

javascript
tooltip: {
    trigger: 'axis', // 坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用
    axisPointer: { // 坐标轴指示器,坐标轴触发有效
        type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
    },
    backgroundColor: "transparent", // 可以背景设置为透明,然后在下面 formatter 自定义 html 的背景色
    formatter: function (params) {
        let str = '<div style="width:100%;padding:10px 15px 10px 15px;font-size:13px;box-sizing:border-box;border-radius:4px;position:relative;background:rgba(0,0,0,0.5)">';
        str += "<div style='display:flex;align-items:center;'>" + params[0].marker + params[0].seriesName + ":" + "¥" + params[0].value + "</div>";
        str += "</div>";
        return str;
    }
}

Vue3+Ts启动项目报错

报错信息: Cannot find module fork-ts-checker-webpack-plugin-v5

解决方案: package.json里的devDependencies中的"@vue/cli-plugin-typescript"是"~4.5.0",于是把它改成 “~4.4.0”

Vue/cli4打包报错

vue/cli@4执行npm run build报错:Syntax Error: Thread Loader (Worker 2) The “from“ argument must be of

bash
 error  in ./src/views/singaporeReport/pieSmokeLine.vue?vue&type=template&id=2ec3aa86&
 
Syntax Error: Thread Loader (Worker 2)
The "from" argument must be of type string. Received undefined

原因: vue-cli 使用 wokrer-loader 加载 web woker 时,使用 npm run build 有很大机率会打包失败,报错如上。

thread-loader 与 worker-loader 有冲突 。

解决方案:

vue.config.js 配置 parallel: false 。构建正式环境关闭 thread-loader

Vue2使用scss报错

vue2 项目使用scss报错 TypeError: this.getOptions is not a function

排查发现是因为sass-loader@11.0.0 不能在 vue@2.6.12 下面工作,我们使用sass-loader 11以下的版本就可以了。

这里我使用的是sass-loader@10.1.1,然后重新运行就可以了。

这里是我在vue2项目环境下使用scss时,安装的依赖版本:

json
"sass": "^1.57.1",
"sass-loader": "^10.1.1",
"style-loader": "^3.3.1",

如何将ts库打包为js库

当然可以,以下是一个使用 Vue CLI 将 TypeScript 库打包为 JavaScript 库的基本步骤:

  1. 首先,你需要在项目中安装 Vue CLI。如果你还没有安装,可以使用以下命令进行安装:
bash
npm install -g @vue/cli
# OR
yarn global add @vue/cli
  1. 创建一个新的 Vue CLI 项目:
bash
vue create my-library

在创建过程中,选择 "Manually select features",然后选择 "TypeScript"。

  1. 在项目中创建你的库。你可以在 src 目录下创建你的 TypeScript 文件。例如,你可以创建一个 src/myLib.ts 文件。

  2. 修改 vue.config.js 文件以将项目配置为库模式。在项目的根目录下创建一个 vue.config.js 文件(如果还没有的话),并添加以下内容:

javascript
module.exports = {
  outputDir: 'dist',
  configureWebpack: {
    output: {
      libraryExport: 'default'
    }
  },
  chainWebpack: config => {
    config.module
      .rule('ts')
      .use('ts-loader')
      .tap(options => {
        options.transpileOnly = true;
        options.happyPackMode = false;
        return options;
      });
  }
}
  1. 最后,你可以使用以下命令将你的 TypeScript 库打包为 JavaScript 库:
bash
vue-cli-service build --target lib --name myLib src/myLib.ts

这将会在 dist 目录下生成一个 myLib.umd.js 文件,这就是你的库文件。

18. 如何将一个Vue3+Ts的Vue组件进行打包

以下是一个使用vue-cli打包Vue3和TypeScript的库的示例¹:

  1. 创建项目:使用vue-cli创建一个Vue3项目,假设项目名为my-vue-library,你可以使用以下命令来创建项目:

    bash
    vue create my-vue-library

    在创建项目时,选择自定义(Manually select features),然后选中Choose Vue version、Babel 、TypeScript、 CSS Pre-processors这4项。在接下来的步骤中,选择3.x (Preview)作为Vue.js的版本,选择n作为Use class-style component syntax?的答案,选择y作为Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?的答案,选择Sass/SCSS (with dart-sass)作为CSS pre-processor,选择In dedicated config files作为配置文件的位置,最后选择y并输入模板名来保存模板¹。

  2. 规划目录:你需要规划你的目录结构,例如:

    plaintext
    ├─ build // 编辑打包脚本目录,用于存放脚本文件
    │ ├─ rollup.config.js
    ├─ docs // 文档目录,用于生成 vuepress 文档页面
    │ ├─ .vuepress
    │ ├─ guide
    │ ├─ README.md
    ├─ examples // 原 src 目录,改成 examples 用于示例展示
    │ ├─ App.vue
    │ ├─ main.ts
    ├─ packages // 新增 packages 目录,用于编写存放组件,如button
    │ ├─ button
    │ ├─ index.ts
    ├─ typings // 新增 typings 目录, 用于存放 .d.ts 文件,把 shims-vue.d.ts 移动到这里
    │ ├─ shims-vue.d.ts
    ├─ .npmignore // 新增 .npmignore 配置文件
    ├─ vue.config.js // 新增 vue.config.js 配置文件
  3. 项目配置:接下来,你需要配置你的项目。首先,新增一个vue.config.js配置文件,适配重新规划后的项目目录:

    javascript
    const path = require('path')
    module.exports = {
      // 修改 pages 入口
      pages: {
        index: {
          entry: "examples/main.ts", //入口
          template: "public/index.html", //模板
          filename: "index.html" //输出文件
        }
      },
      // 扩展 webpack 配置
      chainWebpack: (config) => {
        // 新增一个 ~ 指向 packages 目录, 方便示例代码中使用
        config.resolve.alias
          .set('~', path.resolve('packages'))
      }
    }

    然后,新增一个.npmignore配置文件,组件发布到npm中,只有编译后的发布目录(例如lib)、package.json、README.md才是需要被发布的,所以我们需要设置忽略目录和文件¹。 最后,修改tsconfig.json中paths的路径和include的路径¹。

导入SpringBoot项目后java类不识别

有时候我们导入新的项目后会出现java类不识别的问题:

解决方案:

Project Structure/Modules下,将每一个SpringBoot微服务的java标记为Sourcesresources标记为Resources

20. IDEA导入Maven项目后的三个步骤

  • 第一步:设置maven路径和配置文件File | Settings | Build, Execution, Deployment | Build Tools | Maven

  • 第二步:查看jdk版本File | Settings | Build, Execution, Deployment | Compiler | Java Compiler

  • 第三步:刷新maven

Java分布式微服务启动报错排查思路

如果报错是因为缺少具体某一个模块的依赖,可以在那个子模块下尝试install一下,因为有的模块可能依赖于其他本地的maven模块,install可以将项目安装到本地仓库。

Threejs如何插入图片

在Three.js中,你可以使用TextureLoader来加载一张图片,并将其作为纹理添加到一个材质中。然 后,你可以将这个材质应用到一个Mesh上,这个Mesh可以被添加到你的3D模型中。以下是一个基本 的例子:

js
// 创建一个TextureLoader
var loader = new THREE.TextureLoader();
// 加载一张图片作为纹理
loader.load('my-image.jpg', function(texture) {
// 创建一个材质,并将纹理应用到材质中
var material = new THREE.MeshBasicMaterial({ map: texture });
// 创建一个几何体
var geometry = new THREE.PlaneGeometry(1, 1);
// 创建一个Mesh
var mesh = new THREE.Mesh(geometry, material);
// 设置Mesh的位置
mesh.position.set(0, 0, 0);
// 将Mesh添加到场景中
scene.add(mesh);
});

在这个例子中,我们首先创建了一个TextureLoader,并使用它加载了一张图片。然后,我们创建了一个材质,并将加载的纹理应用到了这个材质中。接着,我们创建了一个Mesh,并将这个材质应用到了Mesh上。最后,我们将Mesh添加到了场景中。

Threejs如何添加一张图片,并添加点击事件

  1. 创建一个摄像头图片的纹理并添加到模型中:你可以使用TextureLoader来加载一张摄像头的图 片,并将其作为纹理添加到一个材质中。然后,你可以将这个材质应用到一个Mesh上,这个 Mesh可以被添加到你的3D模型中。
js
// 创建一个TextureLoader
var loader = new THREE.TextureLoader();
// 加载一张图片作为纹理
loader.load('my-image.jpg', function(texture) {
// 创建一个材质,并将纹理应用到材质中
var material = new THREE.MeshBasicMaterial({ map: texture });
// 创建一个几何体
var geometry = new THREE.PlaneGeometry(1, 1);
// 创建一个Mesh
var mesh = new THREE.Mesh(geometry, material);
// 设置Mesh的位置
mesh.position.set(0, 0, 0);
// 将Mesh添加到场景中
scene.add(mesh);
});
  1. 为摄像头图片添加点击事件:你可以使用Raycaster来检测用户的鼠标点击事件,并判断用户是 否点击了摄像头图片。如果用户点击了摄像头图片,你可以弹出一个HTML编写的弹窗。
js
// 创建一个Raycaster
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
// 添加鼠标点击事件
window.addEventListener('click', function(event) {
// 将鼠标位置归一化为-1到1的范围
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// 通过摄像机和鼠标位置更新射线
raycaster.setFromCamera(mouse, camera);
// 计算物体和射线的焦点
var intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
// 用户点击了摄像头图片
// 在这里弹出HTML编写的弹窗
}
}, false);

记一次数据精度丢失问题

描述: 数据表中id字段类型为bigint,在使用postman等工具测试的时候发现,列表中查询出来的数据,每条数据的id自动减1了,例如库里面id=17454545452,查询出来id=17454545451, 这是因为id数据太大出现了精度丢失的问题。

解决办法: 1、数据表中id 类型设置为varchar 32

2、添加id自动转String类型的注解

java
@JsonSerialize(using = com.fasterxml.jackson.databind.ser.std.ToStringSerializer.class)

上次更新于: