【学习vue 3.x】(五)VueRouter路由与Vuex状态管理

在这里插入图片描述

文章目录

  • 章节介绍
    • 本章学习目标
  • 路由的基本搭建与嵌套路由模式
    • vue路由的搭建
    • 嵌套路由模式
  • 动态路由模式与编程式路由模式
    • 动态路由模式
    • 编程式路由
  • 命名路由与命名视图与路由元信息
    • 命名路由
    • 命名视图
    • 路由元信息
  • 路由传递参数的多种方式及应用场景
    • 路由传参
  • 详解route对象与router对象
    • route对象与router对象
  • 路由守卫详解及应用场景
    • 路由守卫分类
    • 完整的导航解析流程
  • Vuex共享状态的基本开发流程
  • Vuex处理异步状态及应用场景
  • Vuex计算属性和辅助函数的使用
    • getters计算属性
    • 辅助函数
  • Vuex-persist对数据进行持久化处理
  • Vuex分割模块及多状态管理
  • 组合式API中使用Router和Vuex注意事项
  • Router_Vuex的任务列表综合案例
  • 搭建 Vite3 + Pinia2 组合模式
    • 总结内容

章节介绍

小伙伴大家好,本章将学习VueRouter路由与Vuex状态管理 - 组织与架构应用。

本章学习目标

本章将学习Vue3中的路由与状态管理,随着前后端分离式开发的兴起,单页面应用开发(即SPA页面)也越来越流行,所以前端路由与共享状态也越来越重要!

路由的基本搭建与嵌套路由模式

在前面的小节中,已经介绍了什么是前端路由以及前端路由所具备的特点。本小节就来对路由进行实际搭建吧。

vue路由的搭建

路由在vue中属于第三方插件,需要下载安装后进行使用。版本说明一下,Vue3搭配的是Vue Router4,目前正常安装的话,就是路由4的版本。如下:

npm install vue-router

安装好后,需要对路由进行配置,并且与Vue进行结合,让路由插件生效。在/src/router/index.js创建配置文件。

在这里插入图片描述

可以通过 createWebHistory()来创建history模式的路由,也可以通过createWebHashHistory()来创建hash模式的路由。那么在浏览器中输入的URL该如何展示对应的组件呢?可以通过这个组件来实现。

除了进行展示外,还可以通过方式进行声明式的路由跳转,代码如下:

<template><div><router-link to="/">首页</router-link> | <router-link to="/about">关于</router-link><router-view></router-view></div>
</template>

嵌套路由模式

往往我们的路由是比较复杂的,需要的层级也比较多,那么就会产生嵌套路由的模式,比如:localhost:8080/about/foolocalhost:8080/about/bar

import Foo from '@/views/Foo.vue'
import Bar from '@/views/Bar.vue'
const routes = [{path: '/about',component: About,children: [{path: 'foo',component: Foo},{path: 'bar',component: Bar}]}
]

可以看到嵌套路由是通过children属性来完成的,那么对于这种嵌套路由写法,我们对应的也要在一级路由对应页面中添加一个,这样才能切换显示二级路由所对应的页面。

动态路由模式与编程式路由模式

动态路由模式

所谓的动态路由其实就是不同的URL可以对应同一个页面,这种动态路由一般URL还是有规律可循的,所以非常适合做类似于详情页的功能。

在这里插入图片描述

// router/index.js,定义动态路由const routes = [{path: 'foo/:id',component: Foo}
]// views/Foo.vue,获取动态路由的id
export default {mounted(){console.log( this.$route.params.id );}
}

编程式路由

前面介绍过如何在页面中对路由进行切换,可以采用声明式写法来完成,但是往往这种方式不够灵活,首先不能更灵活的控制结构和样式,其次不能自动进行路由的跳转,必须点击操作才行。

那么编程式路由就会在JavaScript中通过逻辑的方式进行路由跳转,我们把这种写在JS中进行跳转路由的方式叫做编程式路由,这样方式会更加的灵活。

<template><button @click="handleToBar">编程式路由跳转</button>
</template>
<script>export default {methods: {handleToBar(){this.$router.push('/about/bar');}}}
</script>

可以看到在动态路由中使用到了一个route对象,而在编程式路由中使用了一个router对象,那么这两个比较重要的路由对象,会在后面的小节中给大家进行详细的讲解。

命名路由与命名视图与路由元信息

命名路由

