Vue笔记(八)

一、Pinia

(一)手动添加Piaia到Vue项目

1.安装Pinia:使用包管理器进行安装,在项目目录下运行 npm install pinia 或 yarn add pinia ,为项目引入Pinia状态管理库。
 
2.创建Pinia实例:在项目的JavaScript代码中,通常在 main.js 里创建Pinia实例。先从 pinia 库中导入 createPinia 函数,再调用该函数生成Pinia实例。这一实例用于管理整个项目的状态。
 
3.挂载Pinia实例到Vue应用:创建好Pinia实例后,通过 app.use(pinia) 方法将其挂载到Vue应用上,确保整个Vue项目都能使用Pinia进行状态管理。
 
4.使用注意事项:Pinia主要用于在Vue项目中进行状态管理,它能集中管理组件间共享的数据,提升开发效率和代码的可维护性。在使用时,要注意正确配置和引入相关依赖,按照规范的方式创建和使用状态、getters、actions等。

// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'// 创建Pinia实例
const pinia = createPinia()
const app = createApp(App)// 挂载Pinia实例到Vue应用
app.use(pinia)
app.mount('#app')

 

(二)Pinia基本语法

 1.在Pinia中,通过 defineStore 函数来定义store。 defineStore 接收两个参数,第一个是store的唯一ID,第二个是一个配置对象。

import { defineStore } from 'pinia'// 使用defineStore定义一个名为counterStore的store
const useCounterStore = defineStore('counter', {state: () => {return {count: 0}},getters: {doubleCount: (state) => state.count * 2},actions: {increment() {this.count++}}
})

 2.在组件中使用定义好的store,首先要引入对应的 useStore 函数,然后调用该函数获取store实例,进而访问和修改store中的状态、调用getters和actions。

<template><div><p>Count: {{ counterStore.count }}</p><p>Double Count: {{ counterStore.doubleCount }}</p><button @click="counterStore.increment">Increment</button></div>
</template><script setup>
import { useCounterStore } from './stores/counterStore.js'const counterStore = useCounterStore()
</script>

 3.state 是一个函数,返回一个对象,这个对象中的属性就是store的状态。状态是响应式的,当状态发生变化时,依赖它的组件会自动更新。

Getters(计算属性)

getters 用于对store中的状态进行计算和处理,类似于Vue组件中的计算属性。它接收 state 作为参数,可以返回一个计算后的值。

Actions(操作)

actions 用于定义可以修改状态的方法,也可以进行异步操作。在 actions 中可以通过 this 访问store的状态和其他方法。

(三)Pinia-action异步写法

 1.action不仅能同步修改状态,还可处理异步任务。通过在action中使用 async/await 语法,能让代码以更简洁、直观的方式处理异步操作,避免复杂的回调地狱。

2.与同步action的区别:同步action即时执行并修改状态,而异步action在异步操作完成后才更新状态。并且,异步action需处理异步操作可能出现的错误,增强代码的健壮性。
 
3.错误处理:使用 try...catch 块捕获异步操作中的错误,可在捕获错误后,根据不同错误类型进行相应处理

import { defineStore } from 'pinia'
// 模拟一个异步请求函数
const fetchData = () => {return new Promise((resolve, reject) => {setTimeout(() => {const success = Math.random() > 0.5;if (success) {resolve({ data: '异步请求成功的数据' });} else {reject(new Error('异步请求失败'));}}, 1000);});
}const useAsyncStore = defineStore('asyncStore', {state: () => ({asyncData: null,error: null}),actions: {async fetchAsyncData() {try {const response = await fetchData();this.asyncData = response.data;} catch (error) {this.error = error.message;}}}
});

 在组件中使用这个带有异步action的store:

<template><div><button @click="fetchAsyncData">获取异步数据</button><div v-if="asyncData">数据: {{ asyncData }}</div><div v-if="error" style="color: red">错误: {{ error }}</div></div>
</template><script setup>
import { useAsyncStore } from './stores/asyncStore.js';
const asyncStore = useAsyncStore();
const fetchAsyncData = async () => {await asyncStore.fetchAsyncData();
};
</script>

