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

React进阶之react.js、jsx模板语法及babel编译

React

  • React介绍
    • React官网初识
    • React学习
      • MVC
      • MVVM
  • JSX
    • 外部的元素props和内部的状态state
      • props
      • state
  • 生命周期
    • constructor
    • getDerivedStateFromProps
    • render
    • componentDidMount()
    • shouldComponentUpdate
    • getSnapshotBeforeUpdate(prevProps, prevState)
  • 创建项目
    • CRA:create-react-app
      • create-react-app源码解析
        • packages
          • package/create-react-app
            • index.js
            • createReactApp.js

React介绍

React官网初识

react 官网
react github

团队中选型时候,如果没有历史包的话,就选择最新的react,如果有历史包的话,选择不影响历史包升级的版本
但是最新的也容易踩到坑

在React19中,主要看 新特性和带来的提升即可
在这里插入图片描述
新特性:
在这里插入图片描述
在这里插入图片描述
form类似于 react/field-form
在这里插入图片描述
这里的use可以理解为,添加响应式的逻辑
在这里插入图片描述
性能上的提升:
ref可以作为props,平常项目中使用的是improve API 去关联,而无法用props来关联
在这里插入图片描述

React学习

React 中小厂用的不多,但是大厂用的都是React
React:构建web和原生交互界面的库,React组件本质上就是一个函数

  1. 像Vue一样支持组件的方式去拓展
  2. 支持原生元素标签,并且能够在标签中通过js的方法去执行
  3. 接收props,和state

与Vue相比较的话,React有一个典型的特性,React是单向数据流的
我们的视图是由我们的交互所决定的
ui视图 = render(data) 由数据所触发ui视图的变化

官网中,把这些内容看完就足够了
在这里插入图片描述

MVC

MVC model view controller
是一个架构的设计思路
controller:控制器 操纵数据导致视图变化
modal:数据
view:视图 视图中事件的触发也能够触发controller

// model
var myapp = {}; // 创建这个应用对象

myapp.Model = function() {
  var val = 0;

  this.add = function(v) {
    if (val < 100) val += v;
  };

  this.sub = function(v) {
    if (val > 0) val -= v;
  };

  this.getVal = function() {
    return val;
  };* 观察者模式 /
  var self = this, 
      views = [];

  this.register = function(view) {
    views.push(view);
  };

  this.notify = function() {
    for(var i = 0; i < views.length; i++) {
        views[i].render(self);
    }
  };
};

// view
myapp.View = function(controller) {
  var $num = $('#num'),
      $incBtn = $('#increase'),
      $decBtn = $('#decrease');

  this.render = function(model) {
      $num.text(model.getVal() + 'rmb');
  };

  /  绑定事件  /
  $incBtn.click(controller.increase);
  $decBtn.click(controller.decrease);
};

// controller
myapp.Controller = function() {
  var model = null,
      view = null;

  this.init = function() {
    / 初始化Model和View /
    model = new myapp.Model();
    view = new myapp.View(this);

    / View向Model注册,当Model更新就会去通知View啦 /
    model.register(view);
    model.notify();
  };

  / 让Model更新数值并通知View更新视图 */
  this.increase = function() {
    model.add(1);
    model.notify();
  };

  this.decrease = function() {
    model.sub(1);
    model.notify();
  };
};

// init
(function() {
  var controller = new myapp.Controller();
  controller.init();
})();

MVVM

MVVM: model viewModel view 数据的双向绑定

// model
var data = {
    val: 0
};

// view
<div id="myapp">
    <div>
        <span>{{ val }}rmb</span>
    </div>
    <div>
        <button v-on:click="sub(1)">-</button>
        <button v-on:click="add(1)">+</button>
    </div>
</div>

// controller
new Vue({
  el: '#myapp',
  data: data,
  methods: {
    add(v) {
        if(this.val < 100) {
            this.val += v;
        }
    },
    sub(v) {
        if(this.val > 0) {
            this.val -= v;
        }
    }
  }
});

