VUE3 动态路由
带参数的动态路由匹配
很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 User
组件,它应该对所有用户进行渲染,但用户 ID 不同。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数 :
const User = {template: '<div>User</div>',
}// 这些都会传递给 `createRouter`
const routes = [// 动态字段以冒号开始{ path: '/users/:id', component: User },
]
现在像 /users/johnny
和 /users/jolyne
这样的 URL 都会映射到同一个路由。
路径参数 用冒号 :
表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params
的形式暴露出来。因此,我们可以通过更新 User
的模板来呈现当前的用户 ID:
const User = {template: '<div>User {{ $route.params.id }}</div>',
}
你可以在同一个路由中设置有多个 路径参数,它们会映射到 $route.params
上的相应字段。例如:
匹配模式 | 匹配路径 | $route.params |
---|---|---|
/users/:username | /users/eduardo | { username: 'eduardo' } |
/users/:username/posts/:postId | /users/eduardo/posts/123 | { username: 'eduardo', postId: '123' } |
除了 $route.params
之外,$route
对象还公开了其他有用的信息,如 $route.query
(如果 URL 中存在参数)、$route.hash
等。你可以在 API 参考中查看完整的细节。
这个例子的 demo 可以在这里找到。
响应路由参数的变化
使用带有参数的路由时需要注意的是,当用户从 /users/johnny
导航到 /users/jolyne
时,相同的组件实例将被重复使用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会被调用。
要对同一个组件中参数的变化做出响应的话,你可以简单地 watch $route
对象上的任意属性,在这个场景中,就是 $route.params
:
const User = {template: '...',created() {this.$watch(() => this.$route.params,(toParams, previousParams) => {// 对路由变化做出响应...})},
}
或者,使用 beforeRouteUpdate
导航守卫,它也可以取消导航:
const User = {template: '...',async beforeRouteUpdate(to, from) {// 对路由变化做出响应...this.userData = await fetchUser(to.params.id)},
}
捕获所有路由或 404 Not found 路由
常规参数只匹配 url 片段之间的字符,用 /
分隔。如果我们想匹配任意路径,我们可以使用自定义的 路径参数 正则表达式,在 路径参数 后面的括号中加入 正则表达式 :
const routes = [// 将匹配所有内容并将其放在 `$route.params.pathMatch` 下{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },// 将匹配以 `/user-` 开头的所有内容,并将其放在 `$route.params.afterUser` 下{ path: '/user-:afterUser(.*)', component: UserGeneric },
]
在这个特定的场景中,我们在括号之间使用了自定义正则表达式,并将pathMatch
参数标记为可选可重复。这样做是为了让我们在需要的时候,可以通过将 path
拆分成一个数组,直接导航到路由:
this.$router.push({name: 'NotFound',// 保留当前路径并删除第一个字符,以避免目标 URL 以 `//` 开头。params: { pathMatch: this.$route.path.substring(1).split('/') },// 保留现有的查询和 hash 值,如果有的话query: this.$route.query,hash: this.$route.hash,
})
更多内容请参见重复参数部分。
如果你正在使用历史模式,请务必按照说明正确配置你的服务器。
高级匹配模式
Vue Router 使用自己的路径匹配语法,其灵感来自于 express
,因此它支持许多高级匹配模式,如可选的参数,零或多个 / 一个或多个,甚至自定义的正则匹配规则。请查看高级匹配文档来探索它们。
路由的匹配语法
大多数应用都会使用 /about
这样的静态路由和 /users/:userId
这样的动态路由,就像我们刚才在动态路由匹配中看到的那样,但是 Vue Router 可以提供更多的方式!
:::tip
为了简单起见,所有的路由都省略了 component
属性,只关注 path
值。
:::
在参数中自定义正则
当定义像 :userId
这样的参数时,我们内部使用以下的正则 ([^/]+)
(至少有一个字符不是斜杠 /
)来从 URL 中提取参数。这很好用,除非你需要根据参数的内容来区分两个路由。想象一下,两个路由 /:orderId
和 /:productName
,两者会匹配完全相同的 URL,所以我们需要一种方法来区分它们。最简单的方法就是在路径中添加一个静态部分来区分它们:
const routes = [// 匹配 /o/3549{ path: '/o/:orderId' },// 匹配 /p/books{ path: '/p/:productName' },
]
但在某些情况下,我们并不想添加静态的 /o
/p
部分。由于,orderId
总是一个数字,而 productName
可以是任何东西,所以我们可以在括号中为参数指定一个自定义的正则:
const routes = [// /:orderId -> 仅匹配数字{ path: '/:orderId(\\d+)' },// /:productName -> 匹配其他任何内容{ path: '/:productName' },
]
现在,转到 /25
将匹配 /:orderId
,其他情况将会匹配 /:productName
。routes
数组的顺序并不重要!
:::tip
确保转义反斜杠( \
),就像我们对 \d
(变成\\d
)所做的那样,在 JavaScript 中实际传递字符串中的反斜杠字符。
:::
可重复的参数
如果你需要匹配具有多个部分的路由,如 /first/second/third
,你应该用 *
(0 个或多个)和 +
(1 个或多个)将参数标记为可重复:
const routes = [// /:chapters -> 匹配 /one, /one/two, /one/two/three, 等{ path: '/:chapters+' },// /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等{ path: '/:chapters*' },
]
这将为你提供一个参数数组,而不是一个字符串,并且在使用命名路由时也需要你传递一个数组:
// 给定 { path: '/:chapters*', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 产生 /
router.resolve({ name: 'chapters', params: { chapters: ['a', 'b'] } }).href
// 产生 /a/b// 给定 { path: '/:chapters+', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 抛出错误,因为 `chapters` 为空
这些也可以通过在右括号后添加它们与自定义正则结合使用:
const routes = [// 仅匹配数字// 匹配 /1, /1/2, 等{ path: '/:chapters(\\d+)+' },// 匹配 /, /1, /1/2, 等{ path: '/:chapters(\\d+)*' },
]
Sensitive 与 strict 路由配置
默认情况下,所有路由是不区分大小写的,并且能匹配带有或不带有尾部斜线的路由。例如,路由 /users
将匹配 /users
、/users/
、甚至 /Users/
。这种行为可以通过 strict
和 sensitive
选项来修改,它们可以既可以应用在整个全局路由上,又可以应用于当前路由上:
const router = createRouter({history: createWebHistory(),routes: [// 将匹配 /users/posva 而非:// - /users/posva/ 当 strict: true// - /Users/posva 当 sensitive: true{ path: '/users/:id', sensitive: true },// 将匹配 /users, /Users, 以及 /users/42 而非 /users/ 或 /users/42/{ path: '/users/:id?' },],strict: true, // applies to all routes
})
可选参数
你也可以通过使用 ?
修饰符(0 个或 1 个)将一个参数标记为可选:
const routes = [// 匹配 /users 和 /users/posva{ path: '/users/:userId?' },// 匹配 /users 和 /users/42{ path: '/users/:userId(\\d+)?' },
]
请注意,*
在技术上也标志着一个参数是可选的,但 ?
参数不能重复。
调试
如果你需要探究你的路由是如何转化为正则的,以了解为什么一个路由没有被匹配,或者,报告一个 bug,你可以使用路径排名工具。它支持通过 URL 分享你的路由。
编程式导航
除了使用 <router-link>
创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。
导航到不同的位置
注意:在 Vue 实例中,你可以通过 $router
访问路由实例。因此你可以调用 this.$router.push
。
想要导航到不同的 URL,可以使用 router.push
方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,会回到之前的 URL。
当你点击 <router-link>
时,内部会调用这个方法,所以点击 <router-link :to="...">
相当于调用 router.push(...)
:
声明式 | 编程式 |
---|---|
<router-link :to="..."> | router.push(...) |
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:
// 字符串路径
router.push('/users/eduardo')// 带有路径的对象
router.push({ path: '/users/eduardo' })// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })
注意:如果提供了 path
,params
会被忽略,上述例子中的 query
并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name
或手写完整的带有参数的 path
:
const username = 'eduardo'
// 我们可以手动建立 url,但我们必须自己处理编码
router.push(`/user/${username}`) // -> /user/eduardo
// 同样
router.push({ path: `/user/${username}` }) // -> /user/eduardo
// 如果可能的话,使用 `name` 和 `params` 从自动 URL 编码中获益
router.push({ name: 'user', params: { username } }) // -> /user/eduardo
// `params` 不能与 `path` 一起使用
router.push({ path: '/user', params: { username } }) // -> /user
当指定 params
时,可提供 string
或 number
参数(或者对于可重复的参数可提供一个数组)。任何其他类型(如 undefined
、false
等)都将被自动字符串化。对于可选参数,你可以提供一个空字符串(""
)来跳过它。
由于属性 to
与 router.push
接受的对象种类相同,所以两者的规则完全相同。
router.push
和所有其他导航方法都会返回一个 Promise,让我们可以等到导航完成后才知道是成功还是失败。我们将在 Navigation Handling 中详细介绍。
替换当前位置
它的作用类似于 router.push
,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。
声明式 | 编程式 |
---|---|
<router-link :to="..." replace> | router.replace(...) |
也可以直接在传递给 router.push
的 routeLocation
中增加一个属性 replace: true
:
router.push({ path: '/home', replace: true })
// 相当于
router.replace({ path: '/home' })
横跨历史
该方法采用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于 window.history.go(n)
。
例子
// 向前移动一条记录,与 router.forward() 相同
router.go(1)// 返回一条记录,与 router.back() 相同
router.go(-1)// 前进 3 条记录
router.go(3)// 如果没有那么多记录,静默失败
router.go(-100)
router.go(100)
篡改历史
你可能已经注意到,router.push
、router.replace
和 router.go
是 window.history.pushState
、window.history.replaceState
和 window.history.go
的翻版,它们确实模仿了 window.history
的 API。
因此,如果你已经熟悉 Browser History APIs,在使用 Vue Router 时,操作历史记录就会觉得很熟悉。
值得一提的是,无论在创建路由器实例时传递什么样的 history
配置,Vue Router 的导航方法( push
、replace
、go
)都能始终正常工作。
导航守卫
正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
全局前置守卫
你可以使用 router.beforeEach
注册一个全局前置守卫:
const router = createRouter({ ... })router.beforeEach((to, from) => {// ...// 返回 false 以取消导航return false
})
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
每个守卫方法接收两个参数:
to
: 即将要进入的目标 用一种标准化的方式from
: 当前导航正要离开的路由 用一种标准化的方式
可以返回的值如下:
false
: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from
路由对应的地址。- 一个路由地址: 通过一个路由地址跳转到一个不同的地址,就像你调用
router.push()
一样,你可以设置诸如replace: true
或name: 'home'
之类的配置。当前的导航被中断,然后进行一个新的导航,就和from
一样。
router.beforeEach(async (to, from) => {if (// 检查用户是否已登录!isAuthenticated &&// ❗️ 避免无限重定向to.name !== 'Login') {// 将用户重定向到登录页面return { name: 'Login' }}})
如果遇到了意料之外的情况,可能会抛出一个 Error
。这会取消导航并且调用 router.onError()
注册过的回调。
如果什么都没有,undefined
或返回 true
,则导航是有效的,并调用下一个导航守卫
以上所有都同 async
函数 和 Promise 工作方式一样:
router.beforeEach(async (to, from) => {// canUserAccess() 返回 `true` 或 `false`const canAccess = await canUserAccess(to)if (!canAccess) return '/login'
})
可选的第三个参数 next
在之前的 Vue Router 版本中,也是可以使用 第三个参数 next
的。这是一个常见的错误来源,可以通过 RFC 来消除错误。然而,它仍然是被支持的,这意味着你可以向任何导航守卫传递第三个参数。在这种情况下,确保 next
在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。这里有一个在用户未能验证身份时重定向到/login
的错误用例:
// BAD
router.beforeEach((to, from, next) => {if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })// 如果用户未能验证身份,则 `next` 会被调用两次next()
})
下面是正确的版本:
// GOOD
router.beforeEach((to, from, next) => {if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })else next()
})
全局解析守卫
你可以用 router.beforeResolve
注册一个全局守卫。这和 router.beforeEach
类似,因为它在每次导航时都会触发,不同的是,解析守卫刚好会在导航被确认之前、所有组件内守卫和异步路由组件被解析之后调用。这里有一个例子,确保用户可以访问自定义 meta 属性 requiresCamera
的路由:
router.beforeResolve(async to => {if (to.meta.requiresCamera) {try {await askForCameraPermission()} catch (error) {if (error instanceof NotAllowedError) {// ... 处理错误,然后取消导航return false} else {// 意料之外的错误,取消导航并把错误传给全局处理器throw error}}}
})
router.beforeResolve
是获取数据或执行任何其他操作(如果用户无法进入页面时你希望避免执行的操作)的理想位置。
全局后置钩子
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next
函数也不会改变导航本身:
router.afterEach((to, from) => {sendToAnalytics(to.fullPath)
})
它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
它们也反映了 navigation failures 作为第三个参数:
router.afterEach((to, from, failure) => {if (!failure) sendToAnalytics(to.fullPath)
})
了解更多关于 navigation failures 的信息在它的指南中。
路由独享的守卫
你可以直接在路由配置上定义 beforeEnter
守卫:
const routes = [{path: '/users/:id',component: UserDetails,beforeEnter: (to, from) => {// reject the navigationreturn false},},
]
beforeEnter
守卫 只在进入路由时触发,不会在 params
、query
或 hash
改变时触发。例如,从 /users/2
进入到 /users/3
或者从 /users/2#info
进入到 /users/2#projects
。它们只有在 从一个不同的 路由导航时,才会被触发。
你也可以将一个函数数组传递给 beforeEnter
,这在为不同的路由重用守卫时很有用:
function removeQueryParams(to) {if (Object.keys(to.query).length)return { path: to.path, query: {}, hash: to.hash }
}function removeHash(to) {if (to.hash) return { path: to.path, query: to.query, hash: '' }
}const routes = [{path: '/users/:id',component: UserDetails,beforeEnter: [removeQueryParams, removeHash],},{path: '/about',component: UserDetails,beforeEnter: [removeQueryParams],},
]
请注意,你也可以通过使用路径 meta 字段和全局导航守卫来实现类似的行为。
组件内的守卫
最后,你可以在路由组件内直接定义路由导航守卫(传递给路由配置的)
可用的配置 API
你可以为路由组件添加以下配置:
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
const UserDetails = {template: `...`,beforeRouteEnter(to, from) {// 在渲染该组件的对应路由被验证前调用// 不能获取组件实例 `this` !// 因为当守卫执行时,组件实例还没被创建!},beforeRouteUpdate(to, from) {// 在当前路由改变,但是该组件被复用时调用// 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`},beforeRouteLeave(to, from) {// 在导航离开渲染该组件的对应路由时调用// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`},
}
beforeRouteEnter
守卫 不能 访问 this
,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next
来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数:
beforeRouteEnter (to, from, next) {next(vm => {// 通过 `vm` 访问组件实例})
}
注意 beforeRouteEnter
是支持给 next
传递回调的唯一守卫。对于 beforeRouteUpdate
和 beforeRouteLeave
来说,this
已经可用了,所以不支持 传递回调,因为没有必要了:
beforeRouteUpdate (to, from) {// just use `this`this.name = to.params.name
}
这个 离开守卫 通常用来预防用户在还未保存修改前突然离开。该导航可以通过返回 false
来取消。
beforeRouteLeave (to, from) {const answer = window.confirm('Do you really want to leave? you have unsaved changes!')if (!answer) return false
}
使用组合 API
如果你正在使用组合 API 和 setup
函数来编写组件,你可以通过 onBeforeRouteUpdate
和 onBeforeRouteLeave
分别添加 update 和 leave 守卫。 请参考组合 API 部分以获得更多细节。
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫(2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫(2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
相关文章:
VUE3 动态路由
带参数的动态路由匹配 很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但用户 ID 不同。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现…...

CentOS软件包管理rpm、yum
一、软件包概述 Linux常见软件包分为两种,分别是源代码包、二进制文件包。源代码包是没有经过编译的包,需要经过GCC、C编译器编译才能运行,文件内容包含源代码文件,通常以.tar.gz、.zip、.rar结尾;二进制包无需编译&am…...

【VSCode】报错:出现段错误解决办法 (Segmentation fault)
VScode报错:Segmentation fault (core dumped)的解决办法 解决Program received signal SIGSEGV, Segmentation fault.的辛酸 Linux环境下段错误的产生原因及调试方法小结 Linux下的段错误Segmentationfault产生的原因及调试方法经典.pdf 在程序中,TF…...
Linux Centos 8 用户管理之重置密码
如果在使用linux系统时遇到系统密码问题无法进入系统或者操作的时候可以按照下面的方法重置用户密码。 一、root用户密码重置: 方式一: 1.重启电脑或虚拟机,在刚进引导界面时候按“e"键,进入编辑模式。 2.在”quiet"…...

C语言快速回顾(三)
前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》,结合我自己的工作学习经历,我准备写一个音视频系列blog。C/C是音视频必…...

【Apollo】Apollo-ros版本架构学习与源码分析
😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍Apollo-ros版本架构学习与源码分析。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下&a…...
【Express.js】集成RabbitMQ
集成RabbitMQ 本节我们介绍在 express.js 中集成 rabbitmq. RabbitMQ 是一个消息队列中间件,常用于请求削峰,事务的队列处理,事件订阅机制的实现等。 准备工作 创建一个 express.js 项目(本文基于evp-express-cli)…...

UI美工设计岗位的基本职责概述(合集)
UI美工设计岗位的基本职责概述1 1、有良好的美术功底、设计新颖,整体配色及设计创意理念,能够独立完成整个网站页面设计及制作; 2、熟练运用DIV CSS,HTML 设计制作网页 ; 3、熟练运用Photoshop,Dreamweaver,Coreldraw(或Illustrator),Fla…...
最强自动化测试框架Playwright(23)-API测试
playwright支持进行API测试 示例: 如下代码创建API请求上下文,使用post方法请求API,并返回响应结果。 import playwright from playwright.sync_api import sync_playwrightwith sync_playwright() as p:api_request_contextp.request.new…...

k8s 自身原理 4
前面咱们分享了 mater 和 worker 节点里面都有哪些组件,他们又是各自主要负责的工作是什么,现在我们心里应该都有数了吧 master 节点: etcd 存储资源配置,ApiServer 提供 RESTful Api 用于交互,scheduler 用于调度 p…...
ZLMediaKit(webrtc)在linux上(CentOS7)部署与启动
一.ZLMediaKit(webrtc)在CentOS7部署与启动 # 1. 卸载旧版本 yum remove git # 2. 安装 yum 源的 Git 版本 yum install -y git # 3. 查看版本 git version # 输出 git version 1.8.3.1配置全局环境变量 # 1. 编辑配置文件 vim /etc/profile # 2. 在 /etc/profile 文件中末尾…...
汽车基础软件新「战争」:群雄混战,谁在抢跑?
中国车用基础软件迎来了发展的黄金窗口期。 当前,汽车电子电气架构正在加速向“跨域融合”的时代演进,汽车软件架构也在加速向SOA架构升级,软硬件分层解耦成为了实现“软件定义汽车”新开发模式的前提。 过去,汽车的所有功能开发…...

阿里云预装LAMP应用导致MySQL不显示访问密码如何解决
😀前言 本篇博文是关于阿里云云服务器ECS部署MySQL过程中出现的一下坑,希望能够帮助到您😊 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家…...
SQL 自动清除7天前数据前收缩数据库
作用: 删除七天前数据库中间表的资料,并收缩数据库 delete-Ecustom-xml-midtable.sql delete Mid_bom where datediff(day,dty,getdate())>7 delete Mid_cus where datediff(day,dty,getdate())>7 delete Mid_exp where datediff(day,dty,getdate(…...

LangChain-ChatGLM在WIndows10下的部署
LangChain-ChatGLM在WIndows10下的部署 参考资料 1、LangChain ChatGLM2-6B 搭建个人专属知识库中的LangChain ChatGLM2-6B 构建知识库这一节:基本的逻辑和步骤是对的,但要根据Windows和现状做很多调整。 2、没有动过model_config.py中的“LORA_MOD…...

Telerik UI for ASP.NET Core Crack
Telerik UI for ASP.NET Core Crack Telerik ASP.NET Core还包括MVC和Kendo UI捆绑包(用于JavaScript)、Figma的设计工具包以及文档处理库、用于ASP.NET Core的Telerik REPL、RTL支持、辅助功能和键盘导航、主题化、虚拟课堂培训、详细文档、演示、KBs和世界级支持。使用一整套…...

【TypeScript】中关于 { 声明合并 } 的使用及注意事项
概念: 在TS中,如果定义了多个相同命名的函数,接口或者class 类,那么它们会自动合并成一个类型 函数的合并: 前面章节讲解的函数重载就是使用了定义多个函数的类型进行合并: function reverse(x: number):…...
Day 43
Day 43 1049.最后一块石头的重量II 本题中,石头的重量是 stones[i],石头的价值也是 stones[i] ,可以 “最多可以装的价值为 dp[j]” “最多可以背的重量为dp[j]” dp[j] max(dp[j], dp[j - stones[i]] stones[i]); 最后dp[target]里是…...
服务器安全需要注意的几个方面?
服务器安全需要注意的几个方面? 服务器的核心技术相对复杂,专业人员稀少,尤其在病毒技术快速更新迭代的前提下,安全问题更为突出。这里提供一些实际工作中总结出的安全防护经验,以供参考。 一,增强网络整…...

Mysql数据库第十三课-----------sql语句的拔高3--------直冲云霄
作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 🎂 作者介绍: 🎂🎂 🎂 🎉🎉🎉…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...

【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...