(四)Pinia-storeToRefs方法

1.  storeToRefs 是Pinia提供的工具函数,用于将store中的状态转换为响应式引用(refs)。在解构store状态时,能保持状态的响应性,避免丢失响应式导致组件无法随状态变化自动更新。
 
2.原理:它会遍历store的状态对象,为每个属性创建一个对应的ref对象,将这些ref对象包装在一个新对象中返回。在组件中解构这个返回对象,就能得到与store状态关联且保持响应性的ref。
 
3.与直接解构对比:直接解构store状态,如 const { count } = counterStore , count 失去响应性;而使用 storeToRefs ,即 const { count } = storeToRefs(counterStore) , count 是响应式的,组件能感知其变化并重新渲染。

// 定义store
import { defineStore } from 'pinia'
const useCounterStore = defineStore('counter', {state: () => ({count: 0}),actions: {increment() {this.count++}}
})<!-- 组件中使用storeToRefs -->
<template><div><p>Count: {{ count }}</p><button @click="counterStore.increment">Increment</button></div>
</template><script setup>
import { useCounterStore, storeToRefs } from './stores/counterStore.js'
const counterStore = useCounterStore()
const { count } = storeToRefs(counterStore)
</script>

(五)Pinia持久化

 1.Pinia持久化是指将Pinia store中的状态数据保存下来,在页面刷新、关闭浏览器再打开等情况下,数据依然存在,不会丢失。这样可以提升用户体验,保持应用状态的连贯性。
 
2.实现方式:通常借助插件来实现,如 pinia-plugin-persistedstate 插件。该插件能将store状态存储在浏览器的本地存储(Local Storage)、会话存储(Session Storage)或其他存储机制中。

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import App from './App.vue'const pinia = createPinia()
// 使用插件
pinia.use(piniaPluginPersistedstate)const app = createApp(App)
app.use(pinia)
app.mount('#app')
import { defineStore } from 'pinia'const useCounterStore = defineStore('counter', {state: () => ({count: 0}),// 开启持久化,默认存储在本地存储persist: true 
})

 

二、Vue3项目大事件

(一)项目介绍和pnpm创建项目

1.pnpm是一种快速、节省磁盘空间的包管理器。相比npm和yarn,它利用硬链接和内容寻址存储机制,能更高效地管理项目依赖,减少磁盘占用,提升安装速度,并且在多项目开发时能共享依赖,降低维护成本。
 
2.使用pnpm创建项目:需先确保已安装pnpm,可在官网下载对应安装包完成安装。在命令行中,使用 pnpm create vue@latest 命令来创建Vue项目。创建过程中,会提示设置项目名称、选择包管理器(此时默认选择pnpm)、是否使用TypeScript、是否安装Vue Router和Pinia等,可根据项目需求进行选择。
 
3.创建Vue项目:在命令行输入以下命令:

bash   
pnpm create vue@latest

4.根据提示依次输入:

项目名称(例如 big-events-project )。
 选择包管理器时,默认选择 pnpm 。
 对于是否使用TypeScript、是否安装Vue Router和Pinia等问题,按需求输入 y 或 n 进行选择。
例如,若希望项目使用TypeScript且安装Vue Router和Pinia,依次选择 y 确认。 安装完成后,进入项目目录:

bash   
cd big-events-project

(二)ESlint配合Prettier完成代码风格配置


ESlint与Prettier的作用

1. ESlint:主要用于发现并报告JavaScript代码中的问题,确保代码符合一定的规范和最佳实践,还能检测潜在的错误,提升代码质量。
 
2.Prettier:专注于代码格式化,统一代码风格,自动调整代码的排版,如缩进、换行、空格等,使团队成员编写的代码格式一致,增强代码可读性。
 
3.两者配合的优势:ESlint侧重代码质量和规范检查,Prettier负责格式化代码,两者结合能在保证代码质量的同时,让代码拥有统一美观的风格,减少因代码风格不一致引发的冲突,提高开发效率。

配置步骤

