当前位置: 首页 > article >正文

【VUE3】练习项目——大事件后台管理

目录

0 前言

1 准备工作

1.1 安装pnpm

1.2 创建vue项目

1.3 Eslint & Prettier的配置

1.4 husky 提交代码检查

1.5 目录调整

1.6 VueRouter4

1.6.1 基础配置

1.6.2 路由跳转

1.7 引入 Element Plus 组件库

1.8 Pinia

1.8.1 优化 

1.9 封装请求工具

1.9.1 安装 axios 与配置框架

1.9.2 示例代码

2 开发


0 前言

黑马程序员视频地址:Vue3大事件项目-项目介绍和pnpm创建项目

接口文档:登录 - 黑马程序员-大事件 


1 准备工作

1.1 安装pnpm

官网:pnpm - 速度快、节省磁盘空间的软件包管理器 | pnpm中文文档 | pnpm中文网

安装pnpm命令:

npm i pnpm -g

pnpm创建vue项目命令:

pnpm create vue

命令对比: 

npmyarnpnpm
npm installyarnpnpm install
npm install axiosyarn add axiospnpm add axios
npm install axios -Dyarn add axios -Dpnpm add axios -D
npm uninstall axiosyarn remove axiospnpm remove axios
npm run devyarn devpnpm dev

1.2 创建vue项目

使用pnpm创建vue项目时,选择以下配置

请选择要包含的功能: (↑/↓ 切换,空格选择,a 全选,回车确认)
|  [ ] TypeScript
|  [ ] JSX 支持
|  [+] Router(单页面应用开发)
|  [+] Pinia(状态管理)
|  [ ] Vitest(单元测试)
|  [ ] 端到端测试
|  [+] ESLint(错误预防)
|  [+] Prettier(代码格式化)

标记:警告提示(待解决)

 创建完项目需要进入相应文件夹中,安装所有依赖

pnpm install

1.3 Eslint & Prettier的配置

见 【VUE3】Eslint 与 Prettier 的配置-CSDN博客

推荐使用里面的方案二,即将 prettier 的规则让 eslint 来执行

因为 1.4 中的检查代码需要 eslint 来检查


1.4 husky 提交代码检查

husky 是一个 git hooks 工具  ( git的钩子工具,可以在特定时机执行特定的命令 )

第一步:初始化仓库

git init

第二步:初始化 husky 工具配置

pnpm dlx husky-init; pnpm install

第三步:修改 .husky/pre-commit 文件

pnpm lint

但是这样会有一个问题! 

我们可以打开 package.json 文件,看到里面的 lint 命令对应为:

"lint": "eslint . --fix"

即默认进行的是全量检查,耗时问题,历史问题,因此需要再导入一个包 lint-staged :

第一步:安装

pnpm i lint-staged -D

第二步:配置 package.json 文件

{// ... 省略 ..."lint-staged": {"*.{js,ts,vue}": ["eslint --fix"]}
}{"scripts": {// ... 省略 ..."lint-staged": "lint-staged"}
}

第三步:修改 .husky/pre-commit 文件

pnpm lint-staged

这样就会只检查修改过的文件,哪怕以前提交的文件有问题,也不会检查报错

可以通过控制 1.3 中的那篇文章的第七节中的 'no-undef': 'off'来模拟提交以前有问题的文件


1.5 目录调整

删除默认文件后,增加 api 与 utils 文件夹

如果使用 sass,则需安装对应依赖

pnpm add sass -D

1.6 VueRouter4

更多内容见官网:Vue Router | Vue.js 的官方路由 

1.6.1 基础配置

import { createRouter, createWebHistory } from 'vue-router'// createRouter 创建路由实例,===> new VueRouter()
// 1. history模式: createWebHistory()   http://xxx/user
// 2. hash模式: createWebHashHistory()  http://xxx/#/user// vite 的配置 import.meta.env.BASE_URL 是路由的基准地址,默认是 ’/‘
// https://vitejs.dev/guide/build.html#public-base-path// 如果将来你部署的域名路径是:http://xxx/my-path/user
// vite.config.ts  添加配置  base: my-path,路由这就会加上 my-path 前缀了const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: []
})export default router

1.6.2 路由跳转

由于 setup 下,this 指向 undefined ,因此需要引入包创建 router 与 router 对象

<script setup>
import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
const gotoCart = () => {console.log(route)router.push('/individual')
}
</script><template><div>我是App</div><button @click="gotoCart()">跳转购物车页面</button>
</template>

