跳到主要内容位置
Hello! 我是潜心专研的小张同学

在这里,有技术博客、以及UP主的想法和生活点滴。授人以鱼不如授人以渔,分享个人所学所见,在你学习前端开发的路上助你一臂之力!

QQ 1 群:706947563

去B站关注

最新博客 

使用AI自动写代码,DeepSeek+CLine+VSCode实战教程

0 前言#

最近 DeepSeek 火了起来,各个媒体都在宣传,那 DeekSeek 到底是个啥?从程序员角度来看:DeepSeek 一个人工智能助手,可以帮助我们解决代码知识点疑问,以及某个晦涩难懂的知识点问题,处理生活中的一些文本信息问题等。

其实这些能力早在数年前 ChatGPT 也已经具备了,那么为什么最近 DeepSeek 这么火呢?一个原因就是因为它是国产的,那必须得支持。还有一个原因就是它实惠呀,便宜!目测目前比 ChatGPT 要便宜了近 10 倍不止吧~ 咱能用得起了…… 在价格下降的同时,表现的能力也是越来越聪明。

下面主要是介绍 DeepSeek+CLine+VSCode 的实战教程,所表现出了的能力也是相当出色的,可以直接操控我们的编译器来写代码, 自动写代码!也就是说它除了回答我们一些专业问题之外,还可以直接对我们的文件目录及文件内容进行增删改查!

1 先上结果#

