【学习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-persist
	
import 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
    >   Vue
        React
        Preact
        Lit
        Svelte
    
  3. 选择变体:这里先选择自定义形式

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

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

    cd vite-study
    npm install
    npm run dev
    
    VITE 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存储库

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu开启message文件

环境&#xff1a;ubuntu 20.04 1、首先需要修改 /etc/rsyslog.d/50-default.conf 文件&#xff1b;源文件中message被注释&#xff0c;如下图&#xff1a; 2、打开注释&#xff1a; 3、重启服务 systemctl restart rsyslog.service 如此即可&#xff01;

OFDM802.11a的FPGA实现(五)卷积编码器的FPGA实现与验证(含verilog代码和matlab代码)

目录 1.前言2.卷积编码2.1卷积编码基本概念2.2 802.11a卷积编码器2.3 卷积编码模块设计2.4 Matlab设计与ModelSim仿真验证 1.前言 前面一节完成了扰码器的FPGA设计与Matlab验证&#xff0c;这节继续对卷积编码器进行实现和验证。 2.卷积编码 2.1卷积编码基本概念 卷积码编码器…

Aiseesoft Data Recovery for Mac:专业数据恢复软件

Aiseesoft Data Recovery for Mac是一款高效且专业的数据恢复软件&#xff0c;专为Mac用户量身打造。 Aiseesoft Data Recovery for Mac v1.8.22激活版下载 无论是由于误删、格式化还是系统崩溃等原因导致的数据丢失&#xff0c;Aiseesoft都能帮助您快速找回。 它采用先进的扫描…

Windows下Git安装

目录 一、下载二、安装三、查看 Git 安装路径 一、下载 下载链接&#xff1a;https://git-scm.com/ 二、安装 双击安装包&#xff0c;按提示一步步进行操作&#xff1a; 三、查看 Git 安装路径 where git D:\Program Files\Git\cmd\git.exe

什么是DDoS攻击?怎么防御DDoS攻击?

在网络安全领域&#xff0c;DDoS攻击一直是热门话题&#xff0c;随着网络技术的不断发展和网络环境的复杂化演变&#xff0c;DDoS攻击变得愈加频繁、更具破坏性。根据2023年网络安全态势研判分析年度综合报告&#xff0c;全年全网网络层的DDoS攻击次数达2.51亿次&#xff01;本…

卷积通用模型的剪枝、蒸馏---蒸馏篇--KD蒸馏(以deeplabv3+为例)

上篇文章介绍了剪枝篇,本文以上篇的剪枝模型为学生模型,以剪枝之前的模型为教师模型,进行KD逻辑蒸馏,之后会尝试特征蒸馏和关系蒸馏等。 一、KD逻辑蒸馏 1.1 大致过程 逻辑蒸馏,是基于分类问题设计的,因此非常适用于语义分割。模型最后会有一个softmax层,其输出值对应了…

React正式更新!开始学习React 19!

本文为原创文章&#xff0c;原文链接&#xff1a;J实验室&#xff0c;未经授权请勿转载 今年2月份&#xff0c;React 发布消息确认今年发布 v19 版本&#xff0c;尘封两年的版本号终于要更新了&#xff08;详情点击&#xff1a;React 19 发布在即&#xff0c;抢先学习一下新特性…

x2600君正 ubi文件系统的编译和烧录

使用平台&#xff1a;君正x2600 ubi文件系统使用问题 1.ubi文件和ubifs文件 2 方法&#xff1a;mkfs.ubifs和ubinize两步打包ubi文件系统 mkfs.ubifs工具 mkfs.ubifs命令用于制作ubifs文件系统&#xff0c;命令示例如下&#xff1a; mkfs.ubifs -x lzo -m 2KiB -e 124KiB -c 3…

FSNotes for Mac v6.7.1中文激活版:强大的笔记管理工具

FSNotes for Mac是一款功能强大的文本处理与笔记管理工具&#xff0c;为Mac用户提供了一个直观、高效的笔记记录和整理平台。 FSNotes for Mac v6.7.1中文激活版下载 FSNotes支持Markdown语法&#xff0c;使用户能够轻松设置笔记格式并添加链接、图像等元素&#xff0c;实现笔记…

