快速构建Web应用,从零学习React后台项目模版

想要快速构建实际应用,离不开一个好的应用模版,React作为大厂出品工具,有着稳定性和可维护性的保障,同时可以使用相关的全套全家桶(React + React-router + Axios + Mobx + Antd)进行连贯敏捷开发,本文将从如何在云开发平台创建项目应用模版,基于应用模版创建《后台管理》项目,以及上传并且通过云平台将项目上线部署应用,为项目开发提供更加便捷的操作环境。

一 、通过云开发平台快速创建初始化应用

1.创建相关应用模版请参考链接:https://developer.aliyun.com/article/878171?spm=a2c6h.12873581.0.dArticle878171.c61253e8nVBtAv

2.完成创建后就可以在github中查看到新增的react仓库

快速构建Web应用,从零学习React后台项目模版

二 、本地编写《后台管理》项目

1.将应用模版克隆到本地

• 首先假定你已经安装了Git、node,没有安装请移步node官网进行安装。克隆项目:

git clone + 项目地址

• 进入项目文件

cd create-react-app

• 切换到feature/1.0.0 分支上

git checkout feature/1.0.0

• 使用一下命令全局安装 React :

npm install -g create-react-app

• 安装依赖包

npm install

• 启动服务

npm start

这里打开浏览器3000端口,并出现默认页面。

2.架构与效果预览

• 《后台管理》项目架构

快速构建Web应用,从零学习React后台项目模版
• 效果预览
快速构建Web应用,从零学习React后台项目模版

3.初始化项目

• 初始化package.json

npm init

• 安装webpack

npm add -D webpack webpack-cli webpack-merge

项目中使用的Webpack版本是^5.10.0,Webpack4.0 打包构建做了很多默认的优化配置,不少配置项无需配置或更改。
比如:针对开发模式的加快打包速度,合并chunk; 针对生产模式的代码压缩,减少打包体积等。

// 一部分默认配置
optimization: {
        removeAvailableModules: true, // 删除已解决的chunk (默认 true)
        removeEmptyChunks: true, // 删除空的chunks (默认 true)
        mergeDuplicateChunks: true // 合并重复的chunk (默认 true)
    }

 // 针对生产环境默认配置
    optimization: {
        sideEffects:true, //配合tree shaking
        splitChunks: {...}, //拆包
        namedModules: false, // namedChunks:false 不启用chunk命名,默认自增id
        minimize: true, // 代码压缩
    }

根据开发环境/生产环境 区分webpack配置非常有必要,可以加快开发环境的打包速度,有时候遇到开发环境打包过慢,可以排查下是否配置有误(比如开发环境开启了代码压缩等)。
项目中配合webpack-merge根据开发环境/生产环境进行拆分配置:

快速构建Web应用,从零学习React后台项目模版
Webpack4.0发布已经很长时间了,相信基本上项目都已迁移至4.0,在这里就不多赘述了。
• 配置Html模版
安装:
npm add -D html-webpack-plugin

配置:

const srcDir = path.join(__dirname, "../src");
plugins: [
    new HtmlWebpackPlugin({
        template: ${srcDir}/index.html
 })
]

• 配置本地服务及热更新
安装:

npm add -D webpack-dev-server clean-webpack-plugin

开发环境利用webpack-dev-server搭建本地 web server,并启用模块热更新(HMR)。
为方便开发调试,转发代理请求(本例中配合axios封装 转发接口到easy-mock在线平台)
配置:

mode: "development", // 开发模式
devServer: { // 本地服务配置
    port: 9000,
    hot: true,
    open: false,
    historyApiFallback: true,
    compress: true,
    proxy: { // 代理
        "/testapi": {
            target:
            "https://www.easy-mock.com/mock/5dff0acd5b188e66c6e07329/react-template",
             changeOrigin: true,
             secure: false,
             pathRewrite: { "^/testapi": "" }
        }
    }
},
plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.HotModuleReplacementPlugin()
],

• 配置Babel
安装:

npm add -D babel-loader @babel/core @babel/plugin-transform-runtime
 @babel/preset-env @babel/preset-react  babel-plugin-import
 @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators

Webpack中Babel配置,是比较重要的一环。关系着ES6语法、React jsx、Mobx等语法经过打包后能否正常运行。
其中:
@babel/preset-react转换React jsx语法;
@babel/plugin-proposal-class-properties 转换 Class语法;
@babel/plugin-proposal-decorators 转换 Mobx 等更高级的语法;
babel-plugin-import 配合实现React组件的按需加载;
这里需要注意Babel7.0 相较于Babel6.0的区别。
配置:

module: {
    rules: [
        {
            test: /\.(js|jsx)$/,
            include: [srcDir],
            use: ["babel-loader?cacheDirectory=true"]
        },
    ]
}
• .babelrc 文件配置
{
    "presets": [
        "@babel/preset-env",
        "@babel/preset-react"
    ],
    "plugins": [
        "@babel/transform-runtime",
        [
            "@babel/plugin-proposal-decorators",
            {
                "legacy": true
            }
        ],
        ["@babel/plugin-proposal-class-properties", { "loose": true }],
        [
            "import",
            {
                "libraryName": "antd",
                "libraryDirectory": "es",
                "style": "css" // style: true 会加载 less 文件
            }
        ]
    ]
}

• 处理Less样式和图片等资源
安装:

npm add -D less less-loader style-loader css-loader url-loader
mini-css-extract-plugin postcss-loader autoprefixer

其中:
less-loader、style-loader、css-loader处理加载less、css文件;
postcss-loader、autoprefixer处理css样式浏览器前缀兼容;
url-loader处理图片、字体文件等资源;
mini-css-extract-plugin 分离css成单独的文件;
配置:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
...

module: {
    rules: [
        {
            test: /\.less$/,
            use: [
                devMode ? "style-loader" : MiniCssExtractPlugin.loader,
                "css-loader",
                "postcss-loader",
                "less-loader"
            ]
        },
        {
            test: /\.css$/,
            use: [
                devMode ? "style-loader" : MiniCssExtractPlugin.loader,
                "css-loader",
                "postcss-loader"
            ]
        },
        {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            use: ["url-loader"],
            include: [srcDir]
        },
        {
            test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
            use: ["url-loader"],
            include: [srcDir]
        },
        {
            test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
            use: ["url-loader"],
            include: [srcDir]
        }
    ]
},
plugins: [
    new MiniCssExtractPlugin({
        filename: "[name].[contenthash:8].css",
        chunkFilename: "chunk/[id].[contenthash:8].css"
    }),
    ],

配置postcss .postcssrc.js 文件

// .postcssrc.js
module.exports = {
    plugins: {
        autoprefixer: {}
    }
};
// package.json中配置兼容浏览器
"browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 10" ] < code></=>

• 利用happypack多线程打包
安装:

npm add -D happypack

配置:

const os = require("os");
const HappyPack = require("happypack");
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
module: {
    rules: [
        {
            test: /\.(js|jsx)$/,
            include: [srcDir],
            exclude: /(node_modules|bower_components)/,
            use: ["happypack/loader?id=happybabel"]
        },
    ]
},
plugins: [
    //&#x5F00;&#x542F; happypack &#x7684;&#x7EBF;&#x7A0B;&#x6C60;
    new HappyPack({
        id: "happybabel",
        loaders: ["babel-loader?cacheDirectory=true"],
        threadPool: happyThreadPool,
        cache: true,
        verbose: true
    }),
]

• 生产环境 拆分模块
根据项目实际情况拆分模块,采用异步加载方式,避免单个文件过大。

[En]

Split the module according to the actual project situation, with asynchronous loading to prevent a single file from being too large.

