从0到1建立前端规范

news2024/11/25 20:35:11
本文适合打算建立前端规范的小伙伴阅读
一、为什么需要规范

规范能给我们带来什么好处,如果没有规范会造成什么后果?这里主要拿代码规范来说。

统一代码规范的好处:

  1. 提高代码整体的可读性、可维护性、可复用性、可移植性和可靠性,这会从根本上降低开发成本,也是最重要的一点。
  2. 保证代码的一致性:软件系统中最重要的因素之一就是编码的一致性。如果编码风格一致,也更加易于维护,因为团队内任何人都可以快速理解并修改。
  3. 提升团队整体效率:开发人员通常需要花费大量的时间来解决代码质量问题,如果都按照规范编写,也有助于团队尽早发现问题,甚至完全预防问题,这将提高整个交付过程的效率。
  4. 减少code review期间一系列的争议,因为缺乏标准,在争议过程中双方很难妥协(没少因为这事争论过😕)。

若不统一代码规范,可能会造成的后果:

  1. 由于缺乏规范,导致代码风格不一,增加团队成员间的心理负担,极端情况下,某段代码只有某个人能修改(俗称屎山💩)。
  2. 团队间协作更加困难:因为开发人员得适应不同的风格,会导致效率低下(阅读代码是我们花费时间最多的地方)。
  3. 在code review期间可能经常为类似的事情做过多的讨论。
  4. 影响团队的生产力和质量,严重的甚至会影响团队和谐。

二、为什么依然有很多团队缺乏规范

在这件事上,很难达成一致是我认为最重要的原因。并且,仅仅只是拥有规范也是不够的:

  • 当开发人员被要求在短时间内完成任务时,通常会回避质量标准。
  • 团队中总是有一些有个性的人不会为了团队去改变自己的习惯。
  • 有些人在会议上就约定达成了一致,在会下依旧我行我素。

三、如何保持规范

我曾想通过会议讨论的方式来制定规范,但效果却差强人意。将失败的原因总结为大致几点:

  1. 在会议中,思维很容易发散,经常出现的情况是讨论了很多,却很难有实际性的成效,在开发中依然有不少人选择无视规则
  2. 正式的会议往往很难组织,大家很难一起有空闲的时间来讨论,一次/两周 都很困难。
  3. 会议中对实际案例分析,提出若干点优化建议后,没有对问题的优先级和侧重点进行划分,导致实际效果并不好。
  4. 还有一点也是我自己的原因,组织会议的能力有待提升…😭

经历了上述的挫败之后,经过反复复盘总结,决定换一种方式来执行:

  1. 对规范问题进行归纳分析并通过文档记录(wiki等),在团队内进行统一。
  2. 采用小步快跑的方式,有问题就解决问题,按照优先级和重要性进行排序划分,依次将问题纳入迭代,每个迭代重点解决其中几个即好。
  3. 本迭代的规范问题绝不留到下个迭代,防止堆积(当然,有时候还是得向项目经理妥协😮‍💨)。
  4. 在code review过程中严格把关,拒绝睁一只眼👀闭一只眼🧐。
  5. 当团队成员对具体某个规范有争议时,及时讨论并定出结论。
  6. 没有规则只是为了规则,制定规范的目的并不是一定要按照某某标准来执行,更多的是团队成员达成一致即可。
  7. 鼓励大家大胆的质疑规则,若不能提高代码的可读性,可维护性,可复用性,可移植性和可靠性的规则都应该被受到质疑。

四、开发者需要建立和遵守的规范

大致可以划分成这几个方向:

  • 开发流程规范
  • 代码规范
  • git commit规范
  • 项目文件结构规范
  • UI设计规范
开发流程规范

这里可能有小伙伴有疑问了,开发流程规范不是项目经理定的吗🤔️,跟我有什么关系?

这里想告诉大家的是,开发流程在一定程度上应该是由我们自己来掌控。不管是传统开发的模式还是敏捷开发的模式,对于开发者来说核心依旧是高质高效的完成用户提出的需求