1.安装相关依赖:包括ESlint、Prettier以及它们的Vue插件和相关配置文件。
 
2.初始化ESlint配置:使用命令生成基础配置文件,根据项目需求修改规则。
 
3.配置Prettier:创建配置文件,设置格式化规则,让其与ESlint协同工作。
 
4.解决冲突:由于两者对代码的处理方式有重叠,需配置插件解决潜在冲突,确保代码检查和格式化顺利进行。

 
5.安装依赖:在项目根目录下执行命令:

bash   
pnpm add eslint eslint-plugin-vue @vue/eslint-config-prettier @vue/eslint-config-standard prettier eslint-plugin-prettier eslint-plugin-standard -D

初始化ESlint配置:运行命令生成配置文件,按提示选择配置选项:

bash   
npx eslint --init

创建Prettier配置文件:在项目根目录创建 .prettierrc.json 文件,添加如下配置:

 
json   
{"semi": true,"singleQuote": true,"trailingComma": "es5"
}


 
配置ESlint与Prettier协同工作:在 .eslintrc.js 文件中,添加或修改配置:
 


module.exports = {// 其他配置项...extends: ['plugin:vue/vue3-essential', '@vue/standard', '@vue/prettier']
};


 

(三)基于husky的代码检查工作流程

 

1.husky是一个Git钩子工具,它允许开发者在Git操作(如commit、push等)的特定阶段执行自定义脚本。在Vue3大事件项目中,利用husky可实现自动化的代码检查,保证提交到仓库的代码质量,避免低质量代码进入版本库。
 
2.基于husky的代码检查工作流原理:在项目中配置husky后,当执行Git操作时,husky会检测是否有对应的钩子脚本。若有,就执行该脚本,例如在 pre-commit 钩子中,可以运行ESlint等代码检查工具,检查暂存区的代码是否符合规范,若不符合则阻止提交,开发者需修改代码后再次提交。

配置步骤

1.安装husky:在项目中使用包管理器安装husky,它会在项目中创建必要的文件和目录结构,用于管理钩子脚本。
 
2.的钩子文件模板。
 
3.添加钩子脚本:在husky生成的钩子文件中,添加实际执行代码检查的脚本命令,通常是运行ESlint检查暂存区文件的命令。

安装husky:在项目根目录下,使用pnpm(若项目使用pnpm管理依赖)安装husky,命令如下:
 
bash
  
pnpm add husky -D

激活husky:运行以下命令激活husky,它会在项目根目录下创建 .husky 目录,并在其中生成一些初始文件:
 
bash
  
npx husky install

添加 pre-commit 钩子脚本:在 .husky 目录下找到 pre-commit 文件(若不存在可手动创建),添加以下内容:
 
bash
  
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

pnpm lint

假设项目中 pnpm lint 命令已配置为运行ESlint进行代码检查。这样,每次执行 git commit 时,husky会先运行 pnpm lint 命令检查代码,若代码检查不通过,提交会被阻止。

(四)调整目录

如果在某个组件(如 Home.vue )中原来引用 user.js 的方式是 import { getUserInfo } from '@/user.js'; ,移动文件后需要更新为 import { getUserInfo } from '@/api/user.js';

<!-- Home.vue -->
<template><div><!-- 组件内容 --></div>
</template><script setup>
// 更新前引用路径
// import { getUserInfo } from '@/user.js';
// 更新后引用路径
import { getUserInfo } from '@/api/user.js';
// 后续使用getUserInfo函数的代码
</script>

 

(五)VueRouter4路由语法解析

 1.基本概念:VueRouter4是Vue.js官方的路由管理器,用于构建单页面应用(SPA)的路由系统。它能让页面在不刷新的情况下实现不同视图间的切换,提升用户体验。在Vue3大事件项目里,借助VueRouter4实现页面导航、组件展示切换等功能。

路由定义与配置