pEnSBqJ.png](https://imgse.com/i/pEnSBqJ)

2 注册使用 deepseek 模型的账号#

这里注册 deepseek 账号我们可以选择在其官网上注册使用,也可以选择在其他平台上注册使用。但是现在 deepseek 官网因为频繁受到某国不知名网络的攻击已经关闭了新的注册入口。

现在主要是来介绍在华为云上面的注册方法,使用的效果也是相当可以的,华为云也是相对稳定一些。

首先点击下面的链接可以注册个账号,现在注册可以免费获得 14 块钱的使用额度:

https://cloud.siliconflow.cn/i/10XZLZAC

3 创建秘钥#

我们注册好账号后,再来创建一个 API 秘钥,后面要用到

pEnStP0.png](https://imgse.com/i/pEnStP0)

4 vscode 安装 cline 及配置 deepseek 模型#

刚刚的账号及 API 秘钥弄好以后,我们来到 vscode

4.1 在 vscode 中安装 cline 插件#

安装一个 cline 插件,这个插件可以自动操作我们的 vscode 终端,配合 deepseek、chatgpt 这个 AI 助手来使用效果相当强劲

pEnSbJP.png

4.2 配置 deepseek 模型#

下载好 cline 插件后,我们点击 vscode 侧边栏的 cline 的界面,在里面配置 deepseek 模型,见图 4-2-1

pEnSqRf.png

(图 4-2-1)

图 4-2-1 里面 2.2 文字内容:

https://api.siliconflow.cn/v1

图 4-2-1 里面的 2.3 秘钥就是之前我们创建的那个秘钥

图 4-2-1 里面的 2.4 内容,我选的是 deepseek 最聪明的(最贵的)那个模型:

deepseek-ai/DeepSeek-R1

配置完以后我们带点击一下那个“Done”按钮,就会保存我们的配置。

5 开始使用 vscode+cline+deepseek 写代码#

刚刚我们都已经配置好了,现在开始使用

pEnSXQS.png

pEnSvLQ.png

ok,到这里已经配置完成啦~ 可以体验 AI 写代码的魅力了~

阿里云域名申请ssl证书,通过https方式访问域名

之前我们提到了如何创建子域名,并且已经创建了子域名,那么我们创建了域名以后如何更好升级域名的安全性呢?其实这些域名都是以 http 开头的,不是 https,这个时候我们就要来申请 ssl 证书,通过部署 ssl 证书将域名升级为以 https 的形式来访问。

1. 填写完对应申请的域名,然后点“提交审核”#

img

img

2. SSL 证书验证#

接下了我们要进行一下 ssl 证书验证,点击“验证按钮”

img

然后我们可以看到这个记录值,记录下来,这个要域名解析那边填写一下

img

3. 域名解析添加记录值#

我们来域名解析页面,点击“解析设置”按钮

img

然后点击“添加记录”按钮,填写我们刚刚记录的值,记住一定要完全一致哦,不要填多了(之前我就是主机记录那里字符填多了,导致域名好几填都没有验证通过。。)。

img

4. 再次验证 SSL 证书#

这个时候我们再次回到 ssl 证书管理页面,点击验证(一般 2、3 分钟就可以生效),这个时候就可以验证成功了。

img

5. 小结#

至此,SSL 证书申请的流程已经操作完毕了,只需要静静等待邮箱发送申请成功的邮件就可以了,一般大概 10 分钟左右吧。

阿里云创建子域名(二级域名),同时结合腾讯云

申请子域名基于我们已经有了主域名的情况,如果我们没有主域名先要去搞一个主域名。

那么我们为啥需要子域名了,那肯定是一个域名不够用,需要多个域名,不同的域名对应不同的网站,这样一个几十块的域名就能创建出几十个子域名(对应几十个网站),单从使用性价比方面还是不错的,hhhh

1. 进入域名解析界面,添加子域名#

进入域名解析界面,点击添加域名,我这里添加一个二级域名,然后我输入了二级域名,下面有提示要进行“TXT授权校验”,没事,那我们就去TXT授权校验。

img

2. 进行TXT授权校验#

点击这个链接

img

点击完出现这个信息,记一下,我们要去填到对应的地方

img

域名:zhangqiang.hk.cn
主机记录:alidnscheck
记录值:c350e166c50d4d6a8b2993efcd93430b

3. 添加记录值#

3.1. 腾讯云#

因为我的域名是从腾讯云转过来的,所以我需要也在腾讯云里面添加一下记录值(如果你都是用的阿里云的,那就不用管了),创建如下

img

添加完点击确认,这上面说是要24小时,但是只要我们配置正确的话5、6分钟就会生效了

img

3.2. 阿里云#

阿里云的域名解析里面也要添加记录值

img

4. 验证子域名,添加域名#

刚刚记录值我们都已经填完了,有延迟,需要等5分钟左右,再来验证,我这里是等了5分钟左右的,然后验证成功

img

img

5. 小结#

至此,阿里云创建子域名(二级域名)同时结合腾讯云完成,我们只要在服务器上面给这个域名部署相关的资源(比如网站资源、后台服务等)就可以访问到了。

解决 Vite 项目启动时端口重复问题的总结


背景#

在前端开发的江湖上,Vite 就像一个轻盈迅捷的剑客,以“快”和“爽”闻名。默认栖身于本地 3000 端口,简直是开发者的“专属包间”。但江湖人多,难免遇到这种情况:你刚起剑练招,发现隔壁的同门师兄已经占了你的包间。于是,你只能抱着代码,哼哼唧唧换个地方继续修炼——这种“被端口抢占”的故事,简直就是开发者的日常笑话!

例如:

  1. 多人协作:团队中的多个开发者同时运行了 Vite 项目,使用了相同的端口。
  2. 多项目运行:本地同时启动了多个 Vite 项目或其他服务(如 Webpack、Node.js 服务器),导致端口冲突。
  3. 默认配置不足:Vite 默认没有处理端口占用的逻辑,遇到冲突会直接报错,开发中断。

为了解决这个问题,我研究了几种方法,最终采用了 detect-port 插件,实现了动态检测和自动调整端口的功能,极大地提升了开发效率。


解决方案#

1. 常见解决方法#

1.1 *手动更改端口**#

vite.config.ts 文件中修改 server.port 的值。例如:

export default defineConfig({
server: {
port: 3001 // 手动指定一个新的端口
}
})

缺点:需要手动调整端口,效率较低,且不方便多人协作。

1.2 尝试端口范围#

一些开发者会通过运行脚本动态尝试多个端口,但编写脚本可能较繁琐且不直观。

1.3 使用第三方工具#

利用工具如 detect-portportfinder,自动检测端口是否被占用并返回可用端口。

2. Detect-port 的解决方案(本人的解决方法)#

我最终采用了 detect-port 插件,因为它简单易用,能够自动检测当前端口是否被占用,并返回一个可用的端口。

Step 1: 安装 detect-port#

在项目根目录下运行以下命令:

pnpm install detect-port --save-dev

或者使用 npm/yarn 安装:

npm install detect-port --save-dev
yarn add detect-port --dev

Step 2: 配置 Vite 项目#

修改 vite.config.ts 文件,引入 detect-port,实现动态端口检测:

import { defineConfig } from 'vite'
import detectPort from 'detect-port'
export default defineConfig(async () => {
const DEFAULT_PORT = 3000 // 默认端口
// 使用 detect-port 检测端口是否被占用
const port = await detectPort(DEFAULT_PORT)
console.log(`Selected port: ${port}`) // 输出实际选用的端口
return {
server: {
host: '0.0.0.0', // 允许局域网访问
port, // 动态端口
open: true, // 自动打开浏览器
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
}
})

Step 3: 效果展示#

  • 如果默认端口(如 3000)已被占用,detect-port 会自动检测下一个可用端口,例如 3001 或 3002。
  • 启动时会输出实际使用的端口号:
Selected port: 3001

这样,我们无需手动修改端口设置,提升了开发效率。lalala~

3. 优化点#

在实践中,我还添加了一些优化:

3.1 添加日志输出#

使用 console.log 记录端口信息,便于调试:

console.log(`Using port ${port}. To change, edit vite.config.ts`)

3.2 范围检测(可选)#

通过扩展 detect-port,可尝试在特定范围内寻找端口:

const port = await detectPort(3000)
if (port !== 3000) {
console.log(`Port 3000 is in use. Using port ${port} instead.`)
}

小结#

问题总结#

Vite 默认端口冲突的问题在多人协作和多项目运行的场景中非常常见。传统的手动解决方案需要频繁调整配置,显得麻烦且低效。

我的解决方案#

利用 detect-port 插件,可以轻松实现动态端口检测和分配:

  • 自动检测端口冲突。
  • 动态分配可用端口,提升开发效率。
  • 配置简单、易于扩展。

未来优化#

  • 扩展端口范围检测:可以尝试自定义检测端口范围(如 3000-3100)。
  • 集成其他工具:例如结合 vite-plugin-inspect,提供更多启动信息。
  • 多环境支持:为不同环境(开发、测试、生产)定制端口策略。

在团队开发中,这种自动化的方式能够显著减少端口冲突问题,提升协作效率,非常值得推广。

Vue3中watch中props监听加箭头函数与不加箭头函数的区别

1 前言#

今天写项目时,遇到一个问题,我需要打开点击一个按钮打开一个弹框页面,然后通过watch去监听传进来的值,但是呢,写了watch我点击按钮只有首次打开能够监听到,尽管加上了deep: true页面也不能监听到变化,点击效果如下图:

image-20240903172257604

2 代码实例#

直接上我的关键代码,这个是我弹框页面的代码:

<template>
<div class="content_container">1111</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, watch, onActivated } from 'vue'
import { ElMessageBox } from 'element-plus'
const props = defineProps(['currentRow'])
console.log('props', props)
watch(
props.currentRow,
(newVal, oldVal) => {
console.log('newVal', newVal)
},
{
immediate: true,
deep: true
}
)
</script>

解决后的代码:

<template>
<div class="content_container">1111</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, watch, onActivated } from 'vue'
import { ElMessageBox } from 'element-plus'
const props = defineProps(['currentRow'])
console.log('props', props)
watch(
() => props.currentRow,
(newVal, oldVal) => {
console.log('newVal', newVal)
},
{
immediate: true,
deep: true
}
)
</script>