optimization: {
        runtimeChunk: {
            name: "manifest"
        },
        splitChunks: {
            chunks: "all", //&#x9ED8;&#x8BA4;&#x53EA;&#x4F5C;&#x7528;&#x4E8E;&#x5F02;&#x6B65;&#x6A21;&#x5757;&#xFF0C;&#x4E3A;all&#x65F6;&#x5BF9;&#x6240;&#x6709;&#x6A21;&#x5757;&#x751F;&#x6548;,initial&#x5BF9;&#x540C;&#x6B65;&#x6A21;&#x5757;&#x6709;&#x6548;
            cacheGroups: {
                dll: {
                    test: /[\\/]node_modules[\\/](react|react-dom|react-dom-router|babel-polyfill|mobx|mobx-react|mobx-react-dom|antd|@ant-design)/,
                    minChunks: 1,
                    priority: 2,
                    name: "dll"
                },
                codeMirror: {
                    test: /[\\/]node_modules[\\/](react-codemirror|codemirror)/,
                    minChunks: 1,
                    priority: 2,
                    name: "codemirror"
                },
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    minChunks: 1,
                    priority: 1,
                    name: "vendors"
                }
            }
        }
    }

• 其他配置
引入 ESLint 与 Prettier 配合,规范化团队项目代码开发,统一代码风格。

npm add -D prettier babel-eslint eslint eslint-loader eslint-config-airbnb
eslint-config-prettier eslint-plugin-babel eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react

具体配置详见 /build目录https://github.com/now1then/react-web-pro/tree/master/build
• npm scripts
package.json 文件

{
    ...
    "scripts": {
        "start": "webpack-dev-server --color --inline --progress --config build/webpack.dev.js", //
        "build": "NODE_ENV=production webpack --progress --config ./build/webpack.prod.js",
        "build:report": "NODE_ENV=production webpack --progress --config ./build/webpack.prod.js",
        "build:watch": "NODE_ENV=production webpack --progress --config ./build/webpack.prod.js"
    },
    ...

}

命令行运行:
// 命令行执行
// 运行开发环境;

npm start

// 生产环境打包压缩;

npm build

// 图形化分析打包文件大小;

npm build:report

// 方便排查生产环境打包后文件的错误信息(文件source map);

npm build:watch

其中 build:report 、build:watch 能够实现功能,是在build/webpack.prod.js 中有如下代码:
// 方便排查生产环境打包后文件的错误信息(文件source map)

if (process.env.npm_lifecycle_event == "build:watch") {
    config = merge(config, {
        devtool: "cheap-source-map"
    });
}
// &#x56FE;&#x5F62;&#x5316;&#x5206;&#x6790;&#x6253;&#x5305;&#x6587;&#x4EF6;&#x5927;&#x5C0F;
if (process.env.npm_lifecycle_event === "build:report") {
    const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
        .BundleAnalyzerPlugin;
    config.plugins.push(new BundleAnalyzerPlugin());
}

• 项目代码架构

npm add react react-dom react-router-dom mobx mobx-react mobx-react-router
axios antd moment

4.函数化Hooks

当前React版本已更新到16.12,Hooks 完全应该成为 React 使用的主流。本项目中将完全拥抱Hook,一般不再用 class 来实现组件。
以下为部分实现代码(可暂忽略mobx的使用):

import React, { useState, useEffect, useContext } from 'react';
import { observer } from 'mobx-react';
import { Button } from 'antd';
import Store from './store';
import './style.less';
const HomePage = () => {
    // useContext &#x8BA2;&#x9605;mobx&#x6570;&#x636E;
    const pageStore = useContext(Store);
    // useState state&#x72B6;&#x6001;
    const [num, setNum] = useState(0);
    // useEffect&#x526F;&#x4F5C;&#x7528;
    useEffect(() => {
        pageStore.qryTableDate();
    }, []);
    return (
        <div classname="page-home page-content">
            <h2>{pageStore.pageTitle}</h2>
            <div>
                <span>num&#x503C;&#xFF1A;{num}</span>
                <button 10 type="primary" size="small" style="{{" marginleft: }} onclick="{()" => setNum(num + 1)}
                >+1</button>
            </div>
        </div>
    );
};
export default observer(HomePage);

5.Router路由配置

该项目为单页面应用,路由配置一般分为约定动态路由和集中配置路由。

[En]