// Vue是不是MVVM?React呢?
// 严格来讲都不是。
// Vue操作的是虚拟的dom,而不是真实的dom节点,通过ref.current获取的结果,从虚拟上能够直接指向真实dom                                                                                                                                                                                                                                                                                                                 
// React:ui = render (data) 单向数据流
// Vue:   ref 直接操作DOM,跳过了ViewModel

JSX

function VideoList({ videos, emptyHeading }) {
  const count = videos.length;
  let heading = emptyHeading;
  if (count > 0) {
    const noun = count > 1 ? 'Videos' : 'Video';
    heading = count + ' ' + noun;
  }
  return (
    <section>
      <h2>{heading}</h2>
      {videos.map(video =>
        <Video key={video.id} video={video} />
      )}
    </section>
  );
}

模板化的语言写法,需要注意的是,怎样将模板化的语言写法,转化为对象,最终转化为我们真实的dom

Vue和React都是通过AST去转化的,将我们这样的模板语言转化为js对象的能力:通过 babel
babel 是 js的compiler
compiler是代码执行之前,需要将代码从一种格式转换为另一种格式,方便后续代码的识别和执行
runtime是jsx代码中最终去消费babel编译后的产物,交由给_jsxs去做运行时的逻辑
babel
babel 本质:core-js,定义的js的各种各样的ecma标准都能做到

在这里插入图片描述

babel:将jsx模板写法转化为js对象的能力
jsx本质:借助于Babel的 @babel/preset-react 提供的包的能力转换出来的js对象,在compiler代码编译过程中做到的

绑定事件:
这个事件称之为,合成事件,并不是直接绑定到元素上的,通过驼峰的方式,将方法绑定到属性上
在这里插入图片描述
写业务开发的市场饱和了,要求是写业务代码基础上,能够将写业务代码的工具能掌握好

外部的元素props和内部的状态state

类似于函数

function bar(a,b){
   const d=1
}

a,b就像是props,而d就像是state

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

props和state是怎么影响视图逻辑的?

组件的本质要么是类,要么是函数

props

export default function Profile(){
  return (
    <Avatar
      person={{name:'Lin Lanying',imageId:'1dx5qh6'}}
      size={100}
    />
  )
}

interface IAvatarProps(){
  person?: Record<string,any>;
  size?: number|string;
}

function Avatar(props: IAvatarProps){
  const {person,size=10}=props;
}

也可以这样作解构:

function Avatar({person,size}){
  const {person,size=10}=props;
}

state

useXXX => hooks的标志

import { sculptureList } from './data.js';
import { useState } from 'react';

export default function Gallery() {
  const [index,setIndex]=useState(0) //hooks
  const [showMore,setShowMore]=useState(false) //hooks

  function handleClick() {
    setIndex(index+1)
  }

  function handleMoreClick() {
    setShowMore(!showMore)
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <button onClick={handleMoreClick}>
        {showMore?'Hide':'Show'} details	
      </button>
      { showMore && <p>{sculpture.description}</p>}
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />	
    </>
  );
}

<></> => react 属性中得 Fragment 不表示任何意义,只是提供了一个容器。因为react只能接收一个根节点,因此能使用Fragment将根节点聚合起来

生命周期

在这里插入图片描述

  1. constructor:通过类引入constructor
  2. getDerivedStateFromProps:通过props的不同来找到state的区别
  3. render:实际渲染的动作
  4. Render阶段:react是虚拟dom,这个阶段是在内存中去执行的,并没有真正渲染
  5. Commit阶段:创建真实dom
  6. shouldComponentUpdate:判断组件是否需要更新,减少组件没有必要的重复渲染
  7. getSnapshotBeforeUpdate:上一次更新前的内容,提供了上一次的props和state
  8. componentDidUpdate:执行更新完之后的生命周期
  9. componentWillUnmount:组件卸载之前

constructor

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = { counter: 0 };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // ...
  }

getDerivedStateFromProps

class Form extends Component {
  state = {
    email: this.props.defaultEmail,
    prevUserID: this.props.userID
  };

  static getDerivedStateFromProps(props, state) {
    // 每当当前用户发生变化时,
    // 重置与该用户关联的任何 state 部分。
    // 在这个简单的示例中,只是以 email 为例。
    if (props.userID !== state.prevUserID) {
      return {
        prevUserID: props.userID,
        email: props.defaultEmail
      };
    }
    return null;
  }