1.7 引入 Element Plus 组件库

官方手册:一个 Vue 3 UI 框架 | Element Plus

安装组件库

pnpm install element-plus

按需引入:

第一步:安装插件

pnpm add -D unplugin-vue-components unplugin-auto-import

 第二步:把下列代码插入到你的 Vite 的配置文件中

import { defineConfig } from 'vite'
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: [// ...AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver()],}),],
})

全部引入此处不赘述 

注意:

1.在引入之后,无需任何配置,即可使用组件库内的组件

2.并且components下的vue组件也可以直接使用,无需导入


1.8 Pinia

见文档:【VUE3】Pinia-CSDN博客

注意:由于创建项目时勾选了Pinia,所以此处不需要再手动安装配置Pinia,直接可以使用

但是持久化还需手动配置,此处不再赘述

1.8.1 优化 

将 main.js 中关于 pinia 的代码抽离到 store/index.js 中,并且将 store/modules 中的所有仓库文件统一从 index.js 中导出,方便管理且简化代码 

// main.js
// ...
import pinia from './stores'// ...
app.use(pinia)// ...
// store/index.jsimport { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'const pinia = createPinia()
pinia.use(persist)export default piniaexport * from '@/stores/modules/user'
export * from '@/stores/modules/count'// 上面的代码等同于
// import { useUserStore, ... } from '@/stores/modules/user'
// export { useUserStore, ... }
// 组件.vueimport { useUserStore, useCountStore } from '@/stores'const userStore = useUserStore()
const userCount = useCountStore()

1.9 封装请求工具

手册:axios中文文档|axios中文网 | axios 

1.9.1 安装 axios 与配置框架

1.安装 axios

pnpm add axios

2.框架代码