在路由跳转中,除了path 之外,你还可以为任何路由提供 name 的形式进行路由跳转。那么name方式的好处如下:

  • 没有硬编码的 URL
  • params 的自动编码/解码
  • 防止你在 url 中出现打字错误
  • 绕过路径排序(如显示一个)
// router/index.js,定义命名路由
const routes = [{path: '/about/bar',name: 'bar',component: Bar},{path: '/about/foo/:id',name: 'foo',component: Foo}
];
<!-- About.vue,使用命名路由跳转 -->
<template><div><router-link :to="{ name: 'bar' }">bar</router-link><router-link :to="{ name: 'foo', params: {id: 123} }">foo 123</router-link></div>
</template>

name的方式也支持动态路由形式。

命名视图

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,这个时候就非常适合使用命名视图。
在这里插入图片描述

通过components字段配置多个组件,根据不同的router-view去渲染不同的组件。

路由元信息

有时,你可能希望将任意信息附加到路由上,如过渡名称、谁可以访问路由等。这些事情可以通过接收属性对象的meta属性来实现。

const routes = [{path: '/about/bar',name: 'bar',component: Bar,meta: { auth: false }},{path: '/about/foo/:id',name: 'foo',component: Foo,meta: { auth: true }}
];

定义好meta元信息后,可通过route对象去访问meta属性。

