VueRouter使用详解(5000字通关大全)

Vue Router是一个官方的路由管理器,它可以让我们在Vue应用中实现单页面应用(SPA)的效果,即通过改变URL而不刷新页面来显示不同的内容。Vue Router可以让我们定义多个路由,每个路由对应一个组件,当URL匹配到某个路由时,就会渲染对应的组件。Vue Router还提供了很多高级功能,如嵌套路由、动态路由、命名路由、导航守卫、路由元信息等,让我们可以更灵活地控制路由的行为和状态。

在本文中,我们将介绍Vue Router的基本使用方法,以及一些常用的API和技巧。我们假设你已经有了一些Vue的基础知识,如果不熟悉Vue,请先阅读官方文档。本文使用的Vue Router版本是4.x,这是目前最新的版本,它支持Vue 3.x,并且有一些重要的变化和改进。如果你还在使用旧版本,请参考旧版文档,做好兼容处理。

公众号:Code程序人生,个人网站:https://creatorblog.cn

安装和引入

要使用Vue Router,首先需要安装它。你可以通过npmyarn来安装:

# npm
npm install vue-router# yarn
yarn add vue-router

然后,在你的入口文件(通常是main.js)中引入并创建一个路由实例:

import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'// 定义路由配置,每个路由映射一个组件
const routes = [{ path: '/', component: Home },{ path: '/about', component: About },// ...其他路由
]// 创建一个路由实例,使用history模式
const router = createRouter({history: createWebHistory(),routes, // 等价于routes: routes
})// 创建一个Vue应用实例,并挂载到#app元素上
const app = createApp(App)// 将路由实例注入到应用实例中
app.use(router)// 挂载应用
app.mount('#app')

这里有几点需要注意:

  • Vue Router 4.x使用了函数式的API来创建路由实例,而不是像3.x那样使用new VueRouter()构造函数。这样可以避免全局污染和依赖注入的问题。
  • Vue Router 4.x支持三种模式:historyhashmemory。其中history模式是推荐的模式,它使用HTML5 History API来实现无刷新的URL切换。要使用history模式,需要调用createWebHistory()函数来创建一个history对象,并传递给createRouter()函数。如果你想使用hash模式或memory模式,请分别调用createWebHashHistory()createWebMemoryHistory()函数。
  • 路由配置是一个数组,每个元素是一个对象,表示一个路由。每个路由对象至少需要有两个属性:pathcomponentpath是一个字符串,表示URL路径;component是一个组件,表示要渲染的内容。你可以在routes数组中定义任意多个路由对象。
  • 要将路由实例注入到应用实例中,需要调用app.use(router)方法。这样就可以在应用中使用路由相关的功能了。

使用router-link和router-view

有了路由实例和配置之后,我们就可以在应用中使用router-linkrouter-view两个组件了。router-link是一个特殊的组件,它会渲染成一个a标签,并且可以自动添加或移除active类名来表示当前激活的路由。router-link接受一个to属性,表示要跳转的目标路径。例如:

<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>

这会渲染成:

<a href="/" class="router-link-active">Home</a>
<a href="/about">About</a>

URL变化时,router-link会自动更新active类名,以及对应的样式。你可以通过active-class属性来自定义active类名,或者通过exact属性来控制是否需要完全匹配路径。

router-view是另一个特殊的组件,它会根据当前匹配的路由来渲染对应的组件。你可以把它放在任何地方,通常是放在App组件的模板中,作为一个占位符。例如:

<template><div id="app"><h1>Vue Router Demo</h1><nav><router-link to="/">Home</router-link><router-link to="/about">About</router-link></nav><!-- 这里会渲染匹配到的组件 --><router-view></router-view></div>
</template>

URL变化时,router-view会自动更新渲染的组件,以及对应的生命周期钩子。你可以通过name属性来给router-view命名,以便在嵌套路由中使用。

使用动态路由和命名路由

有时候,我们需要根据URL中的参数来渲染不同的组件,例如用户的个人主页或者文章的详情页。这时候,我们可以使用动态路由来实现。动态路由是指在path中使用冒号(:)来表示一个参数,例如:

const routes = [// ...其他路由// 动态路由,匹配/user/任意值{ path: '/user/:id', component: User },// 动态路由,匹配/post/任意值{ path: '/post/:slug', component: Post },
]

这样,当URL/user/123/post/hello-world时,就会匹配到对应的路由,并渲染UserPost组件。在组件中,我们可以通过$route.params对象来获取动态路由参数的值,例如:

<template><div class="user"><h2>User {{ $route.params.id }}</h2></div>
</template>

或者:

<template><div class="post"><h2>Post {{ $route.params.slug }}</h2></div>
</template>

当然,我们也可以给动态路由参数添加一些限制,例如正则表达式。这样可以避免匹配到不合法的值。例如:

const routes = [// ...其他路由// 动态路由,只匹配/user/数字{ path: '/user/:id(\\d+)', component: User },
]

这样,当URL/user/abc时,就不会匹配到该路由了。

除了使用path来定义路由,我们还可以使用name来给路由命名。命名路由可以让我们在跳转或链接时更方便地引用路由,而不用担心path的变化。例如:

const routes = [// ...其他路由// 命名路由{ path: '/user/:id', name: 'user', component: User },
]

这样,在router-link中,我们就可以使用name属性来指定目标路由,并且通过params属性来传递动态路由参数。例如:

<router-link :to="{ name: 'user', params: { id: 123 }}">User 123</router-link>

这会渲染成:

<a href="/user/123">User 123</a>

同样,在编程式导航中,我们也可以使用nameparams来跳转到目标路由。例如:

// 在组件中
this.$router.push({ name: ‘user’, params: { id: 456 }})// 这会跳转到 /user/456

使用命名路由的好处是,我们可以在任何地方修改路由的path,而不用担心影响到其他地方的引用。只要保持路由的name不变,就可以保证路由的正确性。

使用嵌套路由和命名视图

有时候,我们需要在一个页面中显示多个组件,或者在一个组件中嵌套另一个组件。这时候,我们可以使用嵌套路由和命名视图来实现。嵌套路由是指在一个路由对象中使用children属性来定义子路由,例如:

const routes = [// ...其他路由// 嵌套路由{path: '/user/:id',component: User,children: [// 当URL为/user/:id/profile时,渲染UserProfile组件{ path: 'profile', component: UserProfile },// 当URL为/user/:id/posts时,渲染UserPosts组件{ path: 'posts', component: UserPosts },]}
]

这样,当URL/user/123/profile/user/123/posts时,就会匹配到对应的子路由,并渲染User组件和UserProfileUserPosts组件。注意,子路由的path不需要加斜杠(/),因为它是相对于父路由的path来解析的。

要在父组件中渲染子组件,我们需要在父组件的模板中使用router-view作为占位符。例如:

<template><div class="user"><h2>User {{ $route.params.id }}</h2><!-- 这里会渲染子组件 --><router-view></router-view></div>
</template>

如果我们想要同时显示多个组件,而不是嵌套显示,我们可以使用命名视图来实现。命名视图是指给router-view添加一个name属性来区分不同的视图,并且在路由配置中使用components属性来指定多个组件。例如:

const routes = [// ...其他路由// 命名视图{path: '/dashboard',components: {default: Dashboard,sidebar: Sidebar,header: Header,}}
]

这样,当URL/dashboard时,就会匹配到该路由,并渲染DashboardSidebarHeader三个组件。注意,components是一个对象,它的键是router-viewname属性,它的值是对应的组件。如果没有指定name属性,默认为default

要在应用中使用命名视图,我们需要在模板中使用多个router-view并给它们添加name属性。例如:

<template><div id="app"><!-- 这里会渲染Header组件 --><router-view name="header"></router-view><div class="main"><!-- 这里会渲染Sidebar组件 --><router-view name="sidebar"></router-view><!-- 这里会渲染Dashboard组件 --><router-view></router-view></div></div>
</template>

当然,我们也可以将嵌套路由和命名视图结合起来使用,以实现更复杂的布局和导航。例如:

const routes = [// ...其他路由// 嵌套路由和命名视图{path: '/user/:id',component: User,children: [{path: 'profile',components: {default: UserProfile,sidebar: UserSidebar,}},{path: 'posts',components: {default: UserPosts,sidebar: UserSidebar,}},]}
]

这样,当URL/user/123/profile/user/123/posts时,就会匹配到对应的子路由,并渲染UserUserProfileUserPostsUserSidebar三个组件。注意,子路由的components也是一个对象,它的键是router-viewname属性,它的值是对应的组件。

要在父组件中使用命名视图,我们也需要在模板中使用多个router-view并给它们添加name属性。例如:

<template><div class="user"><h2>User {{ $route.params.id }}</h2><!-- 这里会渲染UserSidebar组件 --><router-view name="sidebar"></router-view><!-- 这里会渲染UserProfile或UserPosts组件 --><router-view></router-view></div>
</template>