其实,只是修改了一句话,多加了一个箭头函数~ 就可以了!他就可以每次进来就都监听了,为啥呢?请看下面的代码精读环节

3 代码精读#

3.1 直接监听 props 属性#

javascriptwatch(
props.currentRow,
(newVal, oldVal) => {
console.log('newVal', newVal);
},
{
immediate: true,
deep: true
}
);

当你直接监听 props.currentRow 时,watch 函数会尝试将 props.currentRow 当作一个响应式引用进行监听。然而,props 本身并不是一个响应式引用,而是一个对象。因此,这种方式可能会导致以下问题:

  • 非响应式引用: 如果 props.currentRow 是一个简单的值(如字符串或数字),那么 watch 可能无法正确地监听到它的变化。
  • 对象或数组内部属性变化: 即使设置了 deep: truewatch 仍然可能无法正确地监听到对象或数组内部属性的变化。

3.2 使用箭头函数监听 props 属性#

javascriptwatch(
() => props.currentRow,
(newVal, oldVal) => {
console.log('newVal', newVal);
},
{
immediate: true,
deep: true
}
);

使用箭头函数 () => props.currentRow 可以确保每次 props.currentRow 发生变化时,都会重新计算并触发 watch 回调。这种方式更可靠,因为它明确地告诉 watch 如何获取最新的 props.currentRow 值。