<!-- Foo.vue -->
<script>
export default {mounted(){this.$route.meta.auth   // true}
}
</script>

路由传递参数的多种方式及应用场景

路由传参

我们经常要在路由跳转的时候传递一些参数,这些参数可以帮助我们完成后续的一些开发和一些处理。路由的传递参数主要有以下三种方式:

  • query方式(显示) -> $route.query
  • params方式(显示) -> $route.params

两种显示传递数据的差异点主要为,query是携带辅助信息,而params是界面的差异化。

<!-- About.vue -->
<template><div><router-link :to="{ name: 'bar', query: { username: 'xiaobai' } }">bar</router-link><router-link :to="{ name: 'foo', params: { username: 'xiaoqiang' } }">foo</router-link></div>
</template><!-- Bar.vue -->
<script>export default {mounted(){console.log(this.$route.query);}}
</script>
<!-- foo.vue -->
<script>export default {mounted(){console.log(this.$route.params);}}
</script>

前两种都是显示传递数据,那么第三种是隐式传递数据,这种方式并不会把数据暴露出来。

<!-- About.vue -->
<template><div><router-link :to="{ name: 'bar', params: { username: 'xiaoqiang' } }">bar</router-link></div>
</template><!-- Bar.vue -->
<script>export default {mounted(){console.log(this.$route.params);}}
</script>

但是这里需要注意以下,隐式发送过来的数据,只是临时性获取的,一旦刷新页面,隐藏的数据就会消失,所以在使用的时候要额外注意以一下。

详解route对象与router对象

在前面小节中,我们频繁的使用过route对象和router对象,这两个对象在路由中非常的重要,下面我们来详细的学习一下。

route对象与router对象

首先route对象用来获取路由信息,而router对象用来调用路由方法的。具体区别在于,route对象是针对获取操作的,主要是操作当前路由的,而router对象是针对设置操作的,主要是操作整个路由系统对应的功能。

route对象具体功能如下:

  • fullPath
  • hash
  • href
  • matched
  • meta
  • name
  • params
  • path
  • query

主要就是一些路由信息,像常见的动态路由参数,query数据,meta元信息,url路径等等。

router对象具体功能如下:

  • addRoute
  • afterEach
  • back
  • beforeEach
  • beforeResolve
  • currentRoute
  • forward
  • getRoutes
  • go
  • hasRoute
  • push
  • removeRoute

主要就是一些方法,动态改变路由表,路由守卫, 历史记录的前进后退,编程式路由等等。

路由守卫详解及应用场景

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

守卫主要的作用就是在进入到指定路由前做一个拦截,看一下我们是否具备权限,如果有权限就直接进入,如果没权限就跳转到其他页面。

路由守卫分类

一般可以分为三种路由守卫使用的方式:

  • 全局环境的守卫
  • 路由独享的守卫
  • 组件内的守卫

先来看一下如何设置全局的路由守卫,一般在路由配置文件中进行设置。

router.beforeEach((to, from, next)=>{if(to.meta.auth){next('/');}else{next();}
})

其中to表示需要进入到哪个路由,from表示从哪个路由离开的,那么next表示跳转到指定的页面。

有时候我们只是想给某一个指定的路由添加守卫,那么可以选择设置路由独享的守卫方式。

const routes = [{name: 'bar',component: Bar,beforeEnter(to, from, next){if(to.meta.auth){next('/');}else{next();}}}
];

还可以通过在.vue文件中进行路由守卫的设置,代码如下:

<script>export default {name: 'FooView',beforeRouteEnter(to, from, next){if(to.meta.auth){next('/');}else{next();}}}
</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 的回调函数,创建好的组件实例会作为回调函数的参数传入。

Vuex共享状态的基本开发流程

在上一个小节中,我们介绍了什么是Vuex,本小节我们一起来看一下Vuex共享状态的基本开发流程。首先我们来看一下Vuex的经典流程图。
在这里插入图片描述

我们可以看到,基本上就是先准备好一个共享数据state,然后渲染我组件中,通过组件调用dispatch -> actions -> commit -> mutations的方式来进行state修改。

那么这里我们先不考虑dispatch -> actions,因为这两个环节是处理异步程序的,那么我们直接组件去调用commit就可以触发mutations中定义的方法,这样在这个方法中进行state的修改。

首先在/src/store/index.js创建一个状态管理的配置文件,然后在main.js中让vuex于vue进行结合,就像我们路由的使用一样。

//  store/index.js
const store = createStore({state: {count: 0},mutations: {change(state, payload){state.count += payload;}}
});//  main.js
import store from './store'
app.use(store)

下面看一下如何在页面中显示state数据和如何通过commit修改我们的共享数据,代码如下:

<template><div><button @click="change(5)">点击</button>hello home, {{ $store.state.count }}</div>
</template>
<script>export default {name: 'HomeView',methods: {handleClick(){this.$store.commit('change', 5);}}}
</script>

Vuex处理异步状态及应用场景

本小节中将讲解一下Vuex中如何处理异步程序,因为在上一个小节中提到过,mutations中只能处理同步,不能处理异步,所以异步的工作就交给了 actions 来完成。

那么如何触发actions中定义的方法呢,就需要通过dispatch进行触发,具体代码如下:

const store = createStore({state: {count: 0},actions: {change(context, payload){setTimeout(()=>{context.commit('change', payload)}, 1000)}},mutations: {change(state, payload){state.count += payload;}}
});
<script>export default {name: 'HomeView',methods: {handleClick(){this.$store.dispatch('change', 5);}}}
</script>

这样在vue devtools插件中就可以更好的观察到异步数据的变化。那么异步处理的应用场景有哪些呢?异步的获取后端的数据,这样可以利用状态管理来充当MVC架构中的C层,不仅衔接前后端,还能对数据进行共享,可以在切换路由的时候做到减少请求次数,而且状态管理配合本地存储进行数据持久化也是非常的方便。

Vuex计算属性和辅助函数的使用

Vuex中除了提供常见的异步处理和同步处理外,还提供了一些辅助的操作方式,比如:状态管理下的计算属性和简化操作的辅助函数。

getters计算属性

在Vuex中通过定义getters字段来实现计算属性,代码如下:

const store = createStore({state: {count: 0}getters: {doubleCount(state){return state.count * 2;}}
});
<template><div>{{ count }}, {{ doubleCount }}</div>
</template>

当count数据发生改变的手,对应的计算属性doubleCount也会跟着发生改变。

辅助函数

在Vuex中为了让我们使用共享数据或调用方法的时候,更加简单易用,提供了对应的辅助函数,分别为:mapState、mapGetters、mapMutations、mapActions。

<template><div><button @click="change(5)">点击</button>hello home, {{ count }}, {{ doubleCount }}</div>
</template><script>import { mapState, mapGetters, mapActions } from 'vuex';export default {name: 'HomeView',methods: {...mapActions(['change'])},computed: {...mapState(['count']),...mapGetters(['doubleCount'])}}
</script>

辅助函数最大的优点就是可以处理大量共享数据的需求,这样写起来会非常的简便,因为只需要往数组里添加子项即可。

Vuex-persist对数据进行持久化处理

默认情况下Vuex状态管理是不会对数据进行持久化存储的,也就是说当我们刷新浏览器后,共享状态就会被还原。那么我们想要在刷新的时候能够保持成修改后的数据就需要进行持久化存储,比较常见的持久化存储方案就是利用本地存储来完成,不过自己去实现还是比较不方便的,下面我们通过第三方模块来实现其功能。

模块github地址:https://github.com/championswimmer/vuex-persist。根据地址要求的配置操作如下:

// npm install vuex-persistimport VuexPersistence from 'vuex-persist';
const vuexLocal = new VuexPersistence({storage: window.localStorage,reducer: (state) => ({count: state.count})
})const store = createStore({state: {count: 0,msg: 'hello'}plugins: [vuexLocal.plugin]
});

默认情况下,vuex-persist会对所有共享状态进行持久化,那么如果我们只需要对指定的属性进行持久化就需要配置 reducer字段,这个字段可以指定需要持久化的状态。

这样当我们修改了state下的count,那么刷新的时候会不会还原了,并且通过chrome浏览器中Application下的Local Storage进行查看。

Vuex分割模块及多状态管理

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

那么这个时候,所有共享状态的值都在一起,所有的方法也都放在了一起,维护起来非常的不方便。那么Vuex中可利用modules属性来配置模块化的共享状态,那么对于后期维护起来是非常方便的,也利于大型项目的架构。

在/store下创建一个modules文件夹,然后编写一个message.js,代码如下:

const state = {msg: 'hello'
};
const getters = {upperMsg(state){return state.msg.toUpperCase()}
};
const actions = {};
const mutations = {change(state, payload){state.msg = payload;}
};
export default {namespaced: true,state,getters,actions,mutations
}

模块中的选项跟index.js中的选项是一样的,对外提供接口的时候,可以看到一个namespaced字段,这表示当前模块的一个命名空间,主要是为了防止跟其他模块之间产生冲突,在调用的时候需要携带对应的命名空间标识符才行。

再来看一下index.js如何去收集我们的模块,并如何去使用我们的模块。

// store/index.js
import message from '@/store/modules/message'
const store = createStore({modules: {message}
});
<!-- About.vue -->
<template><div><button @click="change('hi')">点击</button>hello about, {{ msg }}, {{ upperMsg }}</div>
</template><script>
import { mapState, mapGetters, mapMutations } from 'vuex';export default {name: 'AboutView',methods: {// handleClick(){//   this.$store.commit('message/change', 'hi');// }...mapMutations('message', ['change'])},computed: {//  msg(){//   return this.$store.message.msg;//  },//  upperMsg(){//   return this.$store.getters['message/upperMsg']//  }...mapState('message', ['msg']),...mapGetters('message', ['upperMsg'])}}
</script>

在辅助函数的情况下,也可以进行很好的调用,辅助函数的第一个参数就是命名空间的名字。

组合式API中使用Router和Vuex注意事项

前面介绍的路由和状态管理都是在选项式API中进行使用的,那么路由和状态管理在组合式API中使用的时候,需要注意哪些问题呢?

主要就是路由会提供两个use函数,分别为:useRoute和useRouter;同理状态管理页提供了一个use函数,useStore来操作的。

先来看一下路由相关use函数的使用情况:

<script setup>
import { useRoute, useRouter } from 'vue-router'
const route = useRoute();
const router = useRouter();
console.log( route.meta );
console.log( router.getRoutes() );
</script>

基本上跟选项式API中的用法是一样的,并没有太大的区别。

再来看一下状态管理相关use函数的使用情况:

<script setup>
import { useStore } from 'vuex'
const store = useStore();
console.log( store.state.count );
console.log( store.state.message.msg );
</script>

得到store对象,接下来的操作也是跟选项式API中使用的是一样的。

Router_Vuex的任务列表综合案例

本小节将对本章学习的路由加状态管理做一个综合案例,通过案例来巩固本章所学知识点。

在这里插入图片描述

首先先来配置案例中的路由,主要有三个页面,分别对应所有任务,已完成任务,未完成任务。

import { createRouter, createWebHistory } from 'vue-router'
import Todo from '@/views/Todo.vue'
import Complete from '@/views/Complete.vue'
import Incomplete from '@/views/Incomplete.vue'
const routes = [{path: '/',redirect: '/todo'},{path: '/todo',component: Todo},{path: '/complete',component: Complete},{path: '/incomplete',component: Incomplete,}
];
const router = createRouter({history: createWebHistory(),routes
})
export default router;

在来配置一下Vuex状态管理,主要对任务列表进行共享状态处理:

import { createStore } from "vuex";
const store = createStore({state: {todoList: [{isChecked: true, id: 1, task: '第一个任务'},{isChecked: false, id: 2, task: '第二个任务'}]},actions: {},mutations: {add(state, payload){state.todoList.unshift({ isChecked: false, id: state.todoList.length, task: payload });}},getters: {complete(state){return state.todoList.filter((v)=> v.isChecked)},incomplete(state){return state.todoList.filter((v)=> !v.isChecked)}}
});
export default store;

最后看一下三个页面的基本逻辑处理:

<!-- Todo.vue -->
<template><div><ul><li v-for="item in todoList" :key="item.id" :class="{ through: item.isChecked }"><input type="checkbox" v-model="item.isChecked"> {{ item.task }}</li></ul></div>
</template>
<script setup>
import { computed, defineComponent } from 'vue';
import { useStore } from 'vuex';
defineComponent({name: 'TodoView'
});
const store = useStore();
const todoList = computed(()=> store.state.todoList)
</script>
<!-- Complete.vue -->
<template><div><ul><li v-for="item in todoList" :key="item.id" :class="{ through: item.isChecked }"><input type="checkbox" v-model="item.isChecked"> {{ item.task }}</li></ul></div>
</template>
<script setup>
import { computed, defineComponent } from 'vue';
import { useStore } from 'vuex';
defineComponent({name: 'CompleteView'
});
const store = useStore();
const todoList = computed(()=> store.getters.complete)
</script>
<!-- Incomplete.vue -->
<template><div><ul><li v-for="item in todoList" :key="item.id" :class="{ through: item.isChecked }"><input type="checkbox" v-model="item.isChecked"> {{ item.task }}</li></ul></div>
</template>
<script setup>
import { computed, defineComponent } from 'vue';
import { useStore } from 'vuex';
defineComponent({name: 'IncompleteView'
});
const store = useStore();
const todoList = computed(()=> store.getters.incomplete)
</script>

搭建 Vite3 + Pinia2 组合模式

前面我们介绍过Vite和Pinia,其中Vite是最新的脚手架,基于原生ESM方式;而Pinia则是最新的状态管理,比Vuex使用起来更加简单。

本小节我们将演示Vite如何去搭配Pinia来完成项目的开发。

首先对Vite3脚手架进行初始化的安装。

  1. 安装脚手架

    # npm 6.x
    npm create vite@latest vite-study
    # yarn
    yarn create vite vite-study
    # pnpm
    pnpm create vite vite-study
    
  2. 选择框架:因为Vite可以和很多框架配合使用,所以这里我们选择:Vite + Vue

    ? Select a framework: » - Use arrow-keys. Return to submit.Vanilla
    >   VueReactPreactLitSvelte
    
  3. 选择变体:这里先选择自定义形式

    ? Select a variant: » - Use arrow-keys. Return to submit.JavaScriptTypeScript
    >   Customize with create-vueNuxt
    
  4. 选择安装Pinia

    ? Add Pinia for state management? >> No / Yes
    Yes
    
  5. 进入项目:安装第三方模块,并启动项目

    cd vite-study
    npm install
    npm run devVITE v3.1.0  ready in 408 ms➜  Local:   http://127.0.0.1:5173/➜  Network: use --host to expose
    

在安装好Vite后,打开/src/stores可以看到自动安装好了一个示例模块counter.js,代码如下:

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {const count = ref(0)const doubleCount = computed(() => count.value * 2)function increment() {setTimeout(()=>{count.value++}, 2000)}return { count, doubleCount, increment }
})

这里的风格可以是上一个小节中介绍的配置写法,也可以利用组合式API风格来编程Pinia。这里做了一个共享状态count,又做了一个计算属性doubleCount,还有一个方法increment。

在共享方法中是不分同步还是异步的,对于vue devtools都是可以很好的进行监控的,所以比Vuex使用起来要简单一些。下面看一下共享状态是如何进行渲染和方法调用的。

<!-- App.vue -->
<script setup>import { useCounterStore } from './stores/counter';import { storeToRefs } from 'pinia';const counterStore = useCounterStore();const { count, doubleCount } = storeToRefs(counterStore);const handleClick = () => {counterStore.increment();};
</script>
<template><header><button @click="handleClick">点击</button>{{ count }}, {{ doubleCount }}</header>
</template>

Pinia对于模块化的操作方式也比Vuex要简单一些,直接在/stores创建下新创建一个模块JS即可,如:message.js。message.js的代码跟counter.js的代码是一样的格式,使用的时候也是一样的操作行为。

总结内容

  • 了解什么是前端路由,以及Vue3中如何使用vue-router路由
  • 掌握路由的基本操作,如:编程式路由、动态路由、路由守卫等
  • 了解什么是共享状态,以及Vue3中如何使用vuex共享状态
  • 掌握vuex的基本操作,如:同步异步方法、模块化、持久化等
  • 综合应用以及Vuex下一代版本,Pinia存储库

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

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

相关文章

代码审计之SAST自动化

前言: 很久没写文章了&#xff0c;有点忙&#xff0c;落个笔&#xff0c;分享一些捣鼓或说适配好的一些好玩的东西。 脚本工具不开源&#xff0c;给一些思路&#xff0c;希望能给大家带来一些收获。 笔者能力有限&#xff0c;如有错误&#xff0c;欢迎斧正。 正文&#xff1a…

使用docker创建rocketMQ主从结构,使用

1、 创建目录 mkdir -p /docker/rocketmq/logs/nameserver-a mkdir -p /docker/rocketmq/logs/nameserver-b mkdir -p /docker/rocketmq/logs/broker-a mkdir -p /docker/rocketmq/logs/broker-b mkdir -p /docker/rocketmq/store/broker-a mkdir -p /docker/rocketmq/store/b…

Maven解决找不到依赖项

报错如图 方案一&#xff1a;Maven的Setting文件中添加albaba的镜像文件 1.下载maven &#xff1a;Maven – Download Apache Maven 2. 配置镜像 更改成这个&#xff1a; <mirror> <id>alimaven</id> <name>aliyun maven</name> <url&g…

Python量化炒股的财务因子选股

Python量化炒股的财务因子选股-财务因子选股 选股是股市投资的第一步&#xff0c;是最基础的一步&#xff0c;也是最重要的一步。 初识财务因子选股 量化选股是利用数量化的方法选择股票组合&#xff0c;期望该股票组合能够获得超越基准收益率的投资行为。总的来说&#xff…

PDF 正确指定页码后,挂载的书签页码对不上

这个问题与我的另一篇中方法一样 如何让一个大几千页的打开巨慢的 PDF 秒开-CSDN博客 https://blog.csdn.net/u013669912/article/details/138166922 另作一篇的原因 一篇文章附带一个与该文章主题不相关的问题时&#xff0c;不利于被遇到该问题的人快速搜索发现以解决其遇到…

数据结构学习/复习1--时间复杂度计算/异或的几个实际用途

一、什么是数据结构和算法 1注&#xff1a;在内存中的存储管理数据 2注&#xff1a;解决问题的方法 二、时间复杂度 1.算法的效率 2.时间复杂度的概念 计算时间复杂度案例1&#xff1a; 计算时间复杂度案例2&#xff1a; 计算时间复杂度案例3&#xff1a; 计算…

问题(十五)性能分析组件类加载问题

一、引言 最近作者在做性能分析服务的agent&#xff0c;有个功能是在代理启动的时候加载配置中心&#xff0c;拿到具体哪些目录下的类需要增强&#xff0c;这里碰到了类加载失败的问题。 二、类加载 1、问题 这里使用了pom的设置&#xff0c;在class文件被拉进去&#xff0c;…

HTML5(1)

目录 一.HTML5(超文本&#xff08;链接&#xff09;标记&#xff08;标签<>&#xff09;语言) 1.开发环境&#xff08;写代码&#xff0c;看效果&#xff09; 2.vscode 使用 3.谷歌浏览器使用 4.标签语法 5.HTML基本骨架&#xff08;网页模板&#xff09; 6.标签的…

Jetson Orin NX L4T35.5.0平台LT6911芯片 调试记录(2)vi discarding frame问题调试

基于上篇调试记录 Jetson Orin NX L4T35.5.0平台LT6911芯片 调试记录(1)MIPI问题调试-CSDN博客 1.前言 当通过gstreamer持续捕获视频设备时,帧数会下降,并且I输入越高,丢失的帧数越多。 当达到4k30hz时,它完全无法使用,系统会在几秒钟的收集后崩溃并重新启动 4k30hz …

【C++】:类和对象(下)

目录 一&#xff0c;再谈构造函数1.初始化列表2. 隐式类型转换的过程及其优化3. 隐式类型转换的使用4. explcit关键字5. 单参数和多参数构造函数的隐式类型转换 二&#xff0c;static成员1.静态成员变量2.静态成员函数 三&#xff0c;友元3.1 友元函数3.2 友元类 四&#xff0c…

Ansys Speos|进行智能手机镜头杂散光分析

本例的目的是研究智能手机Camera系统的杂散光。杂散光是指光向相机传感器不需要的散光光或镜面光&#xff0c;是在光学设计中无意产生的&#xff0c;会降低相机系统的光学性能。 在本例中&#xff0c;光学透镜系统使用Ansys Zemax OpticStudio (ZOS)进行设计&#xff0c;并使用…

LangChain入门2 RAG详解

RAG概述 一个典型的RAG应用程序,它有两个主要组件&#xff1a; 索引&#xff1a;从源中获取数据并对其进行索引的管道。这通常在脱机情况下发生。检索和生成&#xff1a;在运行时接受用户查询&#xff0c;并从索引中检索相关数据&#xff0c;然后将其传递给模型。 从原始数据…

机器学习:深入解析SVM的核心概念【一、间隔与支持向量】

直接阅读原始论文可能有点难和复杂&#xff0c;所以导师直接推荐我阅读周志华的《西瓜书》&#xff01;&#xff01;然后仔细阅读其中的第六章&#xff1a;支持向量机 间隔与支持向量 **问题一&#xff1a;什么叫法向量&#xff1f;为什么是叫法向量**什么是法向量&#xff1f;…

ChatGPT向付费用户推“记忆”功能,可记住用户喜好 | 最新快讯

4月30日消息&#xff0c;人工智能巨头OpenAI宣布&#xff0c;其开发的聊天机器人ChatGPT将在除欧洲和韩国以外的市场全面上线“记忆”功能。这使得聊天机器人能够“记住”ChatGPT Plus付费订阅用户的详细信息&#xff0c;从而提供更个性化的服务。 OpenAI早在今年2月就已经宣布…

AJAX家政系统 自营+多商家(高级授权)+独立端口 -源码下载

应用介绍 后台&#xff1a;https://service.hnajax.com/hxeJVakAdf.php/index/login AJAX家政系统 自营多商家(高级授权)独立端口 基于FastAdmin和原生微信小程序开发的一款同城预约、上门服务、到店核销家政系统&#xff0c;用户端、服务端(高级授权)、门店端(高级授权)各端…

HTML:认识HTML及基本语法

目录 1. HTML介绍 2. 关于软件选择和安装 3. HTML的基本语法 1. HTML介绍 HyperText Markup Language 简称HTML&#xff0c;意为&#xff1a;超文本标记语言 超文本&#xff1a;是指页面内可以包含的图片&#xff0c;链接&#xff0c;声音&#xff0c;视频等内容 标记&am…

76、堆-数据流的中位数

思路&#xff1a; 这个问题是动态数据流中位数查找问题。在数据流中&#xff0c;数据是逐个到来的&#xff0c;而我们需要在任何时候快速返回已有数据的中位数。中位数是将数据集分成两个等长的子集&#xff0c;一个包含所有较小的元素而另一个包含所有较大的元素。 为了高效解…

升级 Vite 5 出现警告 The CJS build of Vite‘s Node API is deprecated

错误描述 vue3-element-admin 项目将Vite4 升级至 Vite5 后,项目运行出现如下警告: The CJS build of Vites Node API is deprecated. See https://vitejs.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.图片 问题原因 Vite 官方弃用 C…

WIN10 anaconda 安装 CondaError: Run ‘conda init‘ before ‘conda activate‘

1 下载 https://www.anaconda.com/download/success 2 安装 3 修改环境变量 安装后修改环境变量 4 winrun 进入命令窗口 输入cmd 输入 conda info 5 创建 虚拟环境 conda create -n yolov8 python3.8 -y 6 CondaError: Run ‘conda init’ before ‘conda activate’ c…

在Primavera P6 中维护自定义活动栏

前言 自从 Henry Gantt 在 1910 年左右提出这个想法以来&#xff0c;以图形方式显示项目进度表并沿时间刻度显示条形图一直延续到当今最复杂和流行的项目进度系统中。在本文中&#xff0c;我们将仔细研究 Primavera P6 Professional 中的甘特图&#xff0c;并探索一些自定义其…