  // ...
}

render

import { Component } from 'react';

class Greeting extends Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

componentDidMount()

class ChatRoom extends Component {
  state = {
    serverUrl: 'https://localhost:1234'
  };

  componentDidMount() {
    this.setupConnection();
  }

  componentDidUpdate(prevProps, prevState) {
    if (
      this.props.roomId !== prevProps.roomId ||
      this.state.serverUrl !== prevState.serverUrl
    ) {
      this.destroyConnection();
      this.setupConnection();
    }
  }

  componentWillUnmount() {
    this.destroyConnection();
  }

  // ...
}

shouldComponentUpdate

class Rectangle extends Component {
  state = {
    isHovered: false
  };

  shouldComponentUpdate(nextProps, nextState) {
    if (
      nextProps.position.x === this.props.position.x &&
      nextProps.position.y === this.props.position.y &&
      nextProps.size.width === this.props.size.width &&
      nextProps.size.height === this.props.size.height &&
      nextState.isHovered === this.state.isHovered
    ) {
      // 没有任何改变,因此不需要重新渲染
      return false;
    }
    return true;
  }

  // ...
}

getSnapshotBeforeUpdate(prevProps, prevState)

不怎么经常使用的API,应用场景少

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // 我们是否要向列表中添加新内容?
    // 捕获滚动的​​位置,以便我们稍后可以调整滚动。
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // 如果我们有快照值,那么说明我们刚刚添加了新内容。
    // 调整滚动,使得这些新内容不会将旧内容推出视野。
    //(这里的 snapshot 是 getSnapshotBeforeUpdate 返回的值)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

创建项目

pnpx create-react-app my-app

在这里插入图片描述
package.json:
这里的scripts里的指令本质:如何搭建一个自定义的webpack配置
在这里插入图片描述
CRA是脚手架,react-scripts是用CRA写的,CRA是用webpack写的

CRA:create-react-app

create-react-app

在这里插入图片描述
安装react,react-dom,react-scripts,基于cra-template模板安装的
创建git-commit
提供方法,react-scripts

create-react-app源码解析

create-react-app源码

  • docusaurus 静态站点,包含了这些的说明
    • website 静态站点
    • docs 静态站点的说明
      在这里插入图片描述
  • .github
    • PULL_REQUEST_TEMPLATE.md
    • workflows 工作流,包含构建,通过github的钩子做的一些事情
  • packages 多包结构
  • lerna.json 基于lerna的多包结构
    {
      "lerna": "2.6.0",
      "npmClient": "yarn",
      "useWorkspaces": true,  //使用多包管理
      "version": "independent", //每个包的版本号不需要一致
      "changelog": {  //更新添加元素
        "repo": "facebook/create-react-app",
        "labels": {
          "tag: new feature": ":rocket: New Feature",
          "tag: breaking change": ":boom: Breaking Change",
          "tag: bug fix": ":bug: Bug Fix",
          "tag: enhancement": ":nail_care: Enhancement",
          "tag: documentation": ":memo: Documentation",
          "tag: internal": ":house: Internal",
          "tag: underlying tools": ":hammer: Underlying Tools"
        },
        "cacheDir": ".changelog"
      }
    }
    
  • tasks 测试用例 通过shell脚本去写的 和test结合去用的,怎样基于测试用例执行事件
  • test
  • .alexrc rc,runtime config 运行时的配置
packages
  • cra-template 模板
  • create-react-app 由这个执行

pnpx create-react-app 命令

执行的是 create-react-app的package.json中的bin的指令,node作为二进制执行的入口,这个命令等效于在create-react-app目录下执行 node ./index.js命令
在这里插入图片描述

package/create-react-app
index.js
'use strict';

const currentNodeVersion = process.versions.node; //20.12.2
const semver = currentNodeVersion.split('.'); //通过.分割node版本号
const major = semver[0]; //获取第一位数字,即主版本号,如20

if (major < 14) { //主版本号小于14的话就退出
  console.error(
    'You are running Node ' +
      currentNodeVersion +
      '.\n' +
      'Create React App requires Node 14 or higher. \n' +
      'Please update your version of Node.'
  );
  process.exit(1);
}
//执行CRA的init方法
const { init } = require('./createReactApp');