笔者曾见过不少开发者在拿到产品经理的需求后就开始急匆匆的写代码,以此来体现他们的高效,但往往却因为需求理解不到位和前期代码欠缺设计导致bug率高和返工。

如何找到适合自己的开发流程是需要依靠经验来支撑的,需要反复总结和思考,最终达到高质高效完成的目的。

说一说笔者自己比较喜欢的开发流程:

在这里插入图片描述

在接收到需求后应第一时间去了解这个需求的背景是什么?这么做到底有没有解决用户的痛点?或者说用户更深层次的需求是什么?如果团队的产品经理经验不丰富,往往可以在这个阶段砍掉很多不合理的需求(这一点真的很重要)

对于复杂大功能往往还需要进行技术方案调研技术方案设计,并输出详细的设计文档。涉及到细节上,则需要将数据流走向、组件设计等通过脑图的形式呈现出来。

代码规范之格式化规范

由于每个开发者的IDE( 集成开发环境: 用于提供程序开发环境的应用程序,是集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套)不同,即使IDE相同也会因为每个人的配置不一样导致格式化的结果不一样。如何确保团队内开发人员采用统一的格式化配置呢?

这里给推荐大家使用 prettier,它内置了一套格式化的规则,具体配置:

  1. 安装依赖:
npm install --save-dev --save-exact prettier 
// or
yarn add --dev --exact prettie
  1. 创建一个空配置文件,让编辑器和其他工具知道你正在使用 Prettier:
echo {}> .prettierrc.jso
  1. 创建一个.prettierignore文件,让 Prettier CLI 和编辑器知道哪些文件不能格式化,example:
# Ignore artifacts:
dist
build
coverag
  1. 配置编辑器(VScode为例)

    IDE中安装 Prettier-Code Formater 插件:

在这里插入图片描述

找到IDE中设置模块,搜索format On Save,勾上这个就可以了。
在这里插入图片描述

现在当我们 Ctrl + S 保存代码时,插件就会帮助我们自动格式化了

这里有小伙伴要问了,要是有人将没有格式化的代码提交上去怎么办?

这时候就需要在 git commit 的阶段自动将提交的代码进行格式化,这里我们借助工具 husky,它主要可以帮助我们在 git 阶段检查提交消息、运行测试、检查代码等。没接触过的小伙伴可以去官网了解一下,配置如下:

  • 安装 husky 和 lint-staged:
 ```js
 npm install --save-dev husky lint-staged
 npx husky install
 npm set-script prepare "husky install"
 npx husky add .husky/pre-commit "npx lint-staged"
 // or
 yarn add --dev husky lint-staged
 npx husky install
 npm set-script prepare "husky install"
 npx husky add .husky/pre-commit "npx lint-staged
 ```
  • 然后将以下内容添加到package.json中:
 ```js
 {
   "lint-staged": {
     "**/*": "prettier --write --ignore-unknown"
   }
 }
 ```

​ 这段配置的意思是:当执行 git commit 阶段前,先执行lint-stagedlint-staged中的内容就是对暂存区的文件执行格式化的命令。

其他:若使用的是脚手架工具搭建的项目,会自带eslint配置(`eslintConfig`)。`prettier 和 eslint 会有一些配置上的冲突`,这个时候需要安装eslint-config-prettier 以使 ESLint 和 Prettier 相互配合,安装完后在`.eslintrc`中配置(以Create-React-App为例): 
"eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest",
      "prettier"
    ]
  }
这样就可以用`"prettier"`的部分规则覆盖前面的规则,让它们都能正常工作。 

代码规范之JS/TS规范

JS/TS主流的大致有这几种:

  • Airbnb JavaScript Style Guide
  • Google JavaScript Style Guide
  • Idiomatic JavaScript Style Guide
  • JavaScript Standard Style Guide
  • jQuery JavaScript Style Guide

比较推荐使用 Airbnb JavaScript Style Guide,它在 Github 上足有 12万 star,几乎覆盖了 JavaScript 的每一项特性。

具体配置:

  • 安装依赖
npm install eslint --save-dev
// or
yarn add eslint --dev
  • 生成配置文件