使用导航守卫和路由元信息

有时候,我们需要在路由跳转时进行一些控制或处理,例如验证用户权限、显示加载提示、记录访问日志等。这时候,我们可以使用导航守卫来实现。导航守卫是一些函数,它们会在路由跳转前后被调用,让我们可以拦截或修改路由的行为。Vue Router提供了三种类型的导航守卫:全局守卫、路由独享守卫和组件内守卫。

全局守卫是指在路由实例上注册的守卫,它们会在任何路由跳转时被调用。全局守卫有三种:beforeEachbeforeResolveafterEachbeforeEach守卫会在路由跳转前被调用,我们可以在这里进行一些权限验证或数据预处理。例如:

// 在创建路由实例之后
router.beforeEach((to, from, next) => {// to是目标路由对象,from是来源路由对象,next是一个函数// 检查目标路由是否需要登录if (to.meta.requiresAuth) {// 检查用户是否已经登录if (store.state.user) {// 已经登录,放行next()} else {// 没有登录,跳转到登录页next({ path: '/login' })}} else {// 不需要登录,放行next()}
})

这里,我们使用了to.meta属性来判断目标路由是否需要登录。meta属性是一个自定义的对象,我们可以在路由配置中给每个路由添加一些元信息,例如:

const routes = [// ...其他路由// 需要登录的路由{ path: '/profile', component: Profile, meta: { requiresAuth: true }},// 不需要登录的路由{ path: '/login', component: Login },
]

这样,在beforeEach守卫中,我们就可以根据meta属性来进行不同的处理。注意,在beforeEach守卫中,我们必须调用next函数来决定是否放行或重定向。next函数可以接受一个参数,表示要跳转的目标路径或路由对象。如果不传递参数,则表示放行当前的跳转。

beforeResolve守卫和beforeEach守卫类似,但是会在所有异步组件被解析后才被调用。我们可以在这里进行一些最后的检查或处理。例如:

// 在创建路由实例之后
router.beforeResolve((to, from, next) => {// to是目标路由对象,from是来源路由对象,next是一个函数// 显示加载提示store.commit('showLoading')// 放行next()
})

afterEach守卫会在路由跳转后被调用,我们可以在这里进行一些收尾工作或清理工作。例如:

// 在创建路由实例之后
router.afterEach((to, from) => {// to是目标路由对象,from是来源路由对象// 隐藏加载提示store.commit(‘hideLoading’);// 记录访问日志store.dispatch(‘logVisit’, { to, from }) });

路由独享守卫是指在路由配置中定义的守卫,它们只会在匹配到该路由时被调用。路由独享守卫有两种:beforeEnterbeforeLeavebeforeEnter守卫会在进入该路由前被调用,我们可以在这里进行一些特定的处理或拦截。例如:

const routes = [// ...其他路由// 路由独享守卫{path: '/admin',component: Admin,beforeEnter: (to, from, next) => {// to是目标路由对象,from是来源路由对象,next是一个函数// 检查用户是否是管理员if (store.state.user.role === 'admin') {// 是管理员,放行next()} else {// 不是管理员,跳转到首页next({ path: '/' })}}}
]

这里,我们使用了beforeEnter守卫来判断用户是否有权限访问/admin路由。注意,在beforeEnter守卫中,我们也必须调用next函数来决定是否放行或重定向。

beforeLeave守卫会在离开该路由前被调用,我们可以在这里进行一些确认或保存工作。例如:

const routes = [// ...其他路由// 路由独享守卫{path: '/edit/:id',component: Edit,beforeLeave: (to, from, next) => {// to是目标路由对象,from是来源路由对象,next是一个函数// 检查编辑内容是否已经保存if (this.$refs.editor.isSaved()) {// 已经保存,放行next()} else {// 没有保存,弹出确认框if (window.confirm('您的编辑内容尚未保存,确定要离开吗?')) {// 确定离开,放行next()} else {// 取消离开,中断跳转next(false)}}}}
]

这里,我们使用了beforeLeave守卫来提示用户是否要保存编辑内容。注意,在beforeLeave守卫中,我们也必须调用next函数来决定是否放行或中断。如果传递false作为参数,则表示中断当前的跳转。

组件内守卫是指在组件选项中定义的守卫,它们只会在该组件被渲染时被调用。组件内守卫有三种:beforeRouteEnterbeforeRouteUpdatebeforeRouteLeavebeforeRouteEnter守卫会在渲染该组件前被调用,我们可以在这里进行一些数据获取或处理。例如:

<template><div class="post"><h2>{{ post.title }}</h2><p>{{ post.content }}</p></div>
</template><script>
export default {data() {return {post: null,}},beforeRouteEnter(to, from, next) {// to是目标路由对象,from是来源路由对象,next是一个函数// 获取文章数据fetch(`/api/posts/${to.params.id}`).then(res => res.json()).then(data => {// 将数据传递给组件实例next(vm => vm.post = data)})},
}
</script>

这里,我们使用了beforeRouteEnter守卫来获取文章数据,并将其传递给组件实例。注意,在beforeRouteEnter守卫中,我们无法访问this,因为组件实例还没有被创建。所以我们需要通过next函数的回调来访问组件实例。

beforeRouteUpdate守卫会在当前路由发生变化时被调用,但是该组件被复用时才会触发。我们可以在这里进行一些数据更新或处理。例如:

<template><div class="post"><h2>{{ post.title }}</h2><p>{{ post.content }}</p></div>
</template><script>
export default {data() {return {post: null,}},beforeRouteEnter(to, from, next) {// ...省略},beforeRouteUpdate(to, from, next) {// to是目标路由对象,from是来源路由对象,next是一个函数// 获取新的文章数据fetch(`/api/posts/${to.params.id}`).then(res => res.json()).then(data => {// 更新组件实例的数据this.post = data// 放行next()})},
}
</script>

这里,我们使用了beforeRouteUpdate守卫来获取新的文章数据,并更新组件实例的数据。注意,在beforeRouteUpdate守卫中,我们可以访问this,因为组件实例已经被创建并复用。同样,在beforeRouteUpdate守卫中,我们也必须调用next函数来决定是否放行或重定向。

beforeRouteLeave守卫会在离开该组件时被调用,我们可以在这里进行一些确认或保存工作。例如:

<template><div class="edit"><h2>编辑文章</h2><textarea ref="editor">{{ post.content }}</textarea><button @click="save">保存</button></div>
</template><script>
export default {data() {return {post: null,saved: false,}},beforeRouteEnter(to, from, next) {// ...省略},beforeRouteLeave(to, from, next) {// to是目标路由对象,from是来源路由对象,next是一个函数// 检查编辑内容是否已经保存if (this.saved) {// 已经保存,放行next()} else {// 没有保存,弹出确认框if (window.confirm('您的编辑内容尚未保存,确定要离开吗?')) {// 确定离开,放行next()} else {// 取消离开,中断跳转next(false)}}},methods: {save() {// ...省略this.saved = true}}
}
</script>

这里,我们使用了beforeRouteLeave守卫来提示用户是否要保存编辑内容。注意,在beforeRouteLeave守卫中,我们也必须调用next函数来决定是否放行或中断。

使用的注意事项

在使用Vue Router时,还有一些注意事项需要了解:

  • 如果你想使用HTML5 History模式,你需要配置你的服务器来支持该模式。具体来说,就是让服务器对于所有的请求都返回index.html文件,以便让Vue Router接管路由的处理。你可以参考官方文档中的相关说明来配置你的服务器。
  • 如果你想使用hash模式,你需要注意URL中的hash值可能会影响到锚点的功能。如果你想使用锚点来定位到页面中的某个元素,你需要在路由配置中使用scrollBehavior属性来自定义滚动行为。你可以参考官方文档中的相关示例来实现你的需求。
  • 如果你想使用memory模式,你需要注意该模式不会改变URL,也不会记录历史记录。这意味着用户无法通过浏览器的前进或后退按钮来导航路由,也无法通过刷新页面来保持当前状态。该模式适合一些不需要URL和历史记录的场景,例如移动端应用或小程序。
  • 如果你想在组件中访问路由相关的信息或功能,你可以通过this.$routethis.$router两个属性来实现。
  • this.$route是一个只读的对象,它包含了当前激活的路由的信息,例如pathparamsquerymeta等。你可以通过this.$route来获取或监视路由的变化,以便进行一些响应式的操作。
<template><div class="user"><h2>User {{ $route.params.id }}</h2><!-- 根据路由的query参数来显示不同的内容 --><div v-if="$route.query.active"><p>This user is active.</p></div><div v-else><p>This user is inactive.</p></div></div>
</template>
  • this.$router是一个可读写的对象,它是路由实例的引用,它包含了一些方法和属性,让我们可以在组件中控制路由的跳转或状态。
<template><div class="post"><h2>{{ post.title }}</h2><p>{{ post.content }}</p><!-- 使用router-link来跳转到上一篇或下一篇文章 --><nav><router-link :to="{ name: 'post', params: { id: prevId }}">Prev</router-link><router-link :to="{ name: 'post', params: { id: nextId }}">Next</router-link></nav><!-- 使用router.go来后退或前进 --><button @click="$router.go(-1)">Back</button><button @click="$router.go(1)">Forward</button></div>
</template><script>
export default {data() {return {post: null,prevId: null,nextId: null,}},beforeRouteEnter(to, from, next) {// ...省略},beforeRouteUpdate(to, from, next) {// ...省略},methods: {// 使用router.push来跳转到编辑页edit() {this.$router.push({ name: 'edit', params: { id: this.post.id }})}}
}
</script>

总结

以上就是Vue Router的基本使用方法,以及一些常用的API和技巧。Vue Router是一个非常强大和灵活的路由管理器,它可以让我们在Vue应用中实现各种复杂和高效的导航功能。

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

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

相关文章

RT-Thread 线程间同步

线程间同步 在多线程实时系统中&#xff0c;一项工作的完成往往可以通过多个线程协调的方式共同来完成&#xff0c;那么多个线程之间如何 “默契” 协作才能使这项工作无差错执行&#xff1f;下面举个例子说明。 例如一项工作中的两个线程&#xff1a;一个线程从传感器中接收…

菜鸟教程《Python 3 教程》笔记(12):推导式

菜鸟教程《Python 3 教程》笔记&#xff08;12&#xff09; 12 推导式12.1 列表推导式12.2 字典推导式12.3 集合推导式12.4 元组推导式&#xff08;生成器表达式&#xff09; 笔记带有个人侧重点&#xff0c;不追求面面俱到。 12 推导式 出处&#xff1a; 菜鸟教程 - Python3 …

nodejs中如何使用Redis

Redis介绍&#xff1a; Redis 是一个开源的内存数据结构存储器&#xff0c;一般可以用于数据库、缓存、消息代理等&#xff0c;我们常在项目中用redis解决高并发、高可用、高可扩展、大数据存储等问题&#xff1b; 它本质上是一个NoSql&#xff08;非关系型数据库&#xff09;…

Linux开机启动Tomcat

需求背景 Linux重启后要手动执行"startup.sh"启动Tomcat&#xff0c;比较麻烦&#xff0c;想要Linux开机启动Tomcat。 开机启动 #---------------------------------------------------------- sudo tee /usr/bin/tomcat.sh <<-EOF #! /bin/bash nohup /opt/to…

Compose学习 - remember、mutableStateOf的使用

一、需求 在显示界面中&#xff0c;数据变动&#xff0c;界面刷新是非常常见的操作&#xff0c;所以使用compose该如何实现呢&#xff1f; 二、remember、mutableStateOf的使用 我们可以借助标题的两个概念 remember、mutableStateOf来完成。这里先不写定义&#xff0c;定义…

C#基础知识点记录

目录 课程一、C#基础1.C#编译环境、基础语法2.Winform-后续未学完 课程二、Timothy C#底层讲解一、类成员0常量1字段2属性3索引器5方法5.1值参数&#xff08;创建副本&#xff0c;方法内对值的操作&#xff0c;不会影响原来变量的值&#xff09;5.2引用参数&#xff08;传的是地…

Unix System V BSD POSIX 究竟是什么?

学习Linux系统,很多同学对这些单词概念很模糊、一脸懵逼! 黄老师觉得,了解了历史,才会真正明白这些单词的含义,坐稳、黄老师发车了!!! 首先介绍一下什么是Unix? UNIX(非复用信息和计算机服务,英语:Uniplexed Information and Computing Service,UnICS)取“UNI…

ELK日志收集系统(四十九)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 二、组件 1. elasticsearch 2. logstash 2.1 工作过程 2.2 INPUT 2.3 FILETER 2.4 OUTPUTS 3. kibana 三、架构类型 3.1 ELK 3.2 ELKK 3.3 ELFK 3.5 EF…

HTML 与 CSS 有什么区别?

HTML&#xff08;超文本标记语言&#xff09;和 CSS&#xff08;层叠样式表&#xff09;是构建网页的两个核心技术。HTML负责定义网页的结构和内容&#xff0c;而CSS则用于控制网页的样式和布局。虽然它们在构建网页时密切相关&#xff0c;但它们在功能和用途上有明显的区别。 …

go语言-协程

mOS结构体 每一种操作系统不同的线程信息 g给g0栈给g0协程内存中分配的地址&#xff0c;记录函数跳转信息&#xff0c; 单线程循环 0.x版本 1.0版本 多线程循环 操作系统并不知道Goroutine的存在 操作系统线程执行一个调度循环&#xff0c;顺序执行Goroutine 调度循环非常…

【LeetCode周赛】LeetCode第359场周赛

LeetCode第359场周赛 判别首字母缩略词k-avoiding 数组的最小总和销售利润最大化找出最长等值子数组 判别首字母缩略词 给你一个字符串数组 words 和一个字符串 s &#xff0c;请你判断 s 是不是 words 的 首字母缩略词 。 如果可以按顺序串联 words 中每个字符串的第一个字符…

css-grammar

语法格式 选择器 {属性名称 : 属性值; 属性名称 : 属性值;...}语法特点: CSS声明总是以键值对(key\value)形式存在。CSS声明总是以分号(;)结束。声明组以大括号({})括起来。为了让CSS可读性更强&#xff0c;每行只描述一个属性。 CSS 注释 注释是用来解释你的代码&#xff…

vue Cesium接入在线地图

Cesium接入在线地图只需在创建时将imageryProvider属性换为在线地图的地址即可。 目录 天地图 OSM地图 ArcGIS 地图 谷歌影像地图 天地图 //矢量服务let imageryProvider new Cesium.WebMapTileServiceImageryProvider({url: "http://t0.tianditu.com/vec_w/wmts?s…

大数据组件-Flume集群环境的启动与验证

&#x1f947;&#x1f947;【大数据学习记录篇】-持续更新中~&#x1f947;&#x1f947; 个人主页&#xff1a;beixi 本文章收录于专栏&#xff08;点击传送&#xff09;&#xff1a;【大数据学习】 &#x1f493;&#x1f493;持续更新中&#xff0c;感谢各位前辈朋友们支持…

【python爬虫】中央气象局预报—静态网页图像爬取练习

静态网页爬取练习 中央气象局预报简介前期准备步骤Python爬取每日预报结果—以降水为例 中央气象局预报简介 中央气象台是中国气象局&#xff08;中央气象台&#xff09;发布的七天降水预报页面。这个页面提供了未来一周内各地区的降水预报情况&#xff0c;帮助人们了解即将到来…

深入学习 cnf问题 和 SAT 算法

前言 SAT问题是一个重要的计算机科学和人工智能问题&#xff0c;它涉及在给定的布尔变量集合和子句集合下&#xff0c;确定是否存在一种变量赋值使得整个合取范式成为真。这个问题在实际应用中有广泛的用途&#xff0c;包括硬件设计、安全协议验证等。 怎么看待 cnf cnf 文件本…

如何高效地设计测试用例并评审

编写出好的测试用例是每一个测试工程师的职责&#xff0c;但在实际工作中大家写的测试用例往往需要不断地修改才能使用&#xff0c;这不仅浪费了时间&#xff0c;还容易让测试工程师产生自我否定的情绪&#xff0c;甚至在团队中产生各种矛盾。 那如何高效地设计测试用例呢&…

【pyqt5界面化工具开发-14】初始牛刀-登录工具

目录 0x00 前言&#xff1a; 一、准备好ui的加载 二、获取对应的触发事件 三、触发事件绑定 三、输入内容的调用 三、完善登录逻辑 0x00 前言&#xff1a; 在逻辑代码的处理添加数据包的请求&#xff0c;返回数据包的判断&#xff0c;就可以完整实现登录检测的一个界面化…

Android.mk开发模板

今天简单写了一个 Android.mk 的示例模板&#xff0c;供初学者参考。 本模板主要给大家示例 Android NDK 开发中的如下几个问题&#xff1a; 如何自动添加需要编译的源文件列表如何添加第三方静态库、动态库的依赖如何构造一个完整的NDK工程框架 假设我们的项目依赖 libmath.…

前后端分离不存在会话,sessionid不一致问题

目录 1.使用拦截器解决跨域的示例&#xff1a; 2.使用redis&#xff0c;不使用session 前后端不分离项目我们可以通过session存储数据&#xff0c;但是前后端分离时不存在会话&#xff0c;每次请求sessionid都会改变&#xff0c;当值我们储存的数据不能取出来。 1.使用拦截器…