The project is a single-page application, and routing configuration is generally divided into agreed dynamic routing and centralized configuration routing.

在 React 的世界里,直接采用成熟的react-router工具管理页面路由。我们现在说到react-router,基本上都是在说 react-router 的第4版之后的版本,当前的最新版本已经更新到5.1.x了。
当前react-router支持动态路由,完全用React组件来实现路由,在渲染过程中动态设置路由规则,匹配命中规则加载对应页面组件。
本项目采用集中配置路由(方便的路由认证、从服务器界面获取菜单路由配置等),同时方便地设置侧菜单栏。当然,为了简单起见,项目中读取了本地静态菜单配置,还没有引入路由身份验证。

[En]

This project adopts centralized configuration routing (convenient route authentication, obtaining menu routing configuration from the server interface, etc.), while conveniently setting the side menu bar. Of course, for simplicity, the local static menu configuration is read in the project, and route authentication has not been introduced yet.

6.静态路由配置 src/routes/config.js :

import React, { lazy } from "react";
import BasicLayout from "@/layouts/BasicLayout";
import BlankLayout from "@/layouts/BlankLayout";
const config = [
    {
        path: "/",
        component: BlankLayout, // &#x7A7A;&#x767D;&#x9875;&#x5E03;&#x5C40;
        childRoutes: [ // &#x5B50;&#x83DC;&#x5355;&#x8DEF;&#x7531;
            {
                path: "/login", // &#x8DEF;&#x7531;&#x8DEF;&#x5F84;
                name: "&#x767B;&#x5F55;&#x9875;", // &#x83DC;&#x5355;&#x540D;&#x79F0; (&#x4E0D;&#x8BBE;&#x7F6E;,&#x5219;&#x4E0D;&#x5C55;&#x793A;&#x5728;&#x83DC;&#x5355;&#x680F;&#x4E2D;&#xFF09;
                icon: "setting", // &#x83DC;&#x5355;&#x56FE;&#x6807;
                component: lazy(() => import("@/pages/Login")) // &#x61D2;&#x52A0;&#x8F7D; &#x8DEF;&#x7531;&#x7EC4;&#x4EF6;
            },
            // login&#x7B49;&#x6CA1;&#x6709;&#x83DC;&#x5355;&#x5BFC;&#x822A;&#x680F;&#x7B49;&#x57FA;&#x672C;&#x5E03;&#x5C40;&#x7684;&#x9875;&#x9762;&#xFF0C; &#x8981;&#x653E;&#x5728;&#x57FA;&#x672C;&#x5E03;&#x5C40;BasicLayout&#x4E4B;&#x524D;&#x3002;
            {
                path: "/",
                component: BasicLayout, // &#x57FA;&#x672C;&#x5E03;&#x5C40;&#x6846;&#x67B6;
                childRoutes: [
                    {
                        path: "/welcome",
                        name: "&#x6B22;&#x8FCE;&#x9875;",
                        icon: "smile",
                        component: lazy(() => import("@/pages/Welcome"))
                    },
                    {... /* &#x5176;&#x4ED6; */},
                    { path: "/", exact: true, redirect: "/welcome" },
                    { path: "*", exact: true, redirect: "/exception/404" }
                ]
            }
        ]
    }
];
export default config;

以上是静态路由配置的一部分

[En]

Above is part of the configuration of the static route

注意:中会用包裹,会匹配命中的第一个。”/login”等没有菜单导航栏等基本布局的页面, 要放在基本布局BasicLayout之前。
利用和React.lazy()实现页面组件懒加载。

7.路由组建渲染 src/routes/AppRouter.js :

