从0到1建立前端规范

本文适合打算建立前端规范的小伙伴阅读
一、为什么需要规范

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

统一代码规范的好处:

  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设计师,以此来相互监督是否达成了规范协议。

五、总结

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

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

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

相关文章

计算机系统的层次结构与性能指标

目录 一. 计算机系统的层次结构二. 计算机性能指标2.1. 存储器的性能指标2.2 CPU的性能指标2.3 系统整体的性能指标2.4 系统整体的性能指标(动态测试) \quad 一. 计算机系统的层次结构 \quad \quad 虚拟机器的意思是看起来像是机器直接就能执行程序员所写的代码, 其实是需要通过…

[Matlab有限元分析] 2.杆单元有限元分析

1. 一维杆单元有限元分析程序 一维刚单元的局部坐标系&#xff08;单元坐标系&#xff09;与全局坐标系相同。 1.1 线性杆单元 如图所示是一个杆单元&#xff0c;由两个节点i和j&#xff0c;局部坐标系的X轴沿着杆的方向&#xff0c;由i节点指向j节点&#xff0c;每个节点有…

ZGC 垃圾回收过程

ZGC&#xff08;Z Garbage Collector&#xff09;是Java平台上的一种垃圾收集器&#xff0c;它是由Oracle开发的&#xff0c;旨在解决大堆的低延迟垃圾收集问题。ZGC是一种并发的分代垃圾收集器&#xff0c;它主要针对具有大内存需求和低停顿时间要求的应用程序 ZGC的核心概念及…

大数据平台/大数据技术与原理-实验报告--部署全分布模式Hadoop集群

实验名称 部署全分布模式Hadoop集群 实验性质 &#xff08;必修、选修&#xff09; 必修 实验类型&#xff08;验证、设计、创新、综合&#xff09; 综合 实验课时 2 实验日期 2023.10.16-2023.10.20 实验仪器设备以及实验软硬件要求 专业实验室&#xff08;配有cen…

【Android Gradle】之Gradle入门及 wrapper 生成(一)

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。 &#x1f60a; 座右铭&#xff1a;不…

Stm32CubeMx生成代码提示缺少“core_cm3.h“

Stm32CubeMx生成代码提示缺少"core_cm3.h" 1.原因分析 1.1问题根源 在我们使用本地解压的方法去安装固件包,但是找错了要下载的固件包&#x1f60a;.在你点击进入下载页面之后,能看到一共有两个下载链接,其中上面的是补丁包,而第二个才是我们应该要下载的固件包 当…

3DCAT为华东师大设计学院打造元宇宙数字虚拟学院

6月11日&#xff0c;华东师范大学设计学院在chi K11美术馆举办了一场别开生面的 2023 年本科毕业设计暨项目实践教学现场演示展。其中&#xff0c;元宇宙数字虚拟学院&#xff08;一期&#xff09;的现场发布会引起了现场震撼&#xff0c;吸引了众多观众的目光和参与。 该元宇宙…

数据库基础教程之序列自增设置(三)

点击public来选择一个模式。 选择其他-》序列。 选择新建序列。 设置序列参数&#xff08;最大值不超过2的63次方-1&#xff09;。 点击保存。 刷新序列列表&#xff0c;可以看见新建序列。 设置主键自增 打开设计表-》选中字段-》默认值设置为&#xff1a;nextval(‘log_text’…

如何在Ubuntu系统上安装MongoDB

简单介绍 MongoDB是由C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统。在高负载的情况下&#xff0c;添加更多的节点&#xff0c;可以保证服务器性能。MongoDB旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB将数据存储为一个文档&#xff0c;数…

GCPS—20型工程钻机的设计自动摊铺机的设计机械设计

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;摊铺机 获取完整论文报告工程源文件 摊铺机是一种复合式多功能摊铺机&#xff0c;为适应我国深基础和连续墙以及水利、纺织的发展与需要&#xff0c;结合大口径摊铺机灌注桩和地下连续墙施工的特点&#xff0c;为解决在复…

论文笔记--Toolformer: Language Models Can Teach Themselves to Use Tools

论文笔记--Toolformer: Language Models Can Teach Themselves to Use Tools 1. 文章简介2. 文章概括3 文章重点技术3.1 Toolformer3.2 APIs 4. 文章亮点5. 原文传送门 1. 文章简介 标题&#xff1a;Toolformer: Language Models Can Teach Themselves to Use Tools作者&#…

佳易王商超便利店进销存管理系统软件下载,扫描商品自动计算金额支持扫码支付

佳易王商超便利店进销存管理系统软件下载&#xff0c;扫描商品自动计算金额支持扫码支付 软件特色&#xff1a; 1、功能实用&#xff0c;操作简单&#xff0c;不会电脑也会操作&#xff0c;软件免安装&#xff0c;已内置数据库。软件在关闭的时候&#xff0c;可以设置会员数据…

《C++PrimePlus》第10章 对象和类

10.1 过程性编程和面向对象编程 10.2 抽象和类 10.3 类的构造函数和析构函数 类的定义和使用&#xff08;买卖股票&#xff09; 头文件stock10.h #ifndef __STOCK00__H__ #define __STOCK00__H__#include <string>class Stock { // pravate的内容只能通过public访问 p…

jsp生成验证码的代码

效果图&#xff1a; loginProcess.jsp <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%><% String captcharequest.getParameter("captcha");%><% String captcha_session(String)s…

新手如何购买保险,保险投资基础入门

一、教程描述 本套保险教程&#xff0c;大小2.63G&#xff0c;共有11个文件。 二、教程目录 第01课 保险到底有什么用.mp4 第02课 已有社保还需要商业保险吗.mp4 第03课 你必须要懂的保险基础知识.mp4 第04课 关于重疾你必须要知道的几件事情.mp4 第05课 家庭重疾险如何…

Python 安装mysqlclient 错误 无法打开包括文件: “mysql.h”: 解决方法

解决方案&#xff1a;python最新3.12.0不支持mysqlclient 请下载 python3.9.9 版本 高速下载地址CNPM Binaries Mirror 官方下载地址Welcome to Python.org 下载完成后将python添加到环境变量 pycharm 虚拟环境下的python版本切换到你刚才下载的3.9.9的python版本 Avai…

SpringBoot事务处理

一、事务回顾 回顾地址&#xff1a; 深入理解数据库事务&#xff08;超详细&#xff09;_数据库事务操作_Maiko Star的博客-CSDN博客 事务&#xff1a; 是一组操作的集合&#xff0c;是一个不可分割的工作单位&#xff0c;这些操作要么同时成功&#xff0c;要么同时失败 事…

【数据分享】我国12.5米分辨率的坡向数据(免费获取)

地形数据&#xff0c;也叫DEM数据&#xff0c;是我们在各项研究中最常使用的数据之一。之前我们分享过源于NASA地球科学数据网站发布的12.5米分辨率DEM地形数据&#xff01;基于该数据我们处理得到12.5米分辨率的坡度数据、12.5米分辨率的山体阴影数据&#xff08;均可查看之前…

MySQL 8 手动安装后无法启动的问题解决

开头还是介绍一下群&#xff0c;如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;&#xff08;…

LeetCode:1457. 二叉树中的伪回文路径(DFS C++ Java)

目录 1457. 二叉树中的伪回文路径 题目描述&#xff1a; 原理思路&#xff1a; 1457. 二叉树中的伪回文路径 题目描述&#xff1a; 给你一棵二叉树&#xff0c;每个节点的值为 1 到 9 。我们称二叉树中的一条路径是 「伪回文」的&#xff0c;当它满足&#xff1a;路径经过的…