init();
createReactApp.js

主要内容:

  1. commander

pnpx create-react-app -h

罗列指令及功能
在这里插入图片描述

pnpx create-react-app --info

输出环境信息
在这里插入图片描述

  1. init方法
function init() {
  const program = new commander.Command(packageJson.name)
    .version(packageJson.version)
    .arguments('<project-directory>')
    .usage(`${chalk.green('<project-directory>')} [options]`)
    .action(name => {
      projectName = name; //自己定义的项目名字,这里就是my-app
    })
    .option('--verbose', 'print additional logs')
    .option('--info', 'print environment debug info')
    .option(
      '--scripts-version <alternative-package>',
      'use a non-standard version of react-scripts'
    )
    .option(
      '--template <path-to-template>',
      'specify a template for the created project'
    )
    .option('--use-pnp')
    .allowUnknownOption()
    .on('--help', () => {
      console.log(
        `    Only ${chalk.green('<project-directory>')} is required.`
      );
      console.log();
      console.log(
        `    A custom ${chalk.cyan('--scripts-version')} can be one of:`
      );
      console.log(`      - a specific npm version: ${chalk.green('0.8.2')}`);
      console.log(`      - a specific npm tag: ${chalk.green('@next')}`);
      console.log(
        `      - a custom fork published on npm: ${chalk.green(
          'my-react-scripts'
        )}`
      );
      console.log(
        `      - a local path relative to the current working directory: ${chalk.green(
          'file:../my-react-scripts'
        )}`
      );
      console.log(
        `      - a .tgz archive: ${chalk.green(
          'https://mysite.com/my-react-scripts-0.8.2.tgz'
        )}`
      );
      console.log(
        `      - a .tar.gz archive: ${chalk.green(
          'https://mysite.com/my-react-scripts-0.8.2.tar.gz'
        )}`
      );
      console.log(
        `    It is not needed unless you specifically want to use a fork.`
      );
      console.log();
      console.log(`    A custom ${chalk.cyan('--template')} can be one of:`);
      console.log(
        `      - a custom template published on npm: ${chalk.green(
          'cra-template-typescript'
        )}`
      );
      console.log(
        `      - a local path relative to the current working directory: ${chalk.green(
          'file:../my-custom-template'
        )}`
      );
      console.log(
        `      - a .tgz archive: ${chalk.green(
          'https://mysite.com/my-custom-template-0.8.2.tgz'
        )}`
      );
      console.log(
        `      - a .tar.gz archive: ${chalk.green(
          'https://mysite.com/my-custom-template-0.8.2.tar.gz'
        )}`
      );
      console.log();
      console.log(
        `    If you have any problems, do not hesitate to file an issue:`
      );
      console.log(
        `      ${chalk.cyan(
          'https://github.com/facebook/create-react-app/issues/new'
        )}`
      );
      console.log();
    })
    .parse(process.argv);

  if (program.info) {
    console.log(chalk.bold('\nEnvironment Info:'));
    console.log(
      `\n  current version of ${packageJson.name}: ${packageJson.version}`
    );
    console.log(`  running from ${__dirname}`);
    return envinfo //是一个会将当前环境都输出的包
      .run(
        {
          System: ['OS', 'CPU'],
          Binaries: ['Node', 'npm', 'Yarn'],
          Browsers: [
            'Chrome',
            'Edge',
            'Internet Explorer',
            'Firefox',
            'Safari',
          ],
          npmPackages: ['react', 'react-dom', 'react-scripts'],
          npmGlobalPackages: ['create-react-app'],
        },
        {
          duplicates: true,
          showNotFound: true,
        }
      )
      .then(console.log);
  }

  if (typeof projectName === 'undefined') {
    console.error('Please specify the project directory:');
    console.log(
      `  ${chalk.cyan(program.name())} ${chalk.green('<project-directory>')}`
    );
    console.log();
    console.log('For example:');
    console.log(
      `  ${chalk.cyan(program.name())} ${chalk.green('my-react-app')}`
    );
    console.log();
    console.log(
      `Run ${chalk.cyan(`${program.name()} --help`)} to see all options.`
    );
    process.exit(1);
  }

  // We first check the registry directly via the API, and if that fails, we try
  // the slower `npm view [package] version` command.
  //
  // This is important for users in environments where direct access to npm is
  // blocked by a firewall, and packages are provided exclusively via a private
  // registry.
  checkForLatestVersion() //检查最新的版本号
    .catch(() => {
      try {
        return execSync('npm view create-react-app version').toString().trim(); //执行这个命令可以得到最新的版本号
      } catch (e) {
        return null;
      }
    })
    .then(latest => {
      if (latest && semver.lt(packageJson.version, latest)) {
        //有最新版本且没有升级到最新的版本,提示要升级到最新的版本了
        console.log();
        console.error(
          chalk.yellow(
            `You are running \`create-react-app\` ${packageJson.version}, which is behind the latest release (${latest}).\n\n` +
              'We recommend always using the latest version of create-react-app if possible.'
          )
        );
        console.log();
        console.log(
          'The latest instructions for creating a new app can be found here:\n' +
            'https://create-react-app.dev/docs/getting-started/'
        );
        console.log();
      } else {
        const useYarn = isUsingYarn(); //判断是否使用yarn
        createApp(
          projectName,
          program.verbose,
          program.scriptsVersion,
          program.template,
          useYarn,
          program.usePnp
        );
      }
    });
}
  1. checkForLatestVersion 获取最新的版本号