import React, { lazy, Suspense } from "react";
import LoadingPage from "@/components/LoadingPage";
import {
    HashRouter as Router,
    Route,
    Switch,
    Redirect
} from "react-router-dom";
import config from "./config";
const renderRoutes = routes => {
    if (!Array.isArray(routes)) {
        return null;
    }
    return (
        <switch>
            {routes.map((route, index) => {
                if (route.redirect) {
                    return (
                        <redirect key="{route.path" || index} exact="{route.exact}" strict="{route.strict}" from="{route.path}" to="{route.redirect}">
                    );
                }
                return (
                    <route key="{route.path" || index} path="{route.path}" exact="{route.exact}" strict="{route.strict}" render="{()" => {
                            const renderChildRoutes = renderRoutes(route.childRoutes);
                            if (route.component) {
                                return (
                                    <suspense fallback="{<LoadingPage">}>
                                        <route.component route="{route}">
                                            {renderChildRoutes}
                                        </route.component>
                                    </suspense>
                                );
                            }
                            return renderChildRoutes;
                        }}
                    />
                );
            })}
        </route></redirect></switch>
    );
};
const AppRouter = () => {
    return <router>{renderRoutes(config)}</router>;
};
export default AppRouter;

8.路由 hooks 语法

react-router-dom 也已经支持 hooks语法,获取路由信息或路由跳转,可以使用新的hooks 函数:
useHistory:获取历史路由,回退、跳转等操作;
• useLocation:查看当前路由信息;
useParams:读取路由附带的params参数信息;
useRouteMatch:匹配当前路由;
只要包含子组件,就可以通过这些钩子函数获取路由信息。

[En]

As long as the subcomponents are wrapped in, you can get the routing information through these hook functions.

代码演示:

import { useHistory } from "react-router-dom";
function HomeButton() {
    const history = useHistory();
    function onClick() {
        history.push("/home");
    }
    return (
        <button type="button" onclick="{onClick}">
            &#x8DF3;&#x8F6C;Home&#x9875;
        </button>
    );
}

9.结合mobx管理数据状态

是否使用状态管理工具或在项目中使用哪些管理工具取决于项目的实际情况。

[En]

Whether or not to use state management tools or which management tools are used in the project depends on the actual project situation.

本项目使用自己比较熟悉的Mobx,Mobx是一个功能强大,上手非常容易的状态管理工具。
为了简洁和易于管理,将其分为全局公共数据状态和页面数据状态。

[En]

In order to be concise and easy to manage, it is divided into global public data state and page data state.

公用数据状态存放在/src/stores目录下;页面几数据存放于对应页面目录下。
在实现上,利用mobx + useContext Hook特性 实现函数式组件的状态管理。
具体在于利用React的createdContext构建包含Mobx 的context上下文;函数式组件中使用useContext Hook 订阅Mobx数据变化。
• 页面级store.js 代码:

import { createContext } from "react";
import { observable, action, computed } from "mobx";
import request from "@/services/newRequest";
class HomeStore {
    @observable tableData = [];
    @observable pageTitle = "Home&#x4E3B;&#x9875;";
    @observable loading = false;
    @action.bound setData(data = {}) {
        Object.entries(data).forEach(item => {
            this[item[0]] = item[1];
        });
    }
    // &#x5217;&#x8868;&#x6570;&#x636E;
    @action.bound
    async qryTableDate(page = 1, size = 10) {
        this.loading = true;
        const res = await request({
            url: "/list",
            method: "post",
            data: { page, size }
        });
        if (res.success) {
            const resData = res.data || {};
            console.log(resData);
        }
        this.loading = false;
    }
}
export default createContext(new HomeStore());

• 页面组件代码 :

import React, { useContext } from "react";
import { observer } from "mobx-react";
import Store from "./store";
import "./style.less";
const HomePage = () => {
    const pageStore = useContext(Store);
    return (
        <div classname="page-home page-content">
            home&#x9875;&#x9762;
            <h2>{pageStore.pageTitle}</h2>
        </div>
    );
};

export default observer(HomePage);
以上是演示代码的一部分。您可以查看特定业务实现的项目代码。

[En]

The above is part of the demo code. You can view the project code for the specific business implementation.

10.Axios Http 请求封装

Axios请求封装,具体代码见 /src/services/newRequest.js

11.UI组件及页面布局

UI组件使用优秀的Ant Design 组件库,注意使用 babel-plugin-import 配置实现组件的按需加载。
本项目的内部页面布局采用 Antd 上经典的布局方式:

快速构建Web应用,从零学习React后台项目模版
页面布局需要合理拆分模块,左侧菜单导航栏根据静态菜单渲染。实际完整代码详见项目,以下为BasicLayout组件:
import React from "react";
import { Layout } from "antd";
import SiderMenu from "../SiderMenu";
import MainHeader from "../MainHeader";
import MainFooter from "../MainFooter";
import "./style.less";
const BasicLayout = ({ route, children }) => {
    return (
        <layout classname="main-layout">
            {/* &#x5DE6;&#x4FA7;&#x83DC;&#x5355;&#x5BFC;&#x822A; */}
            <sidermenu routes="{route.childRoutes}">
            <layout classname="main-layout-right">
                {/* &#x9876;&#x90E8;&#x5C55;&#x793A;&#x5E03;&#x5C40; */}
                <mainheader></mainheader>
                <layout.content classname="main-layout-content">
                    {/* &#x5B9E;&#x9645;&#x9875;&#x9762;&#x5E03;&#x5C40; */}
                    {children}
                    {/* <mainfooter></mainfooter> */}
                </layout.content>
            </layout>
        </sidermenu></layout>
    );
};
export default BasicLayout;

对于登录页等页面无需套在上面的基本布局之类,需要单独处理(菜单配置在BasicLayout配置之前)。

快速构建Web应用,从零学习React后台项目模版

三 、云端一键部署上线应用

1.上传代码

git add .
git commit -m '&#x6DFB;&#x52A0;&#x4F60;&#x7684;&#x6CE8;&#x91CA;'
git push

2.在日常环境部署

只需一次点击即可部署应用程序。在应用详情页点击日常环境中的[部署]按钮,即可一键部署。部署状态变为绿色后,可点击访问部署网站查看结果。

[En]

Deploy the application with one click. Click the “deploy” button in the daily environment on the application details page to deploy with one click. After the deployment status has changed to green, you can click to visit the deployment website to view the results.

快速构建Web应用,从零学习React后台项目模版

3.配置自定义域名在线上环境上线

• 配置线上环境自定义域名。在功能开发验证完成后要在线上环境进行部署,在线上环境的「部署配置」-「自定义域名」中填写自己的域名。例如我们添加一个二级域名 company.workbench.fun 来绑定我们部署的前端应用。然后复制自定义域名下方的API网关地址对添加的二级域名进行CNAME配置。

快速构建Web应用,从零学习React后台项目模版
• 配置CNAME地址。复制好 API网关域名地址后,来到你自己的域名管理平台(此示例中的域名管理是阿里云的域名管理控制台,请去自己的域名控制台操作)。添加记录的「记录类型」选择「CNAME」,在「主机记录」中输入你要创建的二级域名,这里我们输入「company」,在「记录值」中粘贴我们之前复制的 API网关域名地址,「TTL」保留默认值或者设置一个你认为合适的值即可。
快速构建Web应用,从零学习React后台项目模版
• 在线上环境部署上线。回到云开发平台的应用详情页面,按照部署的操作,点击线上环境的「部署按钮」,部署完成以后就在你自定义的域名进行了上线。CNAME 生效之后,我们输入 company.workbench.fun(示例网址) 可以打开部署的页面。至此,如何部署一个应用到线上环境,如何绑定自己的域名来访问一个线上的应用就完成了,赶紧部署自己的应用到线上环境,用自己的域名玩起来吧 ;)
快速构建Web应用,从零学习React后台项目模版
一键创建React应用模版链接 :https://workbench.aliyun.com/application/front/create?fromConfig=12&fromRepo=sol_github_12

参考文献:https://juejin.cn/post/6844904035099623437

