Vue3 集成 VueRouter

Vue Router 是 Vue.js 的官方路由管理器,用于构建单页面应用程序(SPA)。它与 Vue.js 核心深度集成,使得构建单页应用变得简单高效。

  • Vue Router | Vue.js 的官方路由

使用场景

  • 构建单页面应用程序(SPA)
  • 需要前端路由管理的项目
  • 需要实现页面导航、路由守卫和懒加载等功能
  • 需要基于路由的参数传递和状态管理

注意事项

  1. Vue Router 4.x 专为 Vue 3 设计,与 Vue 2 需要使用 Vue Router 3.x
  2. 路由配置应合理组织,避免过于复杂嵌套
  3. 注意路由守卫的执行顺序和时机
  4. 动态路由参数变化时组件不会重新创建,需要使用监听器处理
  5. 路由模式分为 hash 模式和 history 模式,后者需要服务器配置支持

基本用法

安装与配置

npm install vue-router@4
yarn add vue-router@4
pnpm add vue-router@4

配置 router/index.ts

创建 src/router/index.ts 文件
在 src 下创建 router 目录,然后在 router 目录里新建 index.ts 文件:

 └── src/├── router/├── index.ts  // 路由配置文件
// router/index.ts
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';// 定义路由配置
const routes: Array<RouteRecordRaw> = [{path: '/',name: 'Home',component: () => import('@/views/HomeView.vue')},{path: '/about',name: 'About',component: () => import('@/views/AboutView.vue')},{path: '/user/:id',name: 'User',component: () => import('@/views/UserView.vue'),props: true // 将路由参数作为 props 传递给组件}
];// 创建路由实例
const router = createRouter({history: createWebHistory(), // 使用 HTML5 History 模式routes
});export default router;

方式2

import { type RouteRecordRaw } from 'vue-router';
declare module 'vue-router' {interface _RouteRecordBase {hidden?: boolean | string | number;}
}
const routes: RouteRecordRaw[] = [{path: '/index',name: 'index',component: () => {return import('../components/Homepage.vue');},meta: {keepAlive: true},children: [// 添加子路由{path: 'article',name: 'article',component: () => {return import('../views/page/article/index.vue');}},{path: 'TestTool',name: 'TestTool',component: () => {return import('../views/page/testTool/TestTool.vue');},children: [// 添加子路由{path: 'TestToolConvert',name: 'TestToolConvert',component: () => {return import('@/views/page/testTool/TestToolConvert.vue');}}]}]},{ path: '/', redirect: { name: 'home' } }
];
export default routes;

新建router/index.ts

// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { createRouter, createWebHistory, _RouteRecordBase } from 'vue-router'
import routes from './routes'
import NProgress from 'nprogress'const router = createRouter({history: createWebHistory(), //历史模式会制造页面刷新routes
})
// 页面切换之前取消上一个路由中未完成的请求
router.beforeEach((_to: any, _from: any, next: () => void) => {NProgress.start()next()
})
router.afterEach(() => {// 进度条NProgress.done()
})
export default router

挂载路由配置

main.ts 文件中挂载路由配置

import { createApp } from 'vue'
import App from './App.vue'import router from './router/index'
// use
const app = createApp(App)
app.use(router)

在组件中使用路由

<template><div><nav><router-link to="/">首页</router-link><router-link to="/about">关于</router-link><router-link :to="{ name: 'User', params: { id: 123 }}">用户页面</router-link></nav><!-- 路由出口 --><router-view /></div>
</template><script lang="ts" setup>
import { useRouter, useRoute } from 'vue-router'// 获取路由实例和当前路由
const router = useRouter()
const route = useRoute()// 编程式导航
const goToAbout = () => {router.push('/about')// 或者使用命名路由// router.push({ name: 'About' })
}const goToUser = (id: number) => {router.push({ name: 'User', params: { id } })
}// 替换当前路由(不添加历史记录)
const replaceRoute = () => {router.replace('/about')
}// 前进后退
const goBack = () => {router.go(-1) // 后退一步
}const goForward = () => {router.go(1) // 前进一步
}
</script>

路由出口

<template><div id="app"><router-view v-slot="{ Component }"><keep-alive><component :is="Component" v-if="$route.meta.keepAlive" /></keep-alive><component :is="Component" v-if="!$route.meta.keepAlive" /></router-view></div>
</template>

常用操作

路由参数和查询参数

<template><div><h1>用户详情</h1><p>用户ID: {{ userId }}</p><p>用户名: {{ username }}</p></div>
</template><script lang="ts" setup>
import { useRoute } from 'vue-router'
import { computed, watch } from 'vue'const route = useRoute()// 获取路由参数
const userId = computed(() => route.params.id as string)// 获取查询参数
const username = computed(() => route.query.name as string || '未知用户')// 监听路由参数变化
watch(() => route.params.id,(newId) => {console.log('用户ID变化:', newId)// 可以在这里重新获取用户数据}
)
</script>

嵌套路由

// router/index.ts
const routes: Array<RouteRecordRaw> = [{path: '/user/:id',component: () => import('@/views/UserLayout.vue'),children: [{path: '',name: 'UserProfile',component: () => import('@/views/UserProfile.vue')},{path: 'posts',name: 'UserPosts',component: () => import('@/views/UserPosts.vue')},{path: 'settings',name: 'UserSettings',component: () => import('@/views/UserSettings.vue')}]}
]
<!-- UserLayout.vue -->
<template><div><h1>用户页面</h1><nav><router-link :to="{ name: 'UserProfile', params: { id: $route.params.id }}">资料</router-link><router-link :to="{ name: 'UserPosts', params: { id: $route.params.id }}">帖子</router-link><router-link :to="{ name: 'UserSettings', params: { id: $route.params.id }}">设置</router-link></nav><!-- 嵌套路由出口 --><router-view /></div>
</template>

路由守卫

// router/index.ts
import type { NavigationGuardNext, RouteLocationNormalized } from 'vue-router'// 全局前置守卫
router.beforeEach((to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {// 可以在这里进行权限检查const isAuthenticated = checkAuth() // 假设的认证检查函数if (to.meta.requiresAuth && !isAuthenticated) {next({ name: 'Login', query: { redirect: to.fullPath } })} else {next()}
})// 全局后置钩子
router.afterEach((to, from) => {// 可以在这里进行页面跟踪等操作document.title = to.meta.title as string || '默认标题'
})// 路由独享的守卫
const routes: Array<RouteRecordRaw> = [{path: '/admin',component: () => import('@/views/AdminView.vue'),beforeEnter: (to, from, next) => {// 检查管理员权限if (isAdmin()) {next()} else {next({ name: 'Home' })}}}
]
<!-- 组件内守卫 -->
<script lang="ts" setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'// 在组件卸载前调用
onBeforeRouteLeave((to, from, next) => {// 可以在这里询问用户是否确认离开const answer = window.confirm('确定要离开吗?未保存的更改将会丢失。')if (answer) {next()} else {next(false)}
})// 在当前路由更新但该组件被复用时调用
onBeforeRouteUpdate((to, from, next) => {// 可以在这里获取新的数据fetchUserData(to.params.id as string)next()
})
</script>

配置404页面.

修改router/routes.ts

* 代表通配符,若放在任意路由前,会被先匹配,导致跳转到 404 页面,所以需将如下配置置于最后。

const routes = [...//添加(放在最后){path: "/:pathMatch(.*)*",component: () => import("@/pages/notFound.vue"),},{path: '*',name: '404'component: () => import('./404.vue')  }
];

路由重定向

在嵌套路由中,当访问/home时想重定向到/home/user

修改router/routes.ts

{path: '/home',component: () => import('@/pages/home.vue'),redirect: '/home/user', //新增children: [{path: '/home/user',component: () => import('@/pages/user.vue'),},{path: '/home/manage',component: () => import('@/pages/manage.vue'),},],},

刷新当前路由.

//+new Date()保证每次点击路由的query项都是不一样的,确保会重新刷新view
const routers = async (path: string) => {await router.push({path: path,query: {t: +new Date()}})
}

跳转新窗口.

/*** @description: 跳转新页面* @param {string} url* @return {*}*/
function winUrl(url: string): any {window.open(url)
}async function resolveId(path: string, id: number) {const { href } = resolve(path, id)await winUrl(href)
}

高级用法

路由懒加载

使用() => import()方式导入的组件,只会在第一次进入页面时才会加载对应路由的组件

// 方式1
const UserDetails = () => import('./views/UserDetails.vue')
const router = createRouter({// ...routes: [{ path: '/users/:id', component: UserDetails }],
})// 方式2
// 使用动态导入实现懒加载
const routes: Array<RouteRecordRaw> = [{    path: '/admin',name: 'Admin',component: () => import(/* webpackChunkName: "admin" */ '@/views/Admin.vue')}
]

滚动行为

// router/index.ts
const router = createRouter({history: createWebHistory(),routes,scrollBehavior(to, from, savedPosition) {// 返回滚动位置if (savedPosition) {return savedPosition} else if (to.hash) {return {el: to.hash,behavior: 'smooth'}} else {return { top: 0, left: 0 }}}
})

动态路由

// 添加路由
const newRoute: RouteRecordRaw = {path: '/new-route',component: () => import('@/views/NewView.vue')
}
router.addRoute(newRoute)// 添加嵌套路由
router.addRoute('parent-route', {path: 'child-route',component: () => import('@/views/ChildView.vue')
})// 删除路由
router.removeRoute('route-name')

路由模式

Hash 模式

import { createRouter, createWebHashHistory } from 'vue-router'const router = createRouter({history: createWebHashHistory(), // 使用 URL hashroutes
})

History 模式

import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(), // 使用 HTML5 History APIroutes
})

路由导航

useRoute/useRouter.

<script setup>import { useRoute, useRouter } from 'vue-router'const route = useRoute()  // 路由信息console.log(route.query)const router = useRouter()// 路由跳转router.push('/newPage')
</script>

路由导航流程.

  1. 导航被触发
  2. 在失活的组件里调用 beforeRouteLeave 守卫
  3. 调用全局 beforeEach 前置守卫
  4. 重用的组件调用 beforeRouteUpdate 守卫(2.2+)
  5. 路由配置调用 beforeEnter
  6. 解析异步路由组件
  7. 在被激活的组件里调用 beforeRouteEnter 守卫
  8. 调用全局的 beforeResolve 守卫(2.5+)
  9. 导航被确认
  10. 调用全局的 afterEach
  11. 触发 DOM 更新
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入

编程式导航

组合式API

<script setup lang="ts">
import { useRouter } from 'vue-router';const router = useRouter();const handleManage = () => {router.push('/home/manage');
};
</script>

路由传参.

query传参

//页面传参
<script setup lang="ts">
import { useRouter } from 'vue-router';const router = useRouter();const handleManage = () => {router.push({path: '/home/manage',query: {plan: '123', // t: +new Date()},});
};
</script>//页面接参
<script setup lang="ts">
import { useRoute } from 'vue-router';
const route = useRoute();console.log(route.query.plan); //query接参 
</script>

无参跳转.

// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })

带参跳转.

/*** 传值跳转* @param path 路径* @param value 值*/
const routerId = async (path: string, value: number | string) => {await router.push({path: path,query: {id: value,t: +new Date()}})
}

获取跳转过来的参数

import { useRoute } from 'vue-router'const route = useRoute()const state = reactive({id: route.query.id,})

动态路由匹配

//定义路由
{path: '/register/:plan', // 动态字段以冒号开始component: () => import('@/pages/register.vue'),},//页面传参
<script setup lang="ts">
import { useRouter } from 'vue-router';
const router = useRouter();const handleManage = () => {router.push('/register/123');
};
</script>//页面接参
<script setup lang="ts">
import { useRoute } from 'vue-router';
const route = useRoute();console.log(route.params.plan); //params接参
</script>

存储懒加载组件

// 用对象字面量来存储懒加载组件的路径和对应的组件函数
const asyncComponents = {home: () => {return import('@/components/MyHome.vue')},article: () => {return import('@/views/page/article/Index.vue')},column: () => {return import('@/views/page/article/components/column/ArticleColumn.vue')}
}const routes: RouteRecordRaw[] = [{path: '/',name: 'homes',meta: {keepAlive: true},component: asyncComponents.home},

导航守卫

vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。

路由导航守卫

<script setup>import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'// 添加一个导航守卫,在当前组件将要离开时触发。onBeforeRouteLeave((to, from, next) => {next()})// 添加一个导航守卫,在当前组件更新时触发。// 在当前路由改变,但是该组件被复用时调用。onBeforeRouteUpdate((to, from, next) => {next()})
</script>

全局前置守卫.

在路由跳转前触发,可在执行 next 方法前做登录判断,未登陆用户跳转到登录页

const router = new createRouter({})
//to: 即将要进入的目标 用一种标准化的方式
//from: 当前导航正要离开的路由 用一种标准化的方式
router.beforeEach((to, from, next) => {if (to.path === '/login') {//在登录页做清除操作,如清除token等}if (!localStorage.getItem('token') && to.path !== '/login') {// 未登陆且访问的不是登录页,重定向到登录页面return '/login';}...// 必须执行 next 方法来触发路由跳转 next() // 返回 false 以取消导航return false
})// 含有异步操作的方法
router.beforeEach(async (to, from, next) => {const res = await fetch("****");// to: 跳转到哪个路由// from: 从哪个路由跳转过来// next: 跳转函数,可以跳转到具体的 url
});

死循环解决

ue Router warn The “next“ callback was called more than once in one navigation guard

router.beforeEach(async (to, from, next) => {const token = Cookies.get('token');if (to.path === '/login' || to.path === '/') {next();}else {if (token) {next();} else {console.log('pms out');next('/login');}}
})

全局解析守卫

与 beforeEach 类似,也是路由跳转前触发,区别是还需在所有组件内守卫和异步路由组件被解析之后,也就是在组件内 beforeRouteEnter 之后被调用。

router.beforeResolve((to, from, next) => {...// 必须执行 next 方法来触发路由跳转 next() 
})

全局后置钩子

和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身。它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。

router.afterEach((to, from) => {// ...
})

路由独享守卫.

使用场景:部分页面不需要登录,部分页面需要登录才能访问

可在路由配置上直接定义 beforeEnter

const auth = () => {if (!localStorage.getItem("token")) {// 未登陆,重定向到登录页面return "/login";}
};const routes = [...{path: "/home",component: () => import("@/pages/home.vue"),redirect: "/home/user",children: [{path: "/home/user",component: () => import("@/pages/user.vue"),},{path: "/home/manage",component: () => import("@/pages/manage.vue"),beforeEnter: auth, //路由独享守卫},],},
];

组件内的守卫.

使用情景:预防用户在还未保存修改前突然离开。该导航可以通过返回 false 来取消

组件内可直接定义如下路由导航守卫

<script setup lang="ts">
import { onBeforeRouteLeave } from 'vue-router';// 与 beforeRouteLeave 相同,无法访问 `this`
onBeforeRouteLeave((to, from) => {const answer = window.confirm('确定离开吗');// 取消导航并停留在同一页面上if (!answer) return false;
});
</script>

路由元信息

将自定义信息附加到路由上,例如页面标题,是否需要权限,是否开启页面缓存等

使用路由元信息+全局前置守卫实现部分页面不需要登录,部分页面需要登录才能访问

修改router/index.ts

const routes = [...{path: "/home",component: () => import("@/pages/home.vue"),redirect: "/home/user",children: [{path: "/home/user",component: () => import("@/pages/user.vue"),},{path: "/home/manage",component: () => import("@/pages/manage.vue"),meta: {title: "管理页", // 页面标题auth: true, //需要登录权限},},],},
];

修改router/index.ts

router.beforeEach((to, from) => {if (!localStorage.getItem("token") && to.meta.auth) {// 此路由需要授权,请检查是否已登录// 如果没有,则重定向到登录页面return {path: "/login",// 保存我们所在的位置,以便以后再来query: { redirect: to.fullPath },};}
});

router-link 组件默认为a标签,在vue router 3.x中,可通过tag属性更改标签名,event属性更改事件名

在vue router 4.x中,这两个属性已被删除,通过作用域插槽(子组件给父组件传值的插槽)实现自定义导航标签

示例:将导航标签改为div,且需双击触发

active-class

<router-link v-slot="{ href, navigate, isExactActive }" to="/home/user" custom><div :class="{ active: isExactActive }" :href="href" @dblclick="navigate">跳转user</div>
</router-link>
<!-- 字符串 -->
<router-link to="home">Home</router-link><!-- 使用 v-bind 的 JS 表达式 -->
<router-link v-bind:to="'home'">Home</router-link><!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
<router-link :to="'home'">Home</router-link><!-- 同上 -->
<router-link :to="{ path: 'home' }">Home</router-link><!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link><!-- 带查询参数,下面的结果为 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>

设置 replace 属性,点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。

<router-link :to="{ path: '/abc'}" replace></router-link>

设置 append 属性后,则在当前 (相对) 路径前添加其路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b

<router-link :to="{ path: 'relative/path'}" append></router-link>

exact-active-class

配置当链接被精确匹配的时候应该激活的 class。可以通过以下代码来替代。

<p><router-link v-bind:to = "{ path: '/route1'}" exact-active-class = "_active">Router Link 1</router-link><router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
</p>

router.go(n).

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

子路由.

<a-menu-item key="1" @click="Routers('/Admin-index/ArticleTable')">文章列表</a-menu-item>
<router-view></router-view>

路由配置

{path: '/Admin-index',name: 'Admin-index',component: () => import('@/views/admin/index/index.vue'),children: [   // 添加子路由{path: 'ArticleTable',name: 'ArticleTable',component: () => import('@/views/admin/article/ArticleTable.vue'),},]
},

路由守卫及页面权限控制

import router, { asyncRoutes } from '@/router'
import store from '@/store'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
// import getPageTitle from '@/utils/get-page-title'//  to:要去哪个页面
//  from:从哪里来
//  next:它是一个函数。
//     如果直接放行 next()
//  to:要去哪个页面
//  from:从哪里来
//  next:它是一个函数。
//     如果直接放行 next()
//     如果要跳到其它页 next(其它页)
const whiteList = ['/login', '/404']router.beforeEach(async(to, from, next) => {document.title = 'hr人力项目--' + to.meta.title//   console.log(to, '跳转至', from)// document.title = getPageTitle(to.meta.title)NProgress.start() // 开启进度条const token = store.state.user.tokenif (token) {// 已经登陆if (to.path === '/login') {// 如果当前在登录页,那么跳转首页next('/') // next('/') 只要指定地址跳转,就不会经过router.afterEach(),因此需要手动关闭进度条NProgress.done() // 关闭进度条} else {if (!store.getters.userId) {// 即将进入登录页调用获取用户信息的函数 [需满足两个条件,1) 需拥有token   2)并未在登录页上  ]const menuList = await store.dispatch('user/getUserInfo')console.log(menuList, 'menuListdsadasdsdsa')console.log(asyncRoutes, 'asyncRoutes')const filterRoutes = asyncRoutes.filter(route => {const routeName = route.children[0]console.log(route.children[0], 'route.children[0].name')return menuList.includes(routeName)})filterRoutes.push({ path: '*', redirect: '/404', hidden: true })// console.log(filterRoutes, 'filterRoutesfilterRoutes')router.addRoutes(filterRoutes)store.commit('menus/setMenuList', filterRoutes)// next({ ...to, replace: true })next(to.path)// 重新加载页面} else {next()}// 如果没有在登录页,那么放行,}} else {// 没有登录if (whiteList.includes(to.path)) {// 如果此时在白名单页面上,那么放行next()} else {// 如果此时不在白名单页面上,那么跳转至登录页next('/login')NProgress.done() // 关闭进度条}}
})
// 页面跳转之后执行钩子函数afterEach()
router.afterEach(() => {NProgress.done() // 关闭进度条
})

常见问题与解决方案

处理重复导航错误

// 封装一个安全的导航函数
const safePush = (path: string) => {if (route.path !== path) {router.push(path)}
}// 或者在全局错误处理中捕获
router.onError((error) => {if (error.message.includes('Avoided redundant navigation')) {// 忽略重复导航错误} else {// 处理其他错误console.error('路由错误:', error)}
})

处理未知路由

// 添加一个捕获所有路由的规则
const routes: Array<RouteRecordRaw> = [// ...其他路由{path: '/:pathMatch(.*)*',name: 'NotFound',component: () => import('@/views/NotFound.vue')}
]

路由对象/属性类型报错

引入 _RouteRecordBase 定义 hidden

import {createRouter,createWebHashHistory,RouteRecordRaw,_RouteRecordBase 
} from 'vue-router'declare module 'vue-router'{interface _RouteRecordBase {hidden?: boolean | string | number}
}const routes: Array<RouteRecordRaw> = [{path: '/',redirect: '/login',},{path: '/login',name:'login',hidden: false,component: () => import('@/views/login.vue'), // 懒加载组件}
]

-----vue3 TypeError: parentComponent.ctx.deactivate is not a function

只要为component动态组件添加一个唯一属性key即可

<component :is="Component" :key="route.name" v-if="route.meta.isKeepAlive"></component>

router 文件中,使用 pinia 报错

Vue 3​ 中,无论 main.js​ 里的 app.use(pinia)​ 写在 app.use(router)​ 前面还是后面,vue-router​,总是先初始化,所以会出现 pinia​ 使用报错。所以我们在使用 pinia​ 时需要在 router.beforeEach 函数中进行仓库初始化。

// router/index.ts
import { useMenuStore } from "@/store/menu";
// 写在这里会报错
const menuStore = useMenuStore();router.beforeEach(async (to, from, next) => {// ***
});// 正常获取
router.beforeEach(async (to, from, next) => {// 不报错const menuStore = useMenuStore();// ***
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/934649.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 年车床生产厂家最新推荐排行榜:涵盖数控 / 卧式 / 斜床身 / 重型等多类型设备,助力企业精准选购优质车床品牌

随着制造业转型升级加速,汽车摩托车、工程机械、军工等关键行业对车床设备的精度、效率及个性化定制需求日益严苛,市场对高品质车床的采购需求持续攀升。然而,当前车床行业品牌众多,部分厂家存在技术研发薄弱、产品…

2025 最新球墨铸铁管件厂商推荐排行榜权威发布,市政 / 给排水 / 消防用管件优选品牌深度解析

在市政水利、建筑给排水、消防工程等核心领域,球墨铸铁管件的质量直接决定管网系统的安全与寿命。当前市场中,部分企业因工艺落后、检测缺失导致产品抗腐性差、寿命缩水,不仅推高工程维护成本,更埋下安全隐患。同时…

2025 年加工中心厂商最新推荐排行榜权威发布,涵盖立式 / 卧式 / 龙门 / 四轴 / 五轴等机型,助力采购方精准筛选实力厂商

当前加工中心市场竞争激烈,制造商数量繁杂且产品质量、技术水平差异显著,采购方在选择时常常陷入困境。汽车摩托车、工程机械、军工等行业对加工设备的个性化、高精度、高可靠性需求日益提升,但部分厂商存在技术研发…

CH585在MACOS系统中协商BLE连接间隔至7.5ms

首先,部分MAC OS其实是支持分配连接间隔到7.5ms的,并不是所有都支持,不支持的基本都是最低15ms; 例程改写: 1、广播包设备类型修改,必须为鼠标类型 2、BLE初始化中加入声明,// 强制连接参数更新的允许范围,如…

2025 年磨床厂家最新推荐排行榜:平面磨床 / 外圆磨床 / 数控磨床等优质设备品牌深度解析与核心竞争力测评

当前磨床市场呈现出产品种类繁杂、质量差距悬殊的态势,众多企业在选购磨床时屡屡陷入困境。一方面,部分厂家缺乏规范的生产标准与质量管控机制,产出的磨床在精度稳定性、耐用性上难以达标,无法满足汽车制造、军工生…

基于MATLAB的粒子群算法(PSO)优化libsvm参数完整实现

一、优化原理与流程 1. 优化目标参数空间:SVM关键参数为惩罚系数C和RBF核参数gamma 目标函数:最大化交叉验证准确率(分类)或最小化均方误差(回归)2. PSO算法流程 graph TD A[初始化粒子群] --> B{适应度评估}…

FastCopy复制软件绿色版下载!一款快速复制软件!方便实用

软件介绍 小伙伴要拷贝数据,说要把整个硬盘的数据拷贝到另外的一个硬盘,数据有120G左右。用直接系统复制粘贴的方法进行拷贝,那120G的硬盘,要拷到猴年马月了,所以我推荐给他使用今天的这款软件。 这款软件叫FastC…

python实现提取iso中的文件(支持多平台)

#! /bin/python3 import os import shutil from glob import glob from tempfile import TemporaryDirectory import subprocess as spdef cp_with_level(list_src, folder_target, folder_src_parent):""&q…

2025 年最新推荐球墨铸铁管厂家排行榜:涵盖自来水 / 污水 / 消防等多场景适用优质品牌权威推荐

在市政水利、供水排污、消防输水等工程领域,球墨铸铁管的质量直接决定项目稳定性与使用寿命。当前市场上,部分产品存在强度不足、防腐性能差等问题,导致后期维护成本激增,还可能威胁用水安全与工程安全。同时,品牌…

CopyOnWriteArrayList 的故事--一起看看java原生的读写分离

CopyOnWriteArrayList 是JUC中提供的,为了实现高并发的而提供的list容器之一。对于大部分的业务场景,都是读多写少,并发度也基本卡在了读的位置。通常支持并发的容器在解决并发时,采用是:(1)数据分割,每个线程…

OSI模型-笔记

OSI模型 网络工程师必背 OSI(Open System Interconnection Reference Model) 基本概念 用范围形容网络局域网:LAN 广域网:WAN以太网:一个网络的封装协议,不是一种类型或范围 局域网当中使用的是以太网协议(IEEE…

痞子衡嵌入式:如果i.MXRT1xxx在Hab关闭时出现偶发性启动失败,请先检查JTAG电路

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT1xxx在Hab关闭时出现偶发性启动失败原因分析。最近有一个 RT1064 客户(无人机产品)遇到了一个奇怪的启动失败问题,客户应用程序设计里需要…

如何使用notepad++查看二进制bin文件

如何使用notepad++查看二进制bin文件 菜单栏——插件——插件管理——找到HEX-Editor——安装,等待重启——用notepad++打开二进制bin文件(显示乱码)——插件——HEX-Editor——View in HEX——成功另外,下图红色圈内…

2025 电缆绝缘材料生产厂家最新推荐榜单:品牌技术实力解析,爱普等企业领跑行业

随着电力、风电、轨道交通等领域的高速发展,电缆绝缘材料作为保障系统安全的核心部件,其性能与质量直接决定设备运行稳定性。当前市场品牌繁杂,部分产品在耐温性、绝缘强度等关键指标上不达标,且风电、矿用等特殊场…

SAP BP主数据维护BAPI CVI_EI_INBOUND_MAIN(转)

SAP BP主数据维护BAPI CVI_EI_INBOUND_MAIN_sap bp bapi-CSDN博客近期有创建BP供应商主数据的需求,想起上次写这个批导还是2018年,当时的我面对这个BAPI还是抗拒的,因为算是相对来说比较复杂的一类BAPI了,当时网上…

2025 年最新外呼系统机构最新推荐排行榜:深度解析技术实力、服务体系及行业适配方案电话营销外呼系统/智能外呼系统/外呼系统电销卡/外呼系统平台搭建推荐

在数字化转型全面深化的 2025 年,外呼系统已成为企业打通客户沟通链路、提升业务拓展效率的核心工具。然而当前市场中,外呼系统厂商资质良莠不齐,部分厂商缺乏合规资质、技术架构落后导致通话中断率高,或售后服务响…

运放速度揭秘:带宽与压摆率的关键对决

运放速度揭秘:带宽与压摆率的关键对决本文探讨了放大器带宽与速度的概念区别,分析了小信号和大信号带宽的特性及其影响因素。小信号带宽由RC时间常数决定,反映电路的线性响应;大信号带宽则受限于压摆率,影响输出波…

详细介绍:深入解析 List 容器组件:构建高效、可交互的列表解决方案

详细介绍:深入解析 List 容器组件:构建高效、可交互的列表解决方案pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &qu…

CF848C Goodbye Souvenir 题解(CDQ分治)

考虑到可以将每个数最后一次出现与第一次出现的位置之差拆成若干个相邻位置之差: \[last_i - first_i = \sum i-pre_i \]且每次修改一个点,对 \(pre\) 的影响是 \(O(1)\) 的,所以我们可以将所求的答案转为一个(带权…

[Python] python3 使用虚拟环境

[Python] python3 使用虚拟环境$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");因为Ubuntu不让直接使用pip下载软件,防止影响本机环境,因此需要使用虚拟环…