4 总结#

在正常的开发中,我们应该使用箭头函数组合watch来进行props值的变化,来确保每次 props 变化时都能重新计算。

pnpm依赖安装解决pnpm项目从一个文件夹复制到另一个文件夹运行失败问题解决-以vbenAdmin项目为例

1 前言#

最近在使用 vben admin 项目迁移时,从一个文件夹复制到另一个文件夹运行不起来,排查了一天,终于把问题排查出来了,特地记录一下,便于自己看也便于大家看。

使用项目安装包版本:

v2.11.5 https://github.com/vbenjs/vue-vben-admin/tags

2 解决方案#

2.1 软链接问题解决#

问题: pnpm 使用硬链接或符号链接来管理 node_modules 中的依赖项。如果链接路径在新的文件夹或文件系统中失效,可能会导致依赖解析失败。

解决方法: 尝试删除并重新安装所有依赖,确保链接正确创建。

rm -rf node_modules pnpm-lock.yaml

node_modules 文件夹一定要全部删除,pnpm-lock.yaml文件也要删除,上述是用命令删除的,也可以自己手动删(所有的 node_modules 都要删)

image-20240830135249168

2.2 文件路径过长问题#

问题: 在 Windows 系统上,文件路径过长(超过 260 个字符)可能导致文件系统问题,导致文件无法被正确访问。

解决方法: 尝试将项目目录移动到一个路径较短的位置,比如 C:\Projects\my-project,然后重新安装依赖。

node_modules 文件夹里面的内容路径会很长,所以整个项目文件夹所在路径不宜过长,否则路径可能会超过 260 个字符。

image-20240830135718984

2.3 pnpm 缓存问题#

问题: pnpm 的缓存可能导致一些包没有被正确更新或安装。

解决方法: 清除 pnpm 的缓存:

依次执行下面命令

  • 清理未使用的缓存包
pnpm store prune
  • 清空整个 pnpm 的缓存存储库
pnpm store clear

2.4 pnpm 缓存深度清理#

执行下面这句话:

pnpm store path

然后我们看到这个路径

image-20240830140127029

进入这个目录,将这 3 个文件夹都手动删除

image-20240830140240181

2.5 pnpm install#

删完之后,执行pnpm install

pnpm install

image-20240830141017683

2.6 pnpm dev#

等待依赖安装完毕后,我们执行pnpm dev

pnpm dev

程序运行成功

image-20240830142025994

3 pnpm 安装依然失败解决方案#

当我们试了各种方法还是不行,诶?这个时候我们返璞归真,是不是我们的 pnpm 的源下载不了的原因呢?国内的 pnpm 下载出现网络相关的问题还是挺多的,那么让我们来替换成国内专属的 pnpm 源试试