npm init @eslint/config
// or
yarn create @eslint/config

跟着终端中的提示,按照自身需求一步步选择即可。

有了具体的规范后,我们同样需要使用工具去约束:还是通过在git commit阶段校验,若不通过则取消提交。

配置(还是在 package.json 中的 lint-staged

 "lint-staged": {
    "**/*": "prettier --write --ignore-unknown", //格式化
    "src/*": "eslint --ext .js,.ts,.tsx"  //进行eslint校验
  }

注意:这里如果选用的Typescript,则会默认使用@typescript-eslint/parser解析器,官方为了追求更快的解析速度,并不会对.ts文件中的类型进行检查,只会做语法检测。

如果需要对类型也进行检测,需要在extends中加上plugin:@typescript-eslint/recommended-requiring-type-checking。

索性这里换了另一种方式:在pre commit 中执行yarn run tsc,这里的意思是对项目中ts文件进行类型检测,默认会读取根目录中的tsconfig.json配置。

这种方式并不完美,它的弊端就在于全量检测,如果项目不大还好,若是项目代码量够多,检测10-20s也是常有的事。

代码规范之CSS规范

CSS检查代码规范使用 stylelint 插件,规范则推荐使用 stylelint-config-standard:

  • 安装
```js
npm install --save-dev stylelint stylelint-config-standar
```
  • 在项目的根目录中创建一个配置文件.stylelintrc.json,内容如下:
```js
{
  "extends": "stylelint-config-standard"
}
```
  • 解决与prettier配置的冲突:
```js
npm install --save-dev stylelint-config-prettier
```
  • 将下面配置复制到.stylelintrc.json中:

    {
      "extends": ["stylelint-config-standard", "stylelint-config-prettier"]
    }
    
  • 在 git commitv阶段进行检测:

```js
"lint-staged": {
    "**/*": "prettier --write --ignore-unknown", //格式化
    "src/**.{js,jsx,ts,tsx}": "eslint --ext .js,.jsx,.ts,.tsx", //对js文件检测
    "**/*.{less,css}": "stylelint --fix" //对css文件进行检测
  },
```

代码规范之自定义其他规范

下面列一些团队内定的其他规范:

  1. 命名规范

    变量的命名中应尽量减少缩写的情况发生,做到见名知意。

 ```js
 // 👎 自我感觉良好的缩写:
 let rContent = 'willen'; 
 
 // 👍 无需对每个变量都写注释,从名字上就看懂
 let firstName = 'jackie'; 
 
 // 👎 从命名无法知道返回值类型
 function showFriendsList() {....} // // 无法辨别函数意图,返回的是一个数组,还是一个对象,还是true or false?
 
 // 👍 明确函数意图,对于返回true or false的函数,最好以should/is/can/has开头
 function shouldShowFriendsList() {...}
 function isEmpty() {...}
 function canCreateDocuments() {...}
 function hasLicense() {...}
 function sendEmailToUser(user) {.... } //动词开头,函数意图就很明
 ```
  1. 写注释

    在每个文件的顶部明确说明该组件做什么,有没有业务理解难点等等,对业务特殊函数/变量也需要写注释

 ```js
 /**
  * 导航页面-右边区域
  */
  
 const Content=>()=>xxx
  
 const MAX_INPUT_LENGTH = 8; //用于限制密码输入框
 
 function Component(props) {
   return (
     <>
       {/* 如果用户没有订阅则不展示广告 */}
       {user.subscribed ? null : <SubscriptionPlans />}
     </>
   )
 }
 ```
  1. 变量兜底
 ```js
 // 👎 对于求值获取的变量,没有兜底
 const { data } = getApiRequest();
 data.map((s) => s.id); //没有考虑data异常的情况,代码一跑就爆炸
 
 // 👍 对于求值变量,做好兜底
 const { data = [] } = getApiRequest();
 data.map((s) => s?.id); //没有考虑data异常的情况,代码一跑就爆炸
 ```
  1. 辅助函数必须是纯函数
 ```js
 // 👎 不要让功能函数的输出变化无常
 function plusAbc(a, b, c) {  // 这个函数的输出将变化无常,因为api返回的值一旦改变,同样输入函数的a,b,c的值,但函数返回的结果却不一定相同。
   var c = fetch('../api');
   return a+b+c;
 }
 
 // 👍 功能函数使用纯函数,输入一致,输出结果永远唯一
 function plusAbc(a, b, c) {  // 同样输入函数的a,b,c的值,但函数返回的结果永远相同。
   return a+b+c;
 }
 ```
  1. 优先使用函数式编程
 ```js
 // 👎 使用for循环编程
 for(i = 1; i <= 10; i++) {
    a[i] = a[i] +1;
 }
 
 // 👍 使用函数式编程
 let b = a.map(item => ++item
 ```
  1. 优先使用函数式组件

    除非需要用到错误边界,否则函数式组件应该是首选方法。

  2. 组件复杂度

 如果一个组件做的事情太多,应适当提取一些逻辑,将其拆分为更小的组件。

 如果提取的组件很复杂,则需要依照一定的规则和条件一一提取它。

 代码行数并不是一个客观的衡量标准,更多是需要考虑责任划分和抽象。
  1. 用错误边界

    当需要对大量数据进行渲染处理时,需要通过错误边界组件对其进行降级处理。

 ```js
 function Component() {
   return (
     <Layout>
       <ErrorBoundary>
         <CardWidget />
       </ErrorBoundary>
 
       <ErrorBoundary>
         <FiltersWidget />
       </ErrorBoundary>
 
       <div>
         <ErrorBoundary>
           <ProductList />
         </ErrorBoundary>
       </div>
     </Layout>
   )
 }
 ```
  1. props参数传递

    props一层层传递一直是我们很头疼的一个问题,最核心的问题是不清楚props是从哪个初始组件传来的,以及props中到底有哪些东西,上下文是什么?

    因此对于传递较深的场景我推荐直接使用 context,对于 props 中的内容和上下文通过 TS 来解决。

 ```js
 // A.tsx
 interface AProps {
   param: string;
 }
 const A = ({ param }: AProps) => {
   return <B param = {param} />;
 };
 
 // 👍 上下文清晰
 // B.tsx
 const B = ({ param }: { param: AProps['param'] }) => {
   return <div>hello world</div>;
 };
 ```
  1. props传参数量

    如果超过 5 个props,就该考虑是否拆分该组件。在某些情况下,这是需要对组件进行重构的标志。

    注意:组件使用的props越多,重新渲染的理由就越多。

  2. 避免嵌套三元运算符

    三元运算符在第一级之后变得难以阅读,虽然看起来节省了代码空间,但最好在代码中明确意图,保持良好的阅读性。

  ```js
  // 👎 不够清晰,要是再嵌套一层两层呢
  isSubscribed ? (
    <ArticleRecommendations />
  ) : isRegistered ? (
    <SubscribeCallToAction />
  ) : (
    <RegisterCallToAction />
  )
  
  // 👍 将判断逻辑进行拆分
  function CallToActionWidget({ subscribed, registered }) {
    if (subscribed) {
      return <ArticleRecommendations />
    }
  
    if (registered) {
      return <SubscribeCallToAction />
    }
  
    return <RegisterCallToAction />
  }
  
  function Component() {
    return (
      <CallToActionWidget
        subscribed={subscribed}
        registered={registered}
      />
    )
  }
  ```
  1. 将列表组件封装成独立组件
  ```js
  // 👎 列表渲染和其他逻辑杂糅在一起
  function Component({ topic, page, articles, onNextPage }) {
    return (
      <div>
        <h1>{topic}</h1>
        {articles.map(article => (
          <div>
            <h3>{article.title}</h3>
            <p>{article.teaser}</p>
            <img src={article.image} />
          </div>
        ))}
        <div>You are on page {page}</div>
        <button onClick={onNextPage}>Next</button>
      </div>
    )
  }
  
  // 👍 将列表组件提取出来,一目了然
  function Component({ topic, page, articles, onNextPage }) {
    return (
      <div>
        <h1>{topic}</h1>
        <ArticlesList articles={articles} />
        <div>You are on page {page}</div>
        <button onClick={onNextPage}>Next</button>
      </div>
    )
  }
  ```
  1. 避免嵌套渲染函数
  ```js
  // 👎 不要将其定义在渲染函数组件中
  function Component() {
    function renderHeader() {
      return <header>...</header>
    }
    return <div>{renderHeader()}</div>
  }
  
  // 👍 将其抽离到独立的组件中去
  import Header from '@modules/common/components/Header'
  
  function Component() {
    return (
      <div>
        <Header />
      </div>
    )
  }
  ```
  1. 组件/函数导入导出
  ```js
  // 👍 在文件头部导入,顺序依次为: 第三方库 > 公共组件/方法 > 非公共部分组件/方法
  import React from 'react'
  import _ from 'loadsh'
  import Header from '@components/header'
  import Content from './Content'
  
  // 👍 在底部导出
  export { Content, Header }
  export default Componen
  ```

项目文件结构规范

在项目初期若不重视,到了后期就是到处天马行空,你很难在期望的目录下找到你想要的文件。

文件夹名称全部采用小写 + “-” 来隔开,index.ts更多是用来做导出作用,要不然最后编辑器中满屏的index.tsx,很难区分。

 - src 开发目录
      - pages 视图
          - module-a 模块A
            - components 私有组件
              - ComA.tsx
              - ComB.tsx
            - index.module.less
            - index.tsx
            - Content.tsx
          - module-b 模块B
      - components 公共组件
        - index.ts 导出所有组件
        - header
          - index.tsx
          - index.module.less
          - User.tsx
          - useGetBaseInfo.hooks.ts
      - routers 路由文件
      - store redux中的数据
      - utils 这里是以utils为后缀
        - index.ts
        - a.utils.ts
        - b.utils.ts
      - hooks 这里是以hooks为后缀
        - index.ts
        - a.hooks.ts
        - b.hooks.ts
      - styles 静态资源文件
      - service api请求,这里是以api为后缀
        - a.api.ts 按照后端微服务进行划分
        - b.api.ts
      - constans 常量

通过对工具函数、hooks、api 等加上后缀,更加容易区分引入的文件。

Git commit规范

git commit 规范主要可以帮助开发人员在 code review 期间更容易理解提交的内容,现在大部分主流 commit 规范都是基于Angular 团队的规范而衍生出来的,它的 message 格式如下:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer

每个提交消息都包含一个subject、一个body和一个footer (中间使用空行分割),提交信息的任何一行不能超过 100 个字符。

👉 type主要有以下几种类型:

  • feat: 一个新特性
  • fix: 修复bug
  • docs: 文档修改
  • style: 不影响代码含义的更改(空格、格式、缺少分号等)
  • refactor: 代码重构
  • perf: 优化性能
  • test: 测试用例修改
  • chore: 对构建过程或辅助工具和库的更改,例如文档生成

👉 scope:可以是影响范围的任何内容。

👉 subject:包含对更改的简洁描述,规则:

  • 使用陈述语句
  • 第一个字母不要大写
  • 末尾没有点 (.)

👉 body:commit 具体修改内容, 可以分为多行,应该包括改变的动机,并与以前的行为进行对比。

👉 footer: 一些备注, 通常是修复的 bug 的链接。

截取一张开源库的 commit,example:
在这里插入图片描述

有了规范后,我们需要通过工具去约束:commitlint。它要做的就是在我们每次提交 git commit 的时候,都会帮我们检查 commit message 是否符合一定的规范,如果不符合,就让这次提交失败。

具体配置:

# 安装 commitlint cli 和 conventional config
npm install --save-dev @commitlint/{config-conventional,cli}
# Windows:
npm install --save-dev @commitlint/config-conventional @commitlint/cli

配置要使用的 commitlint 规则
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

加入到husky中:
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'
or
yarn husky add .husky/commit-msg 'yarn commitlint --edit $1

UI设计规范

优秀的开发者应该反向推动UI的规范,并且能够支撑UI规范的落地。

UI 规范的最大好处就是能够提质提效:

  • 在开发者的角度,与设计规范同步形成研发资产,避免重复造轮子;
  • 在测试的角度,能够避免重复的无意义走查;
  • 在UI设计师的角度,减少设计成本,提高设计效率,可以快速承接新需求;
  • 站在产品角度,提高产品迭代与优化效率,降低试错成本;
  • 站在用户角度,解决用户体验一致性。

那到底应该怎么去推动UI规范?我的做法是先让设计师去给出一系列的规范,没有相关规范就拉上产品经理一起制定规范。然后前端建立一套自己的组件库,再将组件库提供给UI设计师,以此来相互监督是否达成了规范协议。

五、总结

统一规范的最根本目的是为了保证团队成员的一致性,从而减少沟通成本,提高开发效率。

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

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

相关文章

Java制作“简易王者荣耀”小游戏

第一步是创建项目 项目名自拟 第二部创建个包名 来规范class 然后是创建类 GameFrame 运行类 package com.sxt;import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; im…

圆通速递单号查询入口,以表格的形式导出详细物流信息

批量查询圆通速递单号的物流信息&#xff0c;并以表格的形式导出单号的详细物流信息。 所需工具&#xff1a; 一个【快递批量查询高手】软件 圆通速递单号若干 操作步骤&#xff1a; 步骤1&#xff1a;运行【快递批量查询高手】软件&#xff0c;第一次使用的伙伴记得先注册&…

灯塔的安装

Docker 安装 docker 安装参考&#xff1a;https://docs.docker.com/engine/install/ shell脚本: curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh灯塔安装 mkdir docker-ARL;cd docker-ARL curl https://bootstrap.pypa.io/get-pip.py -o get-pip…

如何在Ubuntu系统上安装Node.js

简单介绍 简单的说Node.js就是运行在服务端的JavaScript。Node.js是一个基于Chrome JavaScript运行时建立的一个平台。Node.js是一个事件驱动I/O服务端JavaScript 环境&#xff0c;基于Google的V8引擎&#xff0c;V8引擎执行Javascript的速度非常快&#xff0c;性能非常好。 no…

【Hadoop】分布式文件系统 HDFS

目录 一、介绍二、HDFS设计原理2.1 HDFS 架构2.2 数据复制复制的实现原理 三、HDFS的特点四、图解HDFS存储原理1. 写过程2. 读过程3. HDFS故障类型和其检测方法故障类型和其检测方法读写故障的处理DataNode 故障处理副本布局策略 一、介绍 HDFS &#xff08;Hadoop Distribute…

直播预告 | AR眼镜在现代医疗中究竟有哪些妙用?11.28晚八点虹科直播间为您揭晓!

什么是AR眼镜&#xff1f; AR眼镜&#xff0c;即增强现实眼镜&#xff0c;是一种结合虚拟信息与真实世界的创新医疗工具。 通过集成高科技传感器和实时数据处理技术&#xff0c;AR眼镜能够将数字化的医学信息以虚拟形式叠加在医生的视野中&#xff0c;使其在诊断和治疗过程中…

数据库基础教程之创建触发器,实现自动更新时间戳(四)

postgresql 更新时间戳需要通过触发器来实现,这里给出两种方法来实现。 创建字段create_time和edit_time 通过Navicat在添加字段时候将字段设置为timestamp类型,生成时间戳方式为CURRENT_TIMESTAMP或者设置为now(),然后点击保存。 新建函数 点击函数,然后在弹出的函数向导中…

【全栈开发】RedwoodJS与BlitzJS:全栈JavaScript元框架的未来

Redwood和Blitz是两个即将出现的全栈元框架&#xff0c;它们提供了创建SPAs、服务器端渲染页面和静态生成内容的工具&#xff0c;并提供了生成端到端支架的CLI。我一直在等待一个有价值的Rails JavaScript替代品&#xff0c;谁知道什么时候。这篇文章是对两者的概述&#xff0c…

Kotlin学习——kt里的集合,Map的各种方法之String篇

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…

初始化GPIO流程 以及点亮LED

点亮LED 需要单片机上的GIPIO端口引脚 输出对应的电压来对LED进行点亮 &#xff0c;关于GPIO的初始化流程其实我们只需要牢牢记住这张图即可 具体参考&#xff1a; https://blog.csdn.net/k666499436/article/details/123971479 1. GPIO的初始化 流程 使能时钟 在stm32中&…

Simulink 的代数环

代数环, 就是由于模型的输出反馈到模块或子系统先的某个输入端, 如果这个输入是直接馈入的, 那么二者在同一个采样点内需得到求解, 但又互相依赖, 哪一方都不能完成求解过程, 使得解算器无法解算导致错误产生, 这样的情况称为代数环。 一旦 Simulink 遇到代数环, 将根据 Confi…

个人成长|信奉长期主义,就要多做可积累有复利的事。

哈喽啊&#xff0c;大家好&#xff0c;我是雷工&#xff01; 最近有个哥们儿吐槽&#xff0c;说他们公司人事找他谈话&#xff0c;要给降工资&#xff0c;他不同意。 过了没几天又说&#xff1a; “定了&#xff0c;全员降薪”。 “你同意了&#xff1f;” “不同意&#xff0…

2017年五一杯数学建模A题公交车排班问题解题全过程文档及程序

2017年五一杯数学建模 A题 公交车排班问题 原题再现 随着徐州市经济的快速发展&#xff0c;公交车系统对于人们的出行扮演着越来越重要的角色。在公交车资源有限的情况下&#xff0c;合理的编排公交车的行车计划成为公交公司亟待解决的问题。以下给出公交车排班问题中的部分名…

python环境搭建-yolo代码跑通-呕心沥血制作(告别报错no module named torch)

安装软件 安装过的可以查看有没有添加环境变量 好的! 我们发车! 如果你想方便快捷的跑通大型项目,那么必须安装以下两个软件: 1.pycharm2.anaconda对应作用: pycharm:专门用来跑通python项目的软件,相当于一个编辑器,可以debug调试,可以接受远程链接调试!anaconda:专…

OpenGL 自学总结

前言&#xff1a; 本人是工作后才接触到的OpenGL&#xff0c;大学找工作的时候其实比较着急&#xff0c;就想着尽快有个着落。工作后才发现自己的兴趣点。同时也能感觉到自己当前的工作有一点温水煮青蛙的意思&#xff0c;很担心自己往后能力跟不上年龄的增长。因此想在工作之余…

DL Homework 8

目录 习题5-2 证明宽卷积具有交换性&#xff0c; 即公式(5.13)&#xff0e; 习题5-4 对于一个输入为100 100 256的特征映射组&#xff0c; 使用3 3的卷积核&#xff0c; 输出为100 100 256的特征映射组的卷积层&#xff0c; 求其时间和空间复杂度&#xff0e; 如果引入一…

CentOS7部署FTP服务器

首先准备一台centos7虚拟机&#xff0c;作为服务器IP地址必须是固定的。 vim /etc/sysconfig/network-scripts/ifcfg-ens33配置内容如下&#xff1a; TYPE"Ethernet" PROXY_METHOD"none" BROWSER_ONLY"no" BOOTPROTO"static" DEFROU…

服务器下db(数据库)的执行

1、查看 select * from xxxx&#xff08;表名&#xff09; where xxx&#xff08;列表&#xff09;1 and.......正常写就行 2、插入 如果你想要在 SELECT INSERT INTO … SELECT 语句中将部分列保持不变,只改变一两列的值,可以在 语句中直接设置目标列的值,而其他列从源表中…

KubeVela核心控制器原理浅析

前言 在学习 KubeVela 的核心控制器之前&#xff0c;我们先简单了解一下 KubeVela 的相关知识。 KubeVela 本身是一个应用交付与管理控制平面&#xff0c;它架在 Kubernetes 集群、云平台等基础设施之上&#xff0c;通过开放应用模型来对组件、云服务、运维能力、交付工作流进…

王者荣耀,,,,,

第一步是创建项目 项目名自拟 第二部创建个包名 来规范class 然后是创建类 GameFrame 运行类 package com.sxt; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;…