function checkForLatestVersion() {
  return new Promise((resolve, reject) => {
    https  //通过http发送get请求读取版本号
      .get(
        'https://registry.npmjs.org/-/package/create-react-app/dist-tags',//版本号
        res => {
          if (res.statusCode === 200) {
            let body = '';
            res.on('data', data => (body += data));
            res.on('end', () => {
              resolve(JSON.parse(body).latest);
            });
          } else {
            reject();
          }
        }
      )
      .on('error', () => {
        reject();
      });
  });
}
  1. isUsingYarn():判断是否使用yarn
function isUsingYarn() {
  return (process.env.npm_config_user_agent || '').indexOf('yarn') === 0; //使用环境变量判断是否使用yarn
}
  1. createApp()
function createApp(name, verbose, version, template, useYarn, usePnp) {
  const unsupportedNodeVersion = !semver.satisfies(
    // Coerce strings with metadata (i.e. `15.0.0-nightly`).
    semver.coerce(process.version),
    '>=14'
  );

  if (unsupportedNodeVersion) {
    console.log(
      chalk.yellow(
        `You are using Node ${process.version} so the project will be bootstrapped with an old unsupported version of tools.\n\n` +
          `Please update to Node 14 or higher for a better, fully supported experience.\n`
      )
    );
    // Fall back to latest supported react-scripts on Node 4
    version = 'react-scripts@0.9.x';
  }

  const root = path.resolve(name);
  const appName = path.basename(root);

  checkAppName(appName);
  fs.ensureDirSync(name);
  if (!isSafeToCreateProjectIn(root, name)) {
    process.exit(1);
  }
  console.log();

  console.log(`Creating a new React app in ${chalk.green(root)}.`);
  console.log();

  // 首先创建一个最基础版
  const packageJson = {
    name: appName,
    version: '0.1.0',
    private: true,
  };
  // 写入
  fs.writeFileSync(
    path.join(root, 'package.json'),
    JSON.stringify(packageJson, null, 2) + os.EOL
  );

  const originalDirectory = process.cwd();
  process.chdir(root);
  if (!useYarn && !checkThatNpmCanReadCwd()) {
    process.exit(1);
  }

  if (!useYarn) {
    const npmInfo = checkNpmVersion();
    if (!npmInfo.hasMinNpm) {
      if (npmInfo.npmVersion) {
        console.log(
          chalk.yellow(
            `You are using npm ${npmInfo.npmVersion} so the project will be bootstrapped with an old unsupported version of tools.\n\n` +
              `Please update to npm 6 or higher for a better, fully supported experience.\n`
          )
        );
      }
      // Fall back to latest supported react-scripts for npm 3
      version = 'react-scripts@0.9.x';
    }
  } else if (usePnp) {
    const yarnInfo = checkYarnVersion();
    if (yarnInfo.yarnVersion) {
      if (!yarnInfo.hasMinYarnPnp) {
        console.log(
          chalk.yellow(
            `You are using Yarn ${yarnInfo.yarnVersion} together with the --use-pnp flag, but Plug'n'Play is only supported starting from the 1.12 release.\n\n` +
              `Please update to Yarn 1.12 or higher for a better, fully supported experience.\n`
          )
        );
        // 1.11 had an issue with webpack-dev-middleware, so better not use PnP with it (never reached stable, but still)
        usePnp = false;
      }
      if (!yarnInfo.hasMaxYarnPnp) {
        console.log(
          chalk.yellow(
            'The --use-pnp flag is no longer necessary with yarn 2 and will be deprecated and removed in a future release.\n'
          )
        );
        // 2 supports PnP by default and breaks when trying to use the flag
        usePnp = false;
      }
    }
  }

  run(
    root,
    appName,
    version,
    verbose,
    originalDirectory,
    template,
    useYarn,
    usePnp
  );
}
  1. setCaretRangeForRuntimeDeps()