【软考高项】第十二章 项目质量管理

目录 12.1管理基础 12.1.1质量与项目质量 12.1.2质量管理 12.1.3质量管理标准体系 12.1.4管理新实践 12.2项目质量管理过程 12.2.1过程概述 12.2.2裁剪考虑因素 12.2.3敏捷与适应方法 12.3规划质量管理 12.3.1输入 12.3.2工具与技术 12.3.3输出 12.4管理质量 12…

最小K个数(力扣面试题17.14)

本文采用的是大堆排序求最小的K个值。需要有堆的数据结构基础哦。 代码展示&#xff1a; /*** Note: The returned array must be malloced, assume caller calls free().*/ void AdjustDown(int* parr,int n,int root)//向下调整 {int parentroot;int child parent*21;while…

opencv_23_高斯模糊

void ColorInvert::gaussian_blur(Mat& image) { Mat dst; GaussianBlur(image, dst, Size(0, 0), 15); // Size(2, 2), imshow("图像模糊2", dst); }

代码随想录算法训练营DAY42|C++动态规划Part4|0-1背包理论基础(一)、0-1背包理论基础之滚动数组(二)、416.分割等和子集

文章目录 0-1背包理论基础(一)前置知识01背包动态规划&#xff1a;01背包二维dp数组 CPP代码再论01背包的遍历顺序 0-1背包理论基础(二)一维dp数组如何初始化一维dp数组遍历顺序举例推导dp数组CPP代码 416.分割等和子集思路将题目抽象成0-1背包问题 CPP代码 0-1背包理论基础(一…

2013NOIP普及组真题 4. 车站分级

线上OJ&#xff1a; 一本通&#xff1a;http://ybt.ssoier.cn:8088/problem_show.php?pid1964 核心思想&#xff1a; 1、原文中提到 “如果这趟车次停靠了火车站 x&#xff0c;则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠”&#xff0c;如果设停靠站为A&…

ansible-playbook离线升级centos内核

目录 概述实践ansible目录结构关键代码执行效果 结束 概述 内核离线包官网下载地址如下&#xff1a; 地址 实践 ansible目录结构 如对 ansible 不熟悉&#xff0c;离线包下载有问题&#xff0c;请至此地址下载&#xff0c;按本文操作可直接使用。 相关文章链接如下 文章地…

如何在iPhone上恢复出厂设置后恢复数据

你不想让这种情况发生&#xff0c;但它确实发生了。您必须将iPhone恢复出厂设置。当您的 iPhone 上出现软件问题且无法修复时&#xff0c;可能会发生这种情况。相反&#xff0c;在更新期间&#xff0c;或者您的iPhone遇到问题时&#xff0c;iPhone上的数据不再存在。 不过不用…

goget配置多个golang 运行环境

一台主机安装多个golang 运行环境 本环境 windows10 为 基础 mac linux也可以按照此方法操作 背景 开发不同的运维工具会用到不同版本的golang&#xff0c;但是开发者不能一直进行重装来处理 &#xff0c;因此 需要一个工具进行golang版本的管理 go管理工具介绍 gvm (Go V…

android webview检测屏幕

1&#xff09;清单文件配置&#xff1a; 配置权限&#xff1a; <uses-permission android:name"android.permission.INTERNET" /> 注册activity&#xff1a; <activityandroid:name".TouchWebViewActivity"android:exported"true"&…

基于随机森林和Xgboost对肥胖风险的多类别预测

基于随机森林和Xgboost对肥胖风险的多类别预测 作者&#xff1a;i阿极 作者简介&#xff1a;数据分析领域优质创作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏…

学习【Mysql运维篇】这一篇就够了

运维篇 1. 日志1-1. 错误日志1-2. 二进制日志1-3. 查询日志1-4. 慢查询日志 2. 主从复制2-1. 概述2-2. 原理2-3. 搭建 3. 分库分表3-1. 介绍3-2. Mycat概述3-3. Mycat入门3-4. Mycat配置3-5. Mycat分片3-6. Mycat管理及监控 4. 读写分类 1. 日志 1-1. 错误日志 错误日志是MyS…