3.1 国内可用源#

3.1.1 淘宝 pnpm 源

https://registry.npmmirror.com

3.1.2 腾讯云 pnpm 源

https://mirrors.cloud.tencent.com

3.1.3 cnpm 源

https://r.cnpmjs.org/

3.2 设置国内可用源命令#

pnpm config set registry https://registry.npmmirror.com

3.3 查看设置的源#

pnpm config get registry

返回信息内容是你刚刚设置地址,即设置成功。

image-20240929154343078

3.4 再次 pnpm install#

ok,pnpm 相关依赖在徐徐下载,我的终于又又装成功了~

4 遗留的瑕疵#

项目虽然可以成功运行了,也可以正常写代码的了,但是终端还有几个 warning ,如果有大佬知道如何解决也可以指点一下,感谢~

image-20240830142224622

为什么 2!=false 和 2!=true 返回的都是true

前言#

今天突然想起一个奇怪的问题,记录一下,我在控制台执行内容如下:

image-20240821171734282

由上图可见,2 != false2 != true 返回的值竟然都是true,那么为什么呢,请看下文:

1 != 操作符的作用#

  • != 是“不等于”操作符。它会在比较前执行类型转换,然后再比较两个值是否不相等。

    在 JavaScript 中,2 != false2 != true 返回 true 的原因涉及到 JavaScript 中的类型转换和比较规则。

2 类型转换#

当使用 != 进行比较时,JavaScript 会尝试将比较的两个值转换为相同的类型,然后再进行比较。以下是 2 != false2 != true 的过程:

2 != false#

  1. false 会被转换为数字类型。根据 JavaScript 的转换规则,false 被转换为 0
  2. 现在表达式变成了 2 != 0
  3. 20 不相等,因此返回 true

2 != true#

  1. true 会被转换为数字类型。根据 JavaScript 的转换规则,true 被转换为 1
  2. 现在表达式变成了 2 != 1
  3. 21 不相等,因此返回 true

总结#

  • 2 != false 返回 true 是因为 20 不相等。
  • 2 != true 返回 true 是因为 21 不相等。

这就是为什么 2 != false2 != true 都会返回 true

Vue3使用Element Plus单个Tag标签文字过长自动换行代码实现

1 需求引入#

直接上图,原先程序显示效果是这样:

image-20240807172107258

由上图可见,element plus 的 tag 标签组件里面内容过长时,把页面都撑开了,不能自动换行,我的 tag 标签代码原先是这样写的

<div style="width: 100%; margin-bottom: 5px">
<el-tag v-if="uploadMessage.successMessage.length > 0" :type="'success'" effect="plain">
{{ uploadMessage.successMessage }}
</el-tag>
</div>

2 解决需求,代码实现#

先看解决效果图:

image-20240807172500463

如何解决的呢,只要我们再单独写一下 css 的样式就 ok 了,看下面的 css 样式代码:

.el-tag {
white-space: normal;
height: auto;
padding: 2px;
display: inline-block;
}

好了,直接加上上面这段 css 代码就 ok 了。

3 小结#

我当时用这个标签是显示错误信息的,后来发现 element 的 Alert 组件用于现实错误信息才比较合适,因为那个有个关闭的按钮,既然已经写了,就记录一下吧~ 希望对看文章的你也有些用吧 ~ >_< ~

async、await的这个小细节你知道?async、await多次实践使用后的一点小结(async返回异步问题)

前言#

我们都知道async、await 是用来将“同步函数变成异步函数,可以同步获取到里面异步函数的返回值”的,比如我们在请求一个接口的时候,这个接口的返回值是一个异步的,那我们就可以用 await 将这个异步接口返回变成同步,使我们可以同步的获取到接口的返回值,然后在紧接着的下文中就可以直接用这个接口的返回值。

一 实例 1#

循序渐进,先上一个简单的代码