Original: https://www.cnblogs.com/yunzhishu/p/16086882.html
Author: 云知树
Title: 快速构建Web应用,从零学习React后台项目模版

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/523908/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux 安装Apache2和PHP

    首先先更新系统 sudo apt update; sudo apt upgrade 然后下载Apache2和PHP主要程序以及它的插件 sudo apt install apach…

    Linux 2023年6月7日
    091
  • 节约内存:Instagram的Redis实践(转)

    1.M emcached 内存Key-Value Cache Redis 内存数据库 四,节约内存:Instagram的Redis实践 Instagram可以说是网拍App的始祖级…

    Linux 2023年5月28日
    094
  • Mysql安装

    linux系统,Mysql安装,用户登录、密码修改。 Mysql安装 环境 ubuntu 20.04 安装 安装服务 sudo apt install mysql-server 启…

    Linux 2023年6月13日
    085
  • 【Example】C++ 标准库多线程同步及数据共享 (std::future 与 std::promise)

    否则你会像听天书一样懵。(…) ==================================== 在任何语言的多线程编程当中,必然涉及线程的同步及数据的共享,方…

    Linux 2023年6月13日
    0105
  • Linux驱动编程1——内核编译

    1.安装必要的内核开发包,包括gcc、make、libncurses-dev。 $ apt-get install gcc make libncurses-dev 2.$ make…

    Linux 2023年6月8日
    094
  • Centos8 设置中文

    1、一般情况 1.1 进入设置选择 Region&Language 1.2 点击 加号 1.3 点击 汉语(中国) 1.4 选择 汉语(智能拼音) 2、特殊情况 有些虚拟机…

    Linux 2023年5月27日
    0116
  • 聊斋-河间生

    人的善恶在转瞬之间就可以改变,发现错误时往往已经差之千里了,但是发现错误及时改正这不也是很美好的一件事情么?河间生就是讲了这么一件事情。 主角简介:河间某生,家里比较富裕,烧火用的…

    Linux 2023年6月14日
    0121
  • 机器学习学习笔记之二:决策树

    使用决策树算法的基本思路 划分数据集,使被划分的特征作为决策树的节点。通常采用二叉树(也可以采用非二叉树)作为最终形成的决策树形式,即将数据集按照某个特征进行划分成两个子数据集,并…

    Linux 2023年6月14日
    072
  • 版本控制gitlab

    版本控制gitlab 版本控制gitlab 版本控制介绍 常用的版本控制工具: gitlab部署 gitlab网页界面的基本使用 使用命令行的方式进行上传文件 版本控制介绍 版本控…

    Linux 2023年6月6日
    0120
  • Nginx 配置文件说明

    bash;gutter:true;</p> <h1>定义Nginx运行的用户和用户组</h1> <p>user www www;&l…

    Linux 2023年6月8日
    093
  • win11下关于安装umi成功后CMD命令不能使用的问题

    先找到你安装的umi全局路径 yarn global bin 然后把这个路径添加到系统变量中去:PATH 还是不能用的话就是找到 umi.cmd 文件的目录,把里面的C盘符号前面的…

    Linux 2023年6月14日
    0109
  • 2021年想做的最后挣扎

    一年的时间转眼间就过完,感觉没变,又感觉跟一年前的今天变化还是蛮多的,树立个小目标争取年前完成把 读书一本书看一篇文章: 《百年孤独》:我总感觉虽然是只单身狗是孤单的,理解不了孤独…

    Linux 2023年6月14日
    084
  • MSSQL·FOR XML PATH语法转义尖括号解决方案

    阅文时长 | 0.14分钟字数统计 | 225.6字符主要内容 | 1、引言&背景 2、示例及解决方案 3、声明与参考资料『MSSQL·FOR XML PATH语法转义尖括…

    Linux 2023年6月14日
    085
  • redis 安装和命令

    转自:https://blog.csdn.net/hzlarm/article/details/99432240 在线安装: 查看使用的默认端口: 查看redis服务器的状态: 重…

    Linux 2023年5月28日
    087
  • Nginx/Tengine安装配置详解

    1 概念 Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。官方测试…

    Linux 2023年5月27日
    0137
  • git 的使用

    git 的使用 1、介绍 代码版本管理、协同开发 对文件(代码)进行版本管理 完成协同开发 项目,帮助程序员整合代码 i)帮助开发者合并开发的代码 ii)如果出现冲突代码的合并,会…

    Linux 2023年6月14日
    090
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球