// utils/request.jsimport axios from 'axios'const baseURL = 'http://big-event-vue-api-t.itheima.net'const instance = axios.create({// TODO 1. 基础地址,超时时间
})instance.interceptors.request.use((config) => {// TODO 2. 携带tokenreturn config},(err) => Promise.reject(err)
)instance.interceptors.response.use((res) => {// TODO 3. 处理业务失败// TODO 4. 摘取核心响应数据return res},(err) => {// TODO 5. 处理401错误return Promise.reject(err)}
)export default instance

1.9.2 示例代码

// utils/request.jsimport axios from 'axios'
import { useUserStore } from '@/stores'
import { ElMessage } from 'element-plus'
import router from '@/router'
const baseURL = 'http://big-event-vue-api-t.itheima.net'const instance = axios.create({// TODO 1. 基础地址,超时时间baseURL,timeout: 100000
})instance.interceptors.request.use((config) => {// TODO 2. 携带tokenconst userStore = useUserStore()if (userStore.token) {config.headers.Authorization = userStore.token}return config},(err) => Promise.reject(err)
)instance.interceptors.response.use((res) => {// TODO 3. 处理业务失败if (res.data.code === 0) {return res}ElMessage({ message: res.data.message || '服务异常', type: 'error' })// TODO 4. 摘取核心响应数据return Promise.reject(res.data)},(err) => {ElMessage({ message: err.response.data.message || '服务异常', type: 'error' })// TODO 5. 处理401错误if (err.response?.status === 401) {router.push('/login')}return Promise.reject(err)}
)export default instance

2 开发

2.1 路由配置

示例:采用 路由懒加载

// router/index.jsimport { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{ path: '/login', component: () => import('@/views/login/LoginPage.vue') },{path: '/',component: () => import('@/views/layout/LayoutContainer.vue'),redirect: '/article/manage',children: [{ path: '/article/manage', component: () => import('@/views/article/ArticleManage.vue') },{ path: '/article/channel', component: () => import('@/views/article/ArticleChannel.vue') },{ path: '/user/profile', component: () => import('@/views/user/UserProfile.vue') },{ path: '/user/avatar', component: () => import('@/views/user/UserAvatar.vue') },{ path: 'user/password', component: () => import('@/views/user/UserPassword.vue') }]}]
})export default router

记得准备路由出口,如:

// App.vue<template><router-view></router-view>
</template>

2.2 登录注册

2.2.1 静态页面

1.安装 element-plus 图标库

pnpm i @element-plus/icons-vue

2.静态结构准备

注意:登录页面与注册页面使用 v-if 与 v-else 控制切换

// views/login/LoginPage.vue<script setup>
import { User, Lock } from '@element-plus/icons-vue'
import { ref } from 'vue'
const isRegister = ref(true)
</script><template><el-row class="login-page"><el-col :span="12" class="bg"></el-col><el-col :span="6" :offset="3" class="form"><el-form ref="form" size="large" autocomplete="off" v-if="isRegister"><el-form-item><h1>注册</h1></el-form-item><el-form-item><el-input :prefix-icon="User" placeholder="请输入用户名"></el-input></el-form-item><el-form-item><el-input :prefix-icon="Lock" type="password" placeholder="请输入密码"></el-input></el-form-item><el-form-item><el-input :prefix-icon="Lock" type="password" placeholder="请输入再次密码"></el-input></el-form-item><el-form-item><el-button class="button" type="primary" auto-insert-space> 注册 </el-button></el-form-item><el-form-item class="flex"><el-link type="info" :underline="false" @click="isRegister = false"> ← 返回 </el-link></el-form-item></el-form><el-form ref="form" size="large" autocomplete="off" v-else><el-form-item><h1>登录</h1></el-form-item><el-form-item><el-input :prefix-icon="User" placeholder="请输入用户名"></el-input></el-form-item><el-form-item><el-inputname="password":prefix-icon="Lock"type="password"placeholder="请输入密码"></el-input></el-form-item><el-form-item class="flex"><div class="flex"><el-checkbox>记住我</el-checkbox><el-link type="primary" :underline="false">忘记密码?</el-link></div></el-form-item><el-form-item><el-button class="button" type="primary" auto-insert-space>登录</el-button></el-form-item><el-form-item class="flex"><el-link type="info" :underline="false" @click="isRegister = true"> 注册 → </el-link></el-form-item></el-form></el-col></el-row>
</template><style lang="scss" scoped>
.login-page {height: 100vh;background-color: #fff;.bg {background:url('@/assets/logo2.png') no-repeat 60% center / 240px auto,url('@/assets/login_bg.jpg') no-repeat center / cover;border-radius: 0 20px 20px 0;}.form {display: flex;flex-direction: column;justify-content: center;user-select: none;.title {margin: 0 auto;}.button {width: 100%;}.flex {width: 100%;display: flex;justify-content: space-between;}}
}
</style>

2.2.2 规则校验

官方文档:Form 表单 | Element Plus

四大校验方式:

        1.非空校验:required

        2.长度校验:min、max

        3.正则校验:pattern

        4.自定义校验 :validator

第一步:声明表单数据对象与规则对象,其中表单数据对象必须是响应式的 

const formData = ref({username: '',password: '',repassword: ''
})
const formRules = {username: [{ required: true, message: '用户名不能为空!', trigger: 'blur' },// blur是失去焦点事件{ min: 5, max: 10, message: '用户名必须为5-10位字符', trigger: 'blur' }],password: [{ required: true, message: '密码不能为空!', trigger: 'blur' },{ pattern: /^\S{8,15}$/, message: '密码必须为8-15位非空字符', trigger: 'change' }// change为改变时校验,发现当检验提示错误后,若触发失焦事件,会导致提示消失,因此不推荐]
}

第二步:给整个表单的大标签绑定数据对象与规则对象

<el-form
...
:model="formData"
:rules="formRules"
>
<!-- ... -->
</el-form>

第三步:给输入框绑定数据,并且给表单元素标签绑定要使用的规则

<el-form-item prop="username">    ❗<el-input:prefix-icon="User"placeholder="请输入用户名"v-model="formData.username"    ❗></el-input>
</el-form-item>

自定义校验方式:

使用方式相同,只是配置规则时,validator 指向一个函数

参数:

        rule:当前校验规则相关的信息

        value:所校验的表单元素目前的表单值

        callback:无论成功还是失败,都需要 callback 回调

const formRules = {// ...repassword: [{validator: (rule, value, callback) => {if (value !== formData.value.password) {callback(new Error('两次密码不一致,请重新输入!'))} else {callback()}},trigger: 'blur'}]
}

2.2.3 表单预校验

由于vue3的特性,即导入的组件内的方法默认不会暴露,因此需要获取组件对象,然后再获取,如:

第一步:获取组件对象

详细见 【VUE3】组合式API-CSDN博客 中的 9.2

const form = ref()
<el-form
ref="form"    ❗
size="large"
autocomplete="off"
v-if="isRegister"
:model="formData"
:rules="formRules"
>

第二步:调用 validate 方法

validate 方法即对整个表单的内容进行验证,接收一个回调函数,或返回 Promise

const register = async () => {await form.value.validate()    ❗await userRegisterService(formData.value)    // 这个是提交数据apiElMessage.success('注册成功!')isRegister.value = false    // 切换登录
}

注意:因为之前我们设置了插件来帮我们自动导入Element组件,所以上述代码中的ElMessage方法我们没有导入,但是eslint会报错,可以在 eslint.config.js 中来配置,让其不报错,位置及代码如下:

// ...export default defineConfig([// ...{rules: {// ...'vue/no-setup-props-destructure': ['off'], // 放在这个下面globals: {ElMessage: 'readonly',ElMessageBox: 'readonly',ElLoading: 'readonly'}}},
])

2.2.4 封装注册api

// api/user.jsimport request from '@/utils/request'export const userRegisterService = ({ username, password, repassword }) =>request.post('/api/reg', { username, password, repassword })

调用见 2.2.3 


持续更新

相关文章:

【VUE3】练习项目——大事件后台管理

目录 0 前言 1 准备工作 1.1 安装pnpm 1.2 创建vue项目 1.3 Eslint & Prettier的配置 1.4 husky 提交代码检查 1.5 目录调整 1.6 VueRouter4 1.6.1 基础配置 1.6.2 路由跳转 1.7 引入 Element Plus 组件库 1.8 Pinia 1.8.1 优化 1.9 封装请求工具 1.9.1 安…...

kylin系统软件移植部署过程中遇到的问题及解决方案

有一个跨平台的c++软件,基于qt,boost,zmq,kafka等库,使用cmake脚本管理构建。在windows下和ubuntu下都能正常编译。在部署到kylin系统下时,遇到了一些问题。记录一下解决过程。 KYLIN 操作系统部署 c++开发环境: 安装了git,ninja,qt,boost等编译必要软件。因为之前…...

万字长篇————C语言指针学习汇总

经过一段时间的学习&#xff0c;我们已经接触到了C语言的很多知识了。不过目前我们接下来我们要接触C语言中一个最大的“门槛”&#xff1a;指针。 什么是指针&#xff1f; 在介绍指针之前&#xff0c;我们首先要明白变量与地址之间的关系。 举一个生活中的案例&#xff1a;一…...

实验一 HDFS的Shell操作

一、实验目的 熟悉HDFS Shell的语法格式&#xff0c;完成对HDFS上文件和目录的一系列操作 二、实验要求 2.1 练习dfs常用的子命令 ① -ls ② -du ③ -mv ④ -cp ⑤ -rm ⑥ -put ⑦ -cat ⑧ -help ⑨ -mkdir ⑩ -get 2.2通过Shell脚本定时采集数据到HDFS 三、实…...

复变函数摘记3

复变函数摘记3 5. 留数5.1 可去奇点、极点、本性奇点5.2 零点与极点的关系5.3 在无穷远点处的情形5.4 留数 5. 留数 \quad 如果函数 f ( z ) f(z) f(z) 在 z 0 z_0 z0​ 及 z 0 z_0 z0​ 的邻域内处处可导&#xff0c;那么称 f ( z ) f(z) f(z) 在点 z 0 z_0 z0​ 处解析。…...

【行测】判断推理:类比推理 and 定义判断

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;读不在三更五鼓&#xff0c;功只怕一曝十寒。 > 目标&#xff1a;掌握 类比推理 and 定义判断 基本题型&#xff0c;并能运用到例题中。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会…...

Java使用WebSocket视频拆帧进度处理与拆帧图片推送,结合Apipost进行调试

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>Configuration public class WebSocketConfig {/*** 启动 WebSocket 服务器*/Beanpublic ServerEndpointE…...

计算斐波那契数列

1.对于斐波那契数列的理解&#xff1a; (1)常规 该数列由兔子繁衍的想法产生&#xff0c;故又“兔子数列” 其数值为&#xff1a;1、1、2、3、5、8、13、21、34 从数学定义上走&#xff1a;F(0)1&#xff0c;F(1)1, F(n)F(n - 1)F(n - 2)&#xff08;n ≥ 2&#xff0c;n ∈…...

JAVA如何操作文件?(超级详细)

目录 一、认识文件和相关知识 1.认识文件 2.⽬录 3.⽂件路径&#xff08;Path&#xff09; 4.文本文件和二进制文件的区分 二、File类操作文件 1.构造方法 2.方法 2.1 方法表 2.2 get相关的方法和构造方法 2.2.1 “.” 和 “..” 2.3 is相关的方法 2.4 删除相关…...

(2)VTK C++开发示例 --- 绘制多面锥体

文章目录 1. 概述2. CMake链接VTK3. main.cpp文件4. 演示效果 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;VTK开发 &#x1f448; 1. 概述 VTK C开发示例程序&#xff1b; 使用C 和VTK绘制一个多面锥体。 环境说明系统ubuntu22.04、windows11cmake3.22、3.2…...

(2025-04-12)向老主机箱中安装新买的显卡及固态硬盘

目录 1 引言2 显卡及其驱动的安装3 固态硬盘的安装及C盘扩容3.1 固态硬盘正确连接到主板上后&#xff0c;操作系统上面仍然不显示对应盘符怎么办&#xff1f;3.2 如何对C盘扩容&#xff1f;3.3 新问题&#xff1a;原有D盘程序不能运行 4 总结 1 引言 今天安装昨天买的新固态硬…...

rk3588 驱动开发(一)字符设备开发

3.字符设备驱动开发 3.1 什么是字符设备驱动 字符设备&#xff1a;就是一个个字节&#xff0c;按照字节流进行读写操作的设备&#xff0c;读写是按照先后顺序的。 举例子&#xff1a;IIC 按键 LED SPI LCD 等 Linux 应用程序调用驱动程序流程&#xff1a; Linux中驱动加载成功…...

AbMole| 体内相互作用筛选揭示肝脏对癌症转移的限制

癌症转移&#xff0c;作为导致患者死亡的主要原因之一&#xff0c;其复杂机制一直是医学界研究的热点。肝脏&#xff0c;作为癌症转移的常见靶器官&#xff0c;其微环境对癌症细胞的生长和转移具有重要影响。然而&#xff0c;肝脏如何限制癌症转移的具体机制尚不完全清楚。 来…...

STM32移植文件系统FATFS——片外SPI FLASH

一、电路连接 主控芯片选型为&#xff1a;STM32F407ZGT6&#xff0c;SPI FLASH选型为&#xff1a;W25Q256JV。 采用了两片32MB的片外SPI FLASH&#xff0c;电路如图所示。 SPI FLASH与主控芯片的连接方式如表所示。 STM32F407GT6W25Q256JVPB3SPI1_SCKPB4SPI1_MISOPB5SPI1_MOSI…...

2025年第十六届蓝桥杯省赛JavaB组真题回顾

第16届蓝桥杯省赛已经结束了&#xff0c;第一次参加也是坐牢了4个小时&#xff0c;现在还是来总结一下吧&#xff08;先声明以下的解法&#xff0c;大家可以当作一种思路来看&#xff0c;解法不一定是正解&#xff0c;只是给大家提供一种能够正常想到的思路吧&#xff09; 试题…...

Android 接口定义语言 (AIDL)

目录 1. 本地进程调用(同一进程内)2. 远程进程调用(跨进程)3 `oneway` 关键字用于修改远程调用的行为Android 接口定义语言 (AIDL) 与其他 IDL 类似: 你可以利用它定义客户端与服务均认可的编程接口,以便二者使用进程间通信 (IPC) 进行相互通信。 在 Android 上,一个进…...

c# 数据结构 链表篇 有关双向链表的一切

本人能力有限,如有不足还请斧正 目录 0.双向链表的好处 1.双向链表的分类 2.不带头节点的标准双向链表 节点类:有头有尾 链表类:也可以有头有尾 也可以只有头 增 头插 尾插 删 查 改 遍历 全部代码 3.循环双向链表 节点类 链表类 增 头插 尾插 删 查 遍历…...

Debian服务器挂载外部存储设备的完整指南

在 Debian 系统中挂载外部存储设备(如 U 盘、移动硬盘、SSD)是服务器运维和桌面使用中非常常见的操作。本文将为你详细拆解从识别设备、格式化到手动/自动挂载的全过程&#xff0c;适合新手到进阶用户参考。 一、准备阶段&#xff1a;插入存储设备并识别 1. 插入外部设备后查看…...

660 中值定理

文章目录 前言168169170总结 前言 background music: 《代替》 张叶蕾 660 上面没有专门的中值定理章节&#xff0c;我蒙了。不过应该可以找一下。就是证明题&#xff0c;标志性应该还行。找一下。然后做一下。660 的题质量应该还是非常高的。但是积分中值定理&#xff0c;还有…...

Elasticsearch:AI 助理 - 从通才到专才

作者&#xff1a;来自 Elastic Thorben Jndling 在 AI 世界中&#xff0c;关于构建针对特定领域定制的大型语言模型&#xff08;large language models - LLM&#xff09;的话题备受关注 —— 不论是为了更好的安全性、上下文理解、专业能力&#xff0c;还是更高的准确率。这个…...

数据结构——布隆过滤器

目录 一、什么是布隆过滤器&#xff1f; 二、布隆过滤器的原理 三、布隆过滤器的特点 一、什么是布隆过滤器&#xff1f; 布隆过滤器是一种空间效率高、适合快速检索的数据结构&#xff0c;用于判断一个元素是否可能存在于一个集合中。它通过使用多个哈希函数和一个位数组来…...

时间的重构:科技如何重塑人类的时间感知与存在方式

时间是人类认知的基石&#xff0c;也是科技发展的终极命题。从石英钟到量子计时器&#xff0c;从日晷到区块链时间戳&#xff0c;技术不断重构着我们对时间的理解与利用。然而&#xff0c;当人工智能、量子计算和脑机接口等前沿技术开始挑战时间的线性本质时&#xff0c;我们不…...

悄悄话识别、 打电话识别、攀高识别三种识别算法

在摄像头正对场景下,悄悄话识别(唇语识别)、打电话识别和攀高识别是三种典型的行为检测技术。以下从技术原理、算法模型、应用场景及挑战等方面进行详细分析: 一、悄悄话识别(唇语识别) 技术原理 唇语识别通过分析嘴唇的几何特征(形状、开合程度、运动轨迹)和动态变化…...

docker多架构镜像构建

docker多架构镜像构建 Docker 多架构镜像构建&#xff08;Multi-Architecture Image Build&#xff09;允许你为不同平台&#xff08;如 linux/amd64, linux/arm64, linux/arm/v7 等&#xff09;构建和推送统一的镜像标签&#xff0c;解决在不同硬件架构之间部署的问题。 Doc…...

机器学习常用算法总结

1. 概述 机器学习的定义是对于某类任务T和性能度量P&#xff0c;如果一个计算机程序在T上其性能P随着经验E而自我完善&#xff0c;那么我们就称这个系统从经验E中学习&#xff0c;机器学习是人工智能的一种方法&#xff0c;它通过在大量数据中学习隐藏的规则&#xff0c;模式和…...

软件架构设计:MVC、MVP、MVVM、RIA 四大风格优劣剖析

MVC、MVP、MVVM 和 RIA 都是软件架构中常见的设计风格&#xff0c;以下是对它们的详细介绍&#xff1a; 一、MVC 架构风格&#xff08;Model - View - Controller&#xff09; 1.简介&#xff1a;MVC 架构风格将软件应用程序分为三个核心部分&#xff0c;通过这种划分来分离不…...

Android12 自定义系统服务

在Android中可以通过两种方式创建系统服务: 由SystemServer启动的系统服务,使用SystemServer线程资源,适合轻量级的服务,比如各种XMS服务;占用独立进程,在系统启动时,由init进程拉起,比如SurfaceFlinger;本文采用的是第一种方式。 自定义AssistantManagerService 参…...

Flink SQL SavePoint最佳实践

以下是 Flink SQL Savepoint 最佳实践&#xff0c;涵盖配置、触发、恢复及注意事项&#xff0c;高效管理作业状态&#xff1a; 一、Savepoint 的配置与触发 1. 基础配置 存储路径&#xff1a;在 flink-conf.yaml 中全局设置 Savepoint 存储目录&#xff0c;避免每次手动指定路…...

【STM32】在FreeRTOS下使用硬件SPI收发数据出现的时序耦合问题(WK2124芯片为例)

问题 STM32中在Freertos使用SPI通讯芯片 WK2124进行SPI转4串口时&#xff0c;接收数据为一个任务&#xff0c;发送数据为一个任务&#xff0c;切接受任务优先级更高实测发现收发一段时间&#xff08;约几分钟&#xff09;外扩芯片会死锁导致WK2124复位。 分析 首先&#xff…...

关于香橙派OrangePi 5 Ultra 这个开源板子,开发Android

我下载了它资料中的开源Android13 系统SDK&#xff0c; 这个SDK连个git 都没有&#xff0c;把这种代码释放能称为开源吗&#xff1f;&#xff1f; 并且也就是说你买了这个板子&#xff0c;里面是没有任何关于RK3588的开发文档&#xff0c;如果你没玩过其他RK平台&#xff0c;估…...