function setCaretRangeForRuntimeDeps(packageName) {
  const packagePath = path.join(process.cwd(), 'package.json');
  const packageJson = require(packagePath);

  if (typeof packageJson.dependencies === 'undefined') {
    console.error(chalk.red('Missing dependencies in package.json'));
    process.exit(1);
  }

  const packageVersion = packageJson.dependencies[packageName];
  if (typeof packageVersion === 'undefined') {
    console.error(chalk.red(`Unable to find ${packageName} in package.json`));
    process.exit(1);
  }

  // 手动注入react,react-dom
  makeCaretRange(packageJson.dependencies, 'react');
  makeCaretRange(packageJson.dependencies, 'react-dom');

  fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2) + os.EOL);
}

手动注入react,react-dom,然后将 cra-template 模板拼上去,就生成了cra代码

  1. 后面就是判断依赖,告诉有哪些异常,异常的话就过滤删除

CRA主要做的事:读取用户的输入,根据用户输入创建出对应的模板,写入到指定的目录下


http://www.kler.cn/a/510140.html

相关文章:

  • 深入理解 SQL 中的 DATEDIFF 函数
  • 华为数据中心CE系列交换机级联M-LAG配置示例
  • ThinkPhp项目解决静态资源请求的跨域问题的解决思路
  • Eamon.MeituanDotnetSDK 美团C# .Net SDK开源啦
  • 深入理解 D3.js 力导向图:原理、调参与应用
  • python之二维几何学习笔记
  • 数据结构---并查集
  • Python学习(十三)什么是模块、模块的引入、自定义模块、常见的内置模块(math、random、os、sys、uuid、时间模块、加密模块)
  • 搭建一个基于Spring Boot的数码分享网站
  • [Qt]窗口-QDialog、QMessageBox、QColorDialog、QFileDialog、QFontFialog、QInputDialog对话框
  • 登录校验Cookie、Session、JWT
  • 【unity进阶篇】弧度、角度和三角函数(Mathf),并实现类似蛇的运动
  • Django SimpleUI 自定义功能实战
  • 【漏洞预警】FortiOS 和 FortiProxy 身份认证绕过漏洞(CVE-2024-55591)
  • 网络系统管理Linux环境——AppSrv之SSH
  • 天机学堂5-XxlJobRedis
  • 硬件学习笔记--34 GB/T17215.321相关内容介绍
  • C++实现设计模式---迭代器模式 (Iterator)
  • Django 和 Vue3 前后端分离开发笔记
  • OpenAI推出首个AI Agent!日常事项自动化处理!
  • 深入浅出 SQLSugar:快速掌握高效 .NET ORM 框架
  • Boost Asio TCP异步服务端和客户端
  • 数据库管理-第285期 Oracle 23ai:深入浅出向量索引(20250117)
  • 2025年编程语言热度分析:Python领跑,Go与Rust崛起
  • 考研计算机组成原理——零基础学习的笔记
  • PHP语言的字符串处理