1. 创建路由实例:通过 createRouter 函数创建路由实例,该函数接收一个配置对象,包含路由模式(如 history 模式用于去除URL中的 # )、路由规则数组等关键信息。
 
2.定义路由规则:在路由规则数组中,每个对象代表一条路由规则。包含 path (路由路径)、 name (路由名称,方便引用)、 component (对应路径要渲染的组件)等属性。例如,定义首页路由, path 设为 / , component 指定为首页组件。

路由导航

1.声明式导航:在模板中使用 <router-link> 组件进行导航。通过设置 to 属性指定目标路由的路径或名称,点击该组件会触发路由切换,如 <router-link to="/home">首页</router-link> 。
 
2.编程式导航:在JavaScript代码中使用 router.push 或 router.replace 方法进行导航。 router.push 会向历史记录中添加一条新记录, router.replace 则替换当前历史记录,常用于登录成功后跳转到特定页面等场景。

动态路由

在路由路径中使用冒号( : )定义动态参数。比如 /user/:id ,其中 :id 就是动态参数,可用于根据不同用户ID展示对应信息。在组件中通过 $route.params 获取动态参数的值。

嵌套路由

用于构建具有层级结构的页面布局,在父路由的 children 属性中定义子路由规则。每个子路由同样包含 path 、 name 、 component 等属性,子路由的路径是相对于父路由的。
 
代码示例

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import UserDetail from '@/views/UserDetail.vue'const router = createRouter({history: createWebHistory(),routes: [{path: '/',name: 'Home',component: Home},{path: '/user/:id',name: 'UserDetail',component: UserDetail},{path: '/parent',name: 'Parent',component: () => import('@/views/Parent.vue'),children: [{path: 'child',name: 'Child',component: () => import('@/views/Child.vue')}]}]
})export default router
<!-- 在模板中使用声明式导航 -->
<template><div><router-link to="/">首页</router-link><router-link to="/user/123">用户详情</router-link><router-link to="/parent/child">子页面</router-link><router-view></router-view></div>
</template>
// 在组件中使用编程式导航
import { useRouter } from 'vue-router'export default {setup() {const router = useRouter()const goToUserDetail = () => {router.push('/user/456')}return {goToUserDetail}}
}

 

// 在UserDetail.vue组件中获取动态参数
import { useRoute } from 'vue-router'export default {setup() {const route = useRoute()const userId = route.params.idreturn {userId}}
}

 

<!-- 在组件模板中使用编程式导航对应的方法 -->
<template><button @click="goToUserDetail">跳转到用户详情</button>
</template>

(六)ElementPlus按需引入

 ElementPlus是基于Vue 3的桌面端组件库。在项目中按需引入,而非全部引入,能有效减少项目体积,提升加载速度。按需引入借助 unplugin-vue-components 和 unplugin-auto-import 插件实现,它们可自动导入所需组件和函数,避免手动逐个引入的繁琐操作。

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'export default defineConfig({plugins: [vue(),AutoImport({resolvers: [ElementPlusResolver()]}),Components({resolvers: [ElementPlusResolver()]})]
})

(七)Pinia构建用户仓库和持久化

 使用Pinia构建用户仓库,用于集中管理与用户相关的状态数据,如用户登录信息、权限等。通过持久化存储用户仓库数据,可在页面刷新或关闭后重新打开时,保留用户状态,提升用户体验。持久化借助 pinia-plugin-persistedstate 插件实现。

import { defineStore } from 'pinia'const useUserStore = defineStore('user', {state: () => ({userInfo: null,token: ''}),actions: {setUserInfo(info) {this.userInfo = info},setToken(token) {this.token = token}},persist: true
})export default useUserStore

 在组件中使用用户仓库:在组件的 <script setup> 中

import { useUserStore } from '@/stores/user.js'const userStore = useUserStore()
const login = () => {const newUserInfo = { name: 'test', age: 18 }const newToken = '123456'userStore.setUserInfo(newUserInfo)userStore.setToken(newToken)
}

(八)数据交互--请求工具设计

// 创建request.js文件
import axios from 'axios'// 创建axios实例
const request = axios.create({baseURL: 'https://api.example.com', // 基础URLtimeout: 5000 // 超时时间
})// 请求拦截器
request.interceptors.request.use(config => {// 在发送请求前做些什么,如添加tokenconst token = localStorage.getItem('token')if (token) {config.headers['Authorization'] = `Bearer ${token}`}return config
}, error => {return Promise.reject(error)
})// 响应拦截器
request.interceptors.response.use(response => {return response.data
}, error => {// 处理响应错误,如统一错误提示console.error('请求错误', error)return Promise.reject(error)
})export default request

 

 

(九)路由的设计和配置

 

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import Login from '@/views/Login.vue'
import Dashboard from '@/views/Dashboard.vue'const router = createRouter({history: createWebHistory(),routes: [{path: '/',name: 'Home',component: Home},{path: '/login',name: 'Login',component: Login},{path: '/dashboard',name: 'Dashboard',component: Dashboard,meta: { requiresAuth: true } // 需要登录才能访问}]
})// 全局前置守卫
router.beforeEach((to, from, next) => {const isLoggedIn = localStorage.getItem('token')if (to.meta.requiresAuth &&!isLoggedIn) {next('/login')} else {next()}
})export default router

三、注册登录

(一)静态结构--基本切换

 搭建注册登录页面的静态结构,使用HTML和CSS构建页面布局,包含用户名、密码输入框,注册/登录按钮等元素。利用Vue的动态组件和状态管理实现注册和登录页面的基本切换功能,通过一个标志变量控制显示哪个页面,增强用户操作的便捷性。

<template><div><button @click="showLogin = true">登录</button><button @click="showLogin = false">注册</button><component :is="showLogin? 'LoginComponent' : 'RegisterComponent'"></component></div>
</template><script setup>
import LoginComponent from '@/components/LoginComponent.vue'
import RegisterComponent from '@/components/RegisterComponent.vue'
import { ref } from 'vue'const showLogin = ref(true)
</script>
<!-- LoginComponent.vue -->
<template><div><h2>登录</h2><input type="text" placeholder="用户名"><input type="password" placeholder="密码"><button>登录</button></div>
</template>
<!-- RegisterComponent.vue -->
<template><div><h2>注册</h2><input type="text" placeholder="用户名"><input type="password" placeholder="密码"><input type="password" placeholder="确认密码"><button>注册</button></div>
</template>

 

 

(二)表单校验

 为确保用户输入数据的准确性和合法性,对注册登录表单进行校验。使用 vee-validate 库,定义校验规则,如用户名长度、密码强度、确认密码一致性等。在表单提交时,根据校验结果决定是否允许提交,同时在页面上实时显示校验错误信息,引导用户正确输入。

# 安装vee-validate
npm install vee-validate@next
<template><div><h2>注册</h2><Form @submit="onSubmit"><Field name="username" :rules="['required', 'alpha_num', 'between:3,20']"><template #default="{ field }"><input v-bind="field" type="text" placeholder="用户名"><ErrorMessage name="username" /></template></Field><Field name="password" :rules="['required', 'length:6,20']"><template #default="{ field }"><input v-bind="field" type="password" placeholder="密码"><ErrorMessage name="password" /></template></Field><Field name="confirmPassword" :rules="['required', 'confirmed:password']"><template #default="{ field }"><input v-bind="field" type="password" placeholder="确认密码"><ErrorMessage name="confirmPassword" /></template></Field><button type="submit">注册</button></Form></div>
</template><script setup>
import { Form, Field, ErrorMessage } from 'vee-validate'
import { ref } from 'vue'const onSubmit = (values) => {console.log('提交的数据', values)
}
</script>

四、注册预校验--封装api实现注册功能

 在注册功能中,进行预校验,如检查用户名是否已存在,提高注册的成功率。封装注册API,将注册请求的逻辑封装在一个函数中,方便在不同组件中调用。在注册时,调用封装的API,处理注册成功或失败的情况,如保存用户信息、提示用户注册结果。

// api/user.js
import request from '@/utils/request'export const register = (data) => {return request.post('/register', data)
}<template><div><h2>注册</h2><Form @submit="handleSubmit"><Field name="username" :rules="['required', 'alpha_num', 'between:3,20']"><template #default="{ field }"><input v-bind="field" type="text" placeholder="用户名"><ErrorMessage name="username" /></template></Field><Field name="password" :rules="['required', 'length:6,20']"><template #default="{ field }"><input v-bind="field" type="password" placeholder="密码"><ErrorMessage name="password" /></template></Field><Field name="confirmPassword" :rules="['required', 'confirmed:password']"><template #default="{ field }"><input v-bind="field" type="password" placeholder="确认密码"><ErrorMessage name="confirmPassword" /></template></Field><button type="submit">注册</button></Form></div>
</template><script setup>
import { Form, Field, ErrorMessage } from 'vee-validate'
import { register } from '@/api/user.js'
import { ref } from 'vue'
import { useRouter } from 'vue-router'const router = useRouter()
const handleSubmit = async (values) => {try {const response = await register(values)if (response.success) {// 注册成功,保存用户信息,跳转到首页localStorage.setItem('token', response.data.token)router.push('/')} else {console.error('注册失败', response.message)}} catch (error) {console.error('注册请求错误', error)}
}
</script>

五、登录校验和登录请求

 登录校验用于确保用户输入的登录信息准确无误,常见校验包括用户名或邮箱格式、密码长度等。登录请求则是将用户输入信息发送到后端服务器进行验证,验证通过后获取相关授权信息(如token),实现用户登录功能。校验和请求功能需协同,校验不通过时阻止请求发送,保障数据交互准确性。

<template><div><h2>登录</h2><form @submit.prevent="handleLogin"><label for="username">用户名:</label><input type="text" id="username" v-model="formData.username" required><label for="password">密码:</label><input type="password" id="password" v-model="formData.password" required minlength="6"><button type="submit">登录</button></form></div>
</template><script setup>
import { ref } from 'vue';
import { login } from '@/api/user.js';const formData = ref({username: '',password: ''
});const handleLogin = async () => {if (!formData.value.username ||!formData.value.password) {alert('用户名和密码不能为空');return;}try {const response = await login(formData.value);if (response.success) {localStorage.setItem('token', response.data.token);// 登录成功,跳转到首页} else {alert('登录失败,请检查用户名和密码');}} catch (error) {console.error('登录请求出错', error);}
};
</script>// api/user.js
import request from '@/utils/request';export const login = (data) => {return request.post('/login', data);
};

六、首页

(一)layout架子分析和登录访问拦截

首页 layout 架子分析旨在确定首页整体布局结构,包括导航栏、侧边栏、内容区域等组件的划分与布局方式。登录访问拦截是利用路由守卫机制,判断用户是否登录。未登录用户尝试访问首页等受保护页面时,将其重定向到登录页面,保障页面访问安全性,防止非法访问。

// router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import Home from '@/views/Home.vue';
import Login from '@/views/Login.vue';const router = createRouter({history: createWebHistory(),routes: [{path: '/',name: 'Home',component: Home,meta: { requiresAuth: true }},{path: '/login',name: 'Login',component: Login}]
});router.beforeEach((to, from, next) => {const token = localStorage.getItem('token');if (to.meta.requiresAuth &&!token) {next('/login');} else {next();}
});export default router;<!-- Home.vue -->
<template><div class="home-layout"><header>导航栏</header><aside>侧边栏</aside><main>内容区域</main></div>
</template><script setup>
// 首页组件逻辑
</script><style scoped>
.home-layout {display: flex;
}
header {width: 100%;height: 60px;background-color: #333;color: white;text-align: center;
}
aside {width: 200px;background-color: #f0f0f0;
}
main {flex: 1;background-color: #fff;
}
</style>

(二)用户基本信息渲染和退出

用户基本信息渲染是从存储(如本地存储、后端接口获取)中读取用户相关信息,如用户名、头像等,并在首页展示。退出功能则是清除用户登录状态相关信息(如token),使用户登出系统,同时更新页面状态,如隐藏用户信息展示区域、跳转到登录页面等

<template><div class="home-layout"><header><div v-if="userInfo"><span>{{ userInfo.username }}</span><button @click="handleLogout">退出</button></div></header><aside>侧边栏</aside><main>内容区域</main></div>
</template><script setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';const userInfo = ref(JSON.parse(localStorage.getItem('userInfo')));
const router = useRouter();const handleLogout = () => {localStorage.removeItem('token');localStorage.removeItem('userInfo');userInfo.value = null;router.push('/login');
};
</script>

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

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

相关文章

vue纯静态实现 视频转GIF 功能(附源码)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、实现后的效果二、使用步骤1.引入库2.下载or复制出来js3. 前端实现 总结 前言 一天一个小demo 今天来一个vue纯静态实现 视频转GIF 功能 上一篇我们讲到了…

嵌入式八股文面试题(二)C语言算法

相关概念请查看文章&#xff1a;C语言概念。 1. 如何实现一个简单的内存池&#xff1f; 简单实现&#xff1a; #include <stdio.h> #include <stdlib.h>//内存块 typedef struct MemoryBlock {void *data; // 内存块起始地址struct MemoryBlock *next; // 下一个内…

【Python】集合

个人主页&#xff1a;GUIQU. 归属专栏&#xff1a;Python 文章目录 1. 集合的创建2. 集合的基本操作2.1 访问集合元素2.2 添加元素2.3 删除元素 3. 集合的数学运算3.1 交集&#xff08;& 或 intersection() 方法&#xff09;3.2 并集&#xff08;| 或 union() 方法&#xf…

Flutter_学习记录_基本组件的使用记录_2

1. PopupMenuButton的使用 代码案例&#xff1a; import package:flutter/material.dart;// ----PopupMemuButtonDemo的案例---- class PopupMemuButtonDemo extends StatefulWidget {const PopupMemuButtonDemo({super.key});overrideState<PopupMemuButtonDemo> crea…

基于java手机销售网站设计和实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

初识计算机网络

从此篇我将开始网络新篇章&#xff01; 1. 网络发展史 最初的计算机之间相互独立存在&#xff0c;每个计算机只能持有自己的数据&#xff0c;数据无法共享。此时的计算机为独立模式 随着时代的发展&#xff0c;越来越需要计算机之间互相通信&#xff0c;共享软件和数据&#x…

PyTorch 中 `torch.cuda.amp` 相关警告的解决方法

在最近的写代码过程中&#xff0c;遇到了两个与 PyTorch 的混合精度训练相关的警告信息。这里随手记录一下。 警告内容 警告 1: torch.cuda.amp.autocast FutureWarning: torch.cuda.amp.autocast(args...) is deprecated. Please use torch.amp.autocast(cuda, args...) i…

【PS 2022】Adobe Genuine Service Alert 弹出

电脑总是弹出Adobe Genuine Service Alert弹窗 1. 不关掉弹窗并打开任务管理器&#xff0c;找到Adobe Genuine Service Alert&#xff0c;并右键进入文件所在位置 2 在任务管理器中结束进程并将文件夹中的 .exe 文件都使用空文档替换掉 3. 打开PS不弹出弹窗&#xff0c;解决&a…

Vue2生命周期面试题

在 Vue 2 中&#xff0c;this.$el 和 this.$data 都是 Vue 实例的属性&#xff0c;代表不同的内容。 1. this.$el this.$el 是 Vue 实例的根 DOM 元素&#xff0c;它指向 Vue 实例所控制的根节点元素。在 Vue 中&#xff0c;el 是在 Vue 实例创建时&#xff0c;指定的根元素&…

unity 安装Entities

因为Entities目前不支持用资源名动态加载资源&#xff01;没错&#xff0c;AssetsBundle或Addressables都不能用于Entities&#xff1b;也就意味着现阶段不能用Entities开发DLC或热更游戏。 Entities必须使用SubScene&#xff0c;而SubScene不能从资源动态加载&#xff0c;路被…

基于 PyTorch 的树叶分类任务:从数据准备到模型训练与测试

基于 PyTorch 的树叶分类任务&#xff1a;从数据准备到模型训练与测试 1. 引言 在计算机视觉领域&#xff0c;图像分类是一个经典的任务。本文将详细介绍如何使用 PyTorch 实现一个树叶分类任务。我们将从数据准备开始&#xff0c;逐步构建模型、训练模型&#xff0c;并在测试…

团结引擎 Shader Graph:解锁图形创作新高度

Shader Graph 始终致力于为开发者提供直观且高效的着色器构建工具&#xff0c;持续推动图形渲染创作的创新与便捷。在团结引擎1.4.0中&#xff0c;Shader Graph 迎来了重大更新&#xff0c;新增多项强大功能并优化操作体验&#xff0c;助力开发者更轻松地实现高质量的渲染效果与…

C# OpenCV机器视觉:模仿Halcon各向异性扩散滤波

在一个充满创意与挑战的图像处理工作室里&#xff0c;阿强是一位热情的图像魔法师。他总是在追求更加出色的图像效果&#xff0c;然而&#xff0c;传统的图像处理方法有时候并不能满足他的需求。 有一天&#xff0c;阿强听说了 Halcon 中的各向异性扩散滤波功能&#xff0c;它…

超详细的数据结构3(初阶C语言版)栈和队列。

文章目录 栈和队列1.栈1.1 概念与结构1.2 栈的实现 2. 队列2.1 概念与结构2.2 队列的实现 总结 栈和队列 1.栈 1.1 概念与结构 栈&#xff1a;⼀种特殊的线性表&#xff0c;其只允许在固定的⼀端进行插⼊和删除元素操作。进⾏数据插⼊和删除操作的⼀端称为栈顶&#xff0c;另…

利用邮件合并将Excel的信息转为Word(单个测试用例转Word)

利用邮件合并将Excel的信息转为Word 效果一览效果前效果后 场景及问题解决方案 一、准备工作准备Excel数据源准备Word模板 二、邮件合并操作步骤连接Excel数据源插入合并域预览并生成合并文档 效果一览 效果前 效果后 场景及问题 在执行项目时的验收阶段&#xff0c;对于测试…

一个基于ESP32S3和INMP441麦克风实现音频强度控制RGB灯带律动的代码及效果展示

一个基于ESP32S3和INMP441麦克风实现音频强度控制RGB灯带律动的代码示例&#xff0c;使用Arduino语言&#xff1a; 硬件连接 INMP441 VCC → ESP32的3.3VINMP441 GND → ESP32的GNDINMP441 SCK → ESP32的GPIO 17INMP441 WS → ESP32的GPIO 18INMP441 SD → ESP32的GPIO 16RG…

用户认证综合实验

实验需求 需求一&#xff1a;根据下表&#xff0c;完成相关配置 需求二&#xff1a;配置DHCP协议&#xff0c;具体要求如下 需求三&#xff1a;防火墙安全区域配置 需求四&#xff1a;防火墙地址组信息 需求五&#xff1a;管理员 为 FW 配置一个配置管理员。要求管理员可以通…

Curser2_解除机器码限制

# Curser1_无限白嫖试用次数 文末有所需工具下载地址 Cursor Device ID Changer 一个用于修改 Cursor 编辑器设备 ID 的跨平台工具集。当遇到设备 ID 锁定问题时&#xff0c;可用于重置设备标识。 功能特性 ✨ 支持 Windows 和 macOS 系统&#x1f504; 自动生成符合格式的…

linux部署node服务

1、安装nvm管理node版本 # 下载、解压到指定目录 wget https://github.com/nvm-sh/nvm/archive/refs/tags/v0.39.1.tar.gz tar -zxvf nvm-0.39.0.tar.gz -C /opt/nvm # 配置环境 vim ~/.bashrc~&#xff1a;这是一个路径简写符号&#xff0c;代表当前用户的主目录。在大多数 …

Kotlin实战经验:将接口回调转换成suspend挂起函数

在 Kotlin 协程中, suspendCoroutine 和 suspendCancellableCoroutine 是用于将回调或基于 future 的异步操作转换成挂起函数。 suspendCoroutine 用途:将回调式异步操作转换为可挂起函数 行为: 启动一个新的协程来处理基于回调的操作挂起当前协程,直到调用回调回调负责…