const asyncFun = (value: number) => {
return new Promise((resolve, reject) => {
// 模拟一个异步请求
setTimeout(() => {
resolve(value + 1)
}, 2000)
})
}
const getValue = async () => {
let result = await asyncFun(1)
console.log('result:', result)
}
getValue() // result:2

如上图代码,输出的结果是

result: 2

我们来浅分析一下这段代码,这段代码其实我们是模拟了一个接口请求的操作,asyncFun(value: number)返回一个 Promise,Promise 就代表这个结果是一个异步的,当我们调用这个函数时得到的结果就会等所有同步代码执行完以后才会得到这个 Promise 的结果。

如果我们调用asyncFun(value: number)这个函数想要同步获取到里面的结果,获取完这个结果后,紧接着同步执行下面的代码,那我们就要使用asyncawait 来解决,这是ES6 推出的新语法,好用的很啊,但是也有一些细节需要注意(下文会提到)。

所以我们在使用getValue() 这个函数调用asyncFun(value: number)时,首先在getValue()函数头部加了 async,声明咱这个函数是一个异步函数,这样在这个函数里面我们就可以用await将异步的返回值转为同步获取到了,所以await asyncFun(1); 的意思是等这里完全执行完(2 秒之后),获取到value+1这个具体数值,然后才会执行console.log('result:', result); 这句话。

所以上面这段代码最后输出的就是

result: 2

二 实例 2(踩坑记录)#

同样的,咱们也是直接上代码块,大家看一下这段代码输出的是个啥:

const asyncFun = (value: number) => {
return new Promise((resolve, reject) => {
// 模拟一个异步请求
setTimeout(() => {
resolve(value + 1)
}, 2000)
})
}
const getValue = async () => {
let result = await asyncFun(1)
return result
}
const add666Value = () => {
let result: any = getValue()
result = result + '666'
console.log('result:', result)
}
add666Value()

上面这段代码就是将getValue()方法又封装了一遍,得到这个结果,然后再去输出这个结果,那么大家觉得这个是个啥值呢?可能有的人会认为输出的是result: 2666,其实不然,真正输出的结果是:

result: [object Promise]666

嘿嘿,这是为啥呢?这就是前面说的那个小细节了,使用 async 声明的函数其返回值是一个 Promise。通常我们写一个普通函数,想 return 啥它就能直接 return 啥,但是只要在这个函数头上加了 async ,那它就会返回 Promise 类型,这个函数的返回值就是一个异步的了,等到所有同步函数执行完以后才会等到里面的确切值。

比如这个小例子 1:

const littleExample1 = () => {
const a = 1
return a
}

这个littleExample1()的返回值就是一个 number 类型的 1;

而看下面这个小例子 2:

const littleExample2 = async () => {
const a = 1
return a
}

嘿,这个小例子 2 返回的就是个 Promise 了,你就说细节不细节,之前都没关注过,但这个场景确实在实际使用中有用到的,然后我就说为啥返回值不是预期的值呢,结果一排查就是这个 async 的原因。

三 实例 2 解决方案#

话不多说,我们来看看 实例2 中的代码块如何处理才能得到一个我们预期的值,也就是: result: 2666 ,直接上代码:

const asyncFun = (value: number) => {
return new Promise((resolve, reject) => {
// 模拟一个异步请求
setTimeout(() => {
resolve(value + 1)
}, 2000)
})
}
const getValue = async () => {
let result = await asyncFun(1)
return result
}
const add666Value = async () => {
let result: any = await getValue()
result = result + '666'
console.log('result:', result)
}
add666Value()

ok,这样子就是我们预期的输出结果了,也就是我们将add666Value()前面加了个 async ,将其声明为异步函数getValue()前面再加个await ,这样getValue()返回的结果就不是 Promise 了,result 就可以得到一个 number 类型的 2,number 类型+string 类型时前面的 number 类型会变成 string 类型,相当于'2'+'666',所以最终输出的结果就是:

result: 2666

至此,async返回异步问题已解决。

四 加强记忆#

知识点参考:

  • AsyncFunction

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction