大白话react第十五章React 应用性能优化深度实践

大白话react第十五章React 应用性能优化深度实践

1. React 服务端渲染(SSR)的深入运用
  • 白话解释:之前咱们做的网页大多是在浏览器里把页面一点点搭建起来,这得花点时间。服务端渲染呢,就是让服务器提前把网页组装好,直接发给浏览器,这样页面打开的速度就快多啦,用户体验也更好。
  • 代码示例:用 Next.js 这个框架来做服务端渲染。Next.js 是基于 React 的,能很方便地实现服务端渲染。
jsx 复制代码
// pages/index.js
// 引入 React 库
import React from'react';

// 定义一个函数组件,这就是我们要渲染的页面
const HomePage = () => {
    return (
        // 返回一个包含标题和段落的 JSX 元素
        <div>
            <h1>欢迎来到我的网站</h1>
            <p>这是一个使用 Next.js 进行服务端渲染的页面</p>
        </div>
    );
};

// 导出这个组件,Next.js 会自动处理它的渲染
export default HomePage;
2. React 与状态管理库 MobX 的搭配
  • 白话解释:在 React 应用里,有些数据在很多组件里都会用到,管理起来有点麻烦。MobX 就像一个大管家,能把这些数据统一管理,让各个组件都能方便地获取和修改这些数据。
  • 代码示例
jsx 复制代码
// 安装 mobx 和 mobx-react 库
// npm install mobx mobx-react

// stores/counterStore.js
// 引入 mobx 中的 observable 和 action
import { makeObservable, observable, action } from'mobx';

// 定义一个计数器的状态管理类
class CounterStore {
    // 定义一个可观察的状态,初始值为 0
    count = 0;

    constructor() {
        // 让这个类的属性和方法具有 mobx 的特性
        makeObservable(this, {
            count: observable,
            increment: action,
            decrement: action
        });
    }

    // 定义一个增加计数的动作
    increment = () => {
        this.count++;
    };

    // 定义一个减少计数的动作
    decrement = () => {
        this.count--;
    };
}

// 创建一个计数器状态管理的实例
const counterStore = new CounterStore();

// 导出这个实例,方便其他组件使用
export default counterStore;
jsx 复制代码
// components/Counter.js
// 引入 React 和 mobx-react 中的 observer
import React from'react';
import { observer } from'mobx-react';
// 引入上面定义的计数器状态管理实例
import counterStore from '../stores/counterStore';

// 使用 observer 包裹组件,让组件能响应状态的变化
const Counter = observer(() => {
    return (
        <div>
            <p>当前计数: {counterStore.count}</p>
            <button onClick={counterStore.increment}>增加</button>
            <button onClick={counterStore.decrement}>减少</button>
        </div>
    );
});

// 导出这个组件
export default Counter;
3. React 中自定义 Hooks 的开发
  • 白话解释:自定义 Hooks 就像是你自己做的工具,能把一些常用的逻辑封装起来,在不同的组件里都能复用。这样可以让代码更简洁,也更好维护。
  • 代码示例
jsx 复制代码
// hooks/useLocalStorage.js
// 引入 React 的 useState 和 useEffect
import React, { useState, useEffect } from'react';

// 定义一个自定义 Hook,用于在本地存储中管理数据
const useLocalStorage = (key, initialValue) => {
    // 使用 useState 来管理数据,初始值从本地存储中获取,如果没有则使用传入的初始值
    const [value, setValue] = useState(() => {
        const storedValue = localStorage.getItem(key);
        return storedValue? JSON.parse(storedValue) : initialValue;
    });

    // 使用 useEffect 来监听 value 的变化,当 value 变化时更新本地存储
    useEffect(() => {
        localStorage.setItem(key, JSON.stringify(value));
    }, [key, value]);

    // 返回一个数组,包含数据和修改数据的函数
    return [value, setValue];
};

// 导出这个自定义 Hook
export default useLocalStorage;
jsx 复制代码
// components/StorageExample.js
// 引入 React 和上面定义的自定义 Hook
import React from'react';
import useLocalStorage from '../hooks/useLocalStorage';

// 定义一个使用自定义 Hook 的组件
const StorageExample = () => {
    // 使用自定义 Hook 来管理本地存储中的数据,初始值为 '默认值'
    const [storedValue, setStoredValue] = useLocalStorage('myData', '默认值');

    return (
        <div>
            <p>本地存储的值: {storedValue}</p>
            <input
                type="text"
                value={storedValue}
                onChange={(e) => setStoredValue(e.target.value)}
            />
        </div>
    );
};

// 导出这个组件
export default StorageExample;
4. React 应用的性能调优实战
  • 白话解释:有时候我们做的 React 应用打开速度慢,或者操作起来不流畅。性能调优就是找出这些问题,然后想办法让应用跑得更快、更顺滑。
  • 代码示例 :使用 React.memo 来避免不必要的组件渲染。
jsx 复制代码
// components/MyComponent.js
// 引入 React
import React from'react';

// 定义一个普通的函数组件
const MyComponent = ({ name }) => {
    console.log('组件渲染了');
    return <p>你好,{name}</p>;
};

// 使用 React.memo 包裹组件,只有当 name 属性变化时才重新渲染
const MemoizedComponent = React.memo(MyComponent);

// 导出这个经过优化的组件
export default MemoizedComponent;
jsx 复制代码
// App.js
// 引入 React 和上面优化后的组件
import React, { useState } from'react';
import MemoizedComponent from './components/MyComponent';

// 定义一个父组件
const App = () => {
    // 使用 useState 来管理一个布尔值状态
    const [toggle, setToggle] = useState(false);
    // 定义一个固定的名字
    const name = '张三';

    return (
        <div>
            <button onClick={() => setToggle(!toggle)}>切换</button>
            {/* 使用优化后的组件 */}
            <MemoizedComponent name={name} />
        </div>
    );
};

// 导出这个父组件
export default App;
5. React 与物联网(IoT)设备的交互
  • 白话解释:现在物联网设备很多,像智能手环、智能灯泡啥的。我们可以让 React 做的网页和这些设备交互,比如在网页上控制智能灯泡的开关和亮度。
  • 代码示例:模拟和一个物联网设备通信,实际中要根据具体设备的 API 来修改。
jsx 复制代码
// components/IoTDeviceControl.js
// 引入 React 和 useState
import React, { useState, useEffect } from'react';

// 定义一个和物联网设备交互的组件
const IoTDeviceControl = () => {
    // 使用 useState 来管理设备的状态,初始状态为关闭
    const [deviceStatus, setDeviceStatus] = useState('关闭');

    // 模拟和物联网设备通信的函数
    const toggleDevice = async () => {
        // 这里应该是实际的网络请求,和设备的 API 交互
        // 为了简单,我们用 setTimeout 模拟请求
        await new Promise((resolve) => setTimeout(resolve, 1000));
        setDeviceStatus(deviceStatus === '打开'? '关闭' : '打开');
    };

    return (
        <div>
            <p>设备状态: {deviceStatus}</p>
            <button onClick={toggleDevice}>切换设备状态</button>
        </div>
    );
};

// 导出这个组件
export default IoTDeviceControl;

通过学习这些内容,你就能在 React 的世界里更上一层楼,做出更厉害、更实用的应用啦!

1. React 与 WebGL 结合打造 3D 交互界面
  • 白话解释:平常咱们做的网页大多是平平的 2D 界面,WebGL 就像是给网页加了个 3D 魔法,能让网页里出现立体的东西,还能和这些 3D 物体互动。咱们要学怎么把 React 和 WebGL 结合起来,做出超酷炫的 3D 网页界面。
  • 代码示例 :使用 react-three-fiber 库,它能让咱们在 React 里轻松用 WebGL 创建 3D 场景。
jsx 复制代码
// 引入 React 库
import React from'react';
// 引入 react-three-fiber 里的 Canvas 组件,用来创建 3D 画布
import { Canvas } from '@react-three/fiber';
// 引入 mesh 和 boxGeometry 等,用来创建 3D 物体
import { Mesh, BoxGeometry, MeshBasicMaterial } from 'three';

// 定义一个 3D 场景组件
const Scene = () => {
    return (
        <Canvas>
            {/* 创建一个 3D 立方体 */}
            <Mesh>
                {/* 定义立方体的形状 */}
                <BoxGeometry args={[1, 1, 1]} />
                {/* 定义立方体的材质和颜色 */}
                <MeshBasicMaterial color="hotpink" />
            </Mesh>
        </Canvas>
    );
};

// 导出这个组件,方便其他地方使用
export default Scene;
2. React 与机器学习模型的集成
  • 白话解释:机器学习能让电脑像人一样学习和判断,比如识别图片里的东西、预测数据。咱们要把 React 和机器学习模型结合起来,让网页能用上机器学习的能力。举个例子,做个网页能上传图片,然后用机器学习模型识别图片里是啥。
  • 代码示例 :使用 tensorflow.js 库在 React 里运行简单的机器学习模型。
jsx 复制代码
// 引入 React 和 useState 钩子
import React, { useState, useEffect } from'react';
// 引入 tensorflow.js 库
import * as tf from '@tensorflow/tfjs';

// 定义一个使用机器学习的组件
const MLComponent = () => {
    // 用 useState 来管理预测结果,初始为空
    const [prediction, setPrediction] = useState('');

    useEffect(() => {
        const runModel = async () => {
            // 加载一个简单的线性回归模型
            const model = tf.sequential();
            model.add(tf.layers.dense({ units: 1, inputShape: [1] }));
            model.compile({ optimizer: 'sgd', loss: 'meanSquaredError' });

            // 准备训练数据
            const xs = tf.tensor2d([1, 2, 3, 4], [4, 1]);
            const ys = tf.tensor2d([2, 4, 6, 8], [4, 1]);

            // 训练模型
            await model.fit(xs, ys, { epochs: 10 });

            // 进行预测
            const input = tf.tensor2d([5], [1, 1]);
            const output = model.predict(input);
            const outputValue = await output.data();
            setPrediction(outputValue[0].toString());
        };

        runModel();
    }, []);

    return (
        <div>
            <p>预测结果: {prediction}</p>
        </div>
    );
};

// 导出这个组件
export default MLComponent;
3. React 项目的自动化测试框架搭建
  • 白话解释:写代码的时候难免会出错,手动一个个检查太麻烦还容易漏。自动化测试框架就像是一个自动检查官,能自动运行一些测试,帮咱们找出代码里的问题,保证代码质量。
  • 代码示例:用 Jest 和 React Testing Library 搭建测试框架。
jsx 复制代码
// components/Button.js
// 引入 React
import React from'react';

// 定义一个简单的按钮组件
const Button = ({ text, onClick }) => {
    return (
        <button onClick={onClick}>
            {text}
        </button>
    );
};

// 导出这个按钮组件
export default Button;
jsx 复制代码
// __tests__/Button.test.js
// 引入 React Testing Library 里的 render 和 screen
import { render, screen } from '@testing-library/react';
// 引入要测试的按钮组件
import Button from '../components/Button';

// 写一个测试用例,看看按钮能不能正常显示文字
test('按钮能显示文字', () => {
    // 渲染按钮组件
    render(<Button text="点击我" onClick={() => {}} />);
    // 在屏幕上查找包含 '点击我' 文字的按钮
    const buttonElement = screen.getByText('点击我');
    // 断言按钮元素存在
    expect(buttonElement).toBeInTheDocument();
});
4. React 微前端架构的实战应用
  • 白话解释:大型的网页应用就像一个大商场,里面有好多不同的店铺。微前端架构就是把这个大商场拆分成一个个小店铺,每个小店铺可以独立开发、独立部署。这样开发起来更方便,不同的团队可以同时开发不同的部分。
  • 代码示例 :使用 single-spa 实现简单的微前端架构。
jsx 复制代码
// 主应用(root-config.js)
// 引入 single-spa 库
import { registerApplication, start } from'single-spa';

// 注册一个微前端应用
registerApplication({
    // 应用的名字
    name: '@my-org/micro-frontend',
    // 加载应用的函数
    app: () => System.import('@my-org/micro-frontend'),
    // 决定什么时候加载应用的函数
    activeWhen: ['/micro-frontend']
});

// 启动 single-spa
start();
jsx 复制代码
// 微前端应用(src/index.js)
// 引入 single-spa-react 里的 singleSpaReact
import singleSpaReact from'single-spa-react';
// 引入 React 和要渲染的根组件
import React from'react';
import ReactDOM from'react-dom/client';
import Root from './Root';

// 创建一个生命周期函数
const lifecycles = singleSpaReact({
    React,
    ReactDOM,
    rootComponent: Root,
    // 可选的,设置加载中显示的内容
    loadingComponent: () => <div>加载中...</div>
});

// 导出生命周期函数,供主应用使用
export const { bootstrap, mount, unmount } = lifecycles;
5. React 应用的国际化与本地化
  • 白话解释:要是咱们做的网页想让全世界的人都能用,就得支持不同的语言和文化习惯。国际化和本地化就是让网页能根据用户所在的地区和语言,显示不同的文字和格式。比如在中国显示中文,在美国显示英文。
  • 代码示例 :使用 react-i18next 库实现国际化。
jsx 复制代码
// i18n.js
// 引入 i18n 库和一些插件
import i18n from 'i18next';
import { initReactI18next } from'react-i18next';
// 引入不同语言的翻译文件
import translationEN from './locales/en/translation.json';
import translationZH from './locales/zh/translation.json';

// 配置 i18n
i18n
  .use(initReactI18next)
  .init({
      // 默认语言
      lng: 'en',
      // 回退语言
      fallbackLng: 'en',
      // 资源,包含不同语言的翻译内容
      resources: {
          en: {
              translation: translationEN
          },
          zh: {
              translation: translationZH
          }
      },
      interpolation: {
          escapeValue: false
      }
  });

// 导出配置好的 i18n
export default i18n;
jsx 复制代码
// App.js
// 引入 React 和 useTranslation 钩子
import React from'react';
import { useTranslation } from'react-i18next';
// 引入配置好的 i18n
import './i18n';

// 定义一个使用国际化的组件
const App = () => {
    // 使用 useTranslation 钩子获取 t 函数,用于翻译文字
    const { t } = useTranslation();

    return (
        <div>
            {/* 使用 t 函数翻译文字 */}
            <h1>{t('欢迎来到我的网站')}</h1>
        </div>
    );
};

// 导出这个组件
export default App;

通过学习这些内容,你就能在 React 的道路上越走越远,做出功能超强大、体验超棒的网页应用啦!

除了react-three-fiber库,还有哪些库可以用于React和WebGL的结合?

除 react - three - fiber 外,可用于 React 和 WebGL 结合的库

1. react - three - drei
  • 白话解释react - three - drei 是基于 react - three - fiber 的一个辅助库,就像是给 react - three - fiber 这个工具盒里又添了好多实用的小工具。它提供了大量预构建的组件和钩子,能让我们更轻松地创建复杂的 3D 场景,不用每次都从头开始写代码。
  • 代码示例
jsx 复制代码
// 引入 React 库
import React from'react';
// 引入 react - three - fiber 里的 Canvas 组件,用于创建 3D 画布
import { Canvas } from '@react - three/fiber';
// 引入 react - three - drei 里的 OrbitControls 和 Stats 组件
import { OrbitControls, Stats } from '@react - three/drei';

// 定义一个 3D 场景组件
const Scene = () => {
    return (
        <Canvas>
            {/* 创建一个球体 */}
            <mesh position={[0, 0, 0]}>
                {/* 定义球体的几何形状 */}
                <sphereGeometry args={[1, 32, 32]} />
                {/* 定义球体的材质 */}
                <meshStandardMaterial color="blue" />
            </mesh>
            {/* 添加轨道控制器,让用户可以用鼠标控制视角 */}
            <OrbitControls />
            {/* 添加性能统计组件,显示帧率等信息 */}
            <Stats />
        </Canvas>
    );
};

// 导出这个组件,方便其他地方使用
export default Scene;
2. react - webgl - three
  • 白话解释react - webgl - three 也是一个能把 React 和 WebGL 结合起来的库。它的特点是简化了在 React 应用里使用 Three.js(一个流行的 WebGL 库)的过程,让我们可以更方便地在 React 组件里创建和管理 3D 场景。
  • 代码示例
jsx 复制代码
// 引入 React 库
import React from'react';
// 引入 react - webgl - three 里的 WebGLRenderer 组件
import { WebGLRenderer } from'react - webgl - three';
// 引入 Three.js 里的一些对象
import * as THREE from 'three';

// 定义一个 3D 场景组件
const WebGLScene = () => {
    // 创建一个场景对象
    const scene = new THREE.Scene();
    // 创建一个相机对象
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    // 创建一个渲染器对象
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);

    // 创建一个立方体的几何形状
    const geometry = new THREE.BoxGeometry();
    // 创建一个材质对象
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    // 创建一个立方体网格对象
    const cube = new THREE.Mesh(geometry, material);
    // 将立方体添加到场景中
    scene.add(cube);

    // 设置相机的位置
    camera.position.z = 5;

    // 定义一个渲染函数
    const render = () => {
        requestAnimationFrame(render);
        // 让立方体旋转
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
        renderer.render(scene, camera);
    };

    // 调用渲染函数
    render();

    return (
        <div>
            {/* 使用 WebGLRenderer 组件渲染场景 */}
            <WebGLRenderer renderer={renderer} />
        </div>
    );
};

// 导出这个组件
export default WebGLScene;
3. react - three - postprocessing
  • 白话解释:这个库主要用于给 3D 场景添加后期处理效果,就像是给照片加滤镜一样。它可以让我们的 3D 场景看起来更炫酷,比如添加模糊、发光、色彩校正等效果。
  • 代码示例
jsx 复制代码
// 引入 React 库
import React from'react';
// 引入 react - three - fiber 里的 Canvas 组件
import { Canvas } from '@react - three/fiber';
// 引入 react - three - postprocessing 里的一些组件
import { EffectComposer, DepthOfField } from '@react - three/postprocessing';

// 定义一个 3D 场景组件
const PostProcessingScene = () => {
    return (
        <Canvas>
            {/* 创建一个球体 */}
            <mesh position={[0, 0, 0]}>
                {/* 定义球体的几何形状 */}
                <sphereGeometry args={[1, 32, 32]} />
                {/* 定义球体的材质 */}
                <meshStandardMaterial color="red" />
            </mesh>
            {/* 添加后期处理效果合成器 */}
            <EffectComposer>
                {/* 添加景深效果 */}
                <DepthOfField focusDistance={1} aperture={0.025} />
            </EffectComposer>
        </Canvas>
    );
};

// 导出这个组件
export default PostProcessingScene;

这些库都能帮助我们在 React 项目里更方便地使用 WebGL 来创建 3D 场景,每个库都有自己的特点和优势,你可以根据项目的具体需求来选择使用。

React与WebGL结合的性能优化方法有哪些?

React 与 WebGL 结合的性能优化方法

1. 场景优化
  • 白话解释:在 WebGL 里,场景就像是一个舞台,舞台上的东西越多越复杂,表演起来就越费劲。所以我们要尽量减少舞台上不必要的东西,让表演更流畅。这就好比打扫房间,把不用的东西都清理掉,活动起来就更方便了。
  • 代码示例
jsx 复制代码
// 引入 React 和 react - three - fiber 的相关组件
import React from'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { Mesh, BoxGeometry, MeshBasicMaterial } from 'three';

// 创建一个简单的 3D 场景组件
const OptimizedScene = () => {
    // 创建一个立方体的引用
    const cubeRef = React.useRef();

    // 使用 useFrame 钩子在每一帧更新立方体的旋转
    useFrame(() => {
        if (cubeRef.current) {
            cubeRef.current.rotation.x += 0.01;
            cubeRef.current.rotation.y += 0.01;
        }
    });

    return (
        <Canvas>
            {/* 创建一个立方体 */}
            <Mesh ref={cubeRef}>
                {/* 定义立方体的几何形状 */}
                <BoxGeometry args={[1, 1, 1]} />
                {/* 定义立方体的材质 */}
                <MeshBasicMaterial color="hotpink" />
            </Mesh>
        </Canvas>
    );
};

export default OptimizedScene;

在这个例子中,我们只创建了一个简单的立方体,没有添加过多复杂的物体,减少了场景的复杂度,从而提高性能。

2. 材质和纹理优化
  • 白话解释:材质和纹理就像是给 3D 物体穿的衣服。如果衣服太大、太复杂,就会让物体变重,影响性能。所以我们要选择合适的材质和纹理,就像给物体选一件轻便又好看的衣服。
  • 代码示例
jsx 复制代码
import React from'react';
import { Canvas } from '@react-three/fiber';
import { Mesh, SphereGeometry, MeshBasicMaterial, TextureLoader } from 'three';

const TextureOptimizedScene = () => {
    // 创建一个纹理加载器
    const textureLoader = new TextureLoader();
    // 加载纹理图片,这里可以选择合适分辨率的图片
    const texture = textureLoader.load('low - res - texture.jpg');

    return (
        <Canvas>
            {/* 创建一个球体 */}
            <Mesh>
                {/* 定义球体的几何形状 */}
                <SphereGeometry args={[1, 32, 32]} />
                {/* 使用加载的纹理作为材质 */}
                <MeshBasicMaterial map={texture} />
            </Mesh>
        </Canvas>
    );
};

export default TextureOptimizedScene;

这里我们使用 TextureLoader 加载纹理,并且选择了低分辨率的图片,减少了纹理的内存占用,提高性能。

3. 批处理与合并几何体
  • 白话解释:在 WebGL 里,每次绘制一个物体都要花费一定的时间。如果有很多小物体,一个个绘制就会很慢。批处理和合并几何体就像是把很多小零件组装成一个大零件,一次绘制完成,这样能节省时间。
  • 代码示例
jsx 复制代码
import React from'react';
import { Canvas } from '@react-three/fiber';
import { BufferGeometry, BufferAttribute, Mesh, MeshBasicMaterial } from 'three';

const BatchScene = () => {
    // 创建一个自定义的几何体
    const geometry = new BufferGeometry();

    // 定义顶点数据
    const positions = new Float32Array([
        0, 0, 0,
        1, 0, 0,
        0, 1, 0
    ]);

    // 设置顶点属性
    geometry.setAttribute('position', new BufferAttribute(positions, 3));

    return (
        <Canvas>
            {/* 创建多个使用相同几何体的网格 */}
            <Mesh geometry={geometry}>
                <MeshBasicMaterial color="blue" />
            </Mesh>
            <Mesh geometry={geometry} position={[2, 0, 0]}>
                <MeshBasicMaterial color="red" />
            </Mesh>
        </Canvas>
    );
};

export default BatchScene;

在这个例子中,我们创建了一个自定义的几何体,然后让多个网格使用这个几何体,实现了批处理,减少了绘制调用的次数。

4. 相机和视锥体剔除
  • 白话解释:相机就像是我们的眼睛,只能看到前面一定范围内的东西。在 WebGL 里,我们可以让程序只绘制相机能看到的东西,看不到的就不画了,这样能节省很多计算资源。
  • 代码示例
jsx 复制代码
import React from'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { Mesh, BoxGeometry, MeshBasicMaterial, PerspectiveCamera } from 'three';

const CullingScene = () => {
    // 创建一个相机的引用
    const cameraRef = React.useRef();

    useFrame(() => {
        if (cameraRef.current) {
            // 可以在这里更新相机的位置和角度
            cameraRef.current.position.x += 0.01;
        }
    });

    return (
        <Canvas>
            {/* 创建一个透视相机 */}
            <PerspectiveCamera ref={cameraRef} position={[0, 0, 5]} />
            {/* 创建一个立方体 */}
            <Mesh>
                <BoxGeometry args={[1, 1, 1]} />
                <MeshBasicMaterial color="green" />
            </Mesh>
        </Canvas>
    );
};

export default CullingScene;

在这个例子中,我们创建了一个相机,并且可以通过更新相机的位置和角度,让程序只绘制相机能看到的物体,实现视锥体剔除。

5. 动画优化
  • 白话解释:动画就像是物体的运动表演。如果表演的动作太复杂,电脑就会忙不过来。所以我们要简化动画的动作,让表演更轻松。
  • 代码示例
jsx 复制代码
import React from'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { Mesh, SphereGeometry, MeshBasicMaterial } from 'three';

const AnimationOptimizedScene = () => {
    // 创建一个球体的引用
    const sphereRef = React.useRef();

    useFrame(() => {
        if (sphereRef.current) {
            // 简单的旋转动画,减少计算量
            sphereRef.current.rotation.x += 0.005;
        }
    });

    return (
        <Canvas>
            {/* 创建一个球体 */}
            <Mesh ref={sphereRef}>
                <SphereGeometry args={[1, 32, 32]} />
                <MeshBasicMaterial color="yellow" />
            </Mesh>
        </Canvas>
    );
};

export default AnimationOptimizedScene;

这里我们只给球体添加了一个简单的旋转动画,减少了动画的复杂度,提高了性能。

React与WebGL结合的实战项目

React 与 WebGL 结合实战项目介绍

项目背景和目标

平常咱们做的网页大多是二维平面的,画面比较单调。WebGL 就像是给网页开了个"3D 特效外挂",能让网页呈现出炫酷的三维效果。咱们要把 React 和 WebGL 结合起来,做一个简单的 3D 立方体旋转展示的网页,让用户能直观看到 3D 物体的动态效果。

项目准备

要做这个项目,得先安装一些必要的库。主要用到 react-three-fiber,它是一个基于 React 的 WebGL 渲染库,能让我们在 React 里轻松创建 3D 场景;还有 three.js,它是 WebGL 的底层库,提供了很多 3D 相关的功能。可以用下面的命令来安装:

bash 复制代码
npm install @react-three/fiber three
代码实现
jsx 复制代码
// 引入 React 库,因为我们要用 React 来构建组件
import React, { useRef, useEffect } from'react';
// 引入 react-three-fiber 里的 Canvas 组件,这个组件就像是一个 3D 画布,我们可以在上面绘制 3D 物体
import { Canvas } from '@react-three/fiber';
// 引入 three.js 里的 OrbitControls 控件,它能让我们用鼠标控制 3D 场景的视角,比如旋转、缩放等
import { OrbitControls } from '@react-three/drei';

// 定义一个 3D 场景组件
const Scene = () => {
    // 使用 useRef 钩子创建一个引用,用来获取立方体对象,方便后续操作
    const cubeRef = useRef();

    // 使用 useEffect 钩子,它会在组件渲染完成后执行,就像一个小助手,帮我们做一些初始化和后续操作
    useEffect(() => {
        // 定义一个动画函数,这个函数会在每一帧被调用,实现立方体的旋转效果
        const animate = () => {
            // 通过 requestAnimationFrame 函数不断调用自身,形成一个循环,实现动画效果
            requestAnimationFrame(animate);
            // 让立方体在 x 轴上每秒旋转 0.01 弧度
            cubeRef.current.rotation.x += 0.01;
            // 让立方体在 y 轴上每秒旋转 0.01 弧度
            cubeRef.current.rotation.y += 0.01;
        };
        // 调用动画函数,开始动画
        animate();
    }, []);

    return (
        // 使用 Canvas 组件创建 3D 画布
        <Canvas>
            {/* 定义环境光,让整个场景都有亮度,不然会黑漆漆的看不到东西 */}
            <ambientLight intensity={0.5} />
            {/* 定义一个点光源,它就像一个手电筒,能照亮特定的区域,让场景更有立体感 */}
            <pointLight position={[10, 10, 10]} />
            {/* 创建一个立方体 */}
            <mesh ref={cubeRef}>
                {/* 定义立方体的形状,这里设置长、宽、高都为 1 */}
                <boxGeometry args={[1, 1, 1]} />
                {/* 定义立方体的材质和颜色,这里设置为蓝色 */}
                <meshBasicMaterial color="blue" />
            </mesh>
            {/* 添加 OrbitControls 控件,让用户可以用鼠标控制 3D 场景的视角 */}
            <OrbitControls />
        </Canvas>
    );
};

// 定义一个 App 组件,它是整个应用的根组件
const App = () => {
    return (
        <div>
            {/* 在 App 组件里使用我们定义的 3D 场景组件 */}
            <Scene />
        </div>
    );
};

// 导出 App 组件,这样其他文件就可以使用它了
export default App;
代码解释
  1. 引入必要的库和组件 :引入 ReactCanvasOrbitControls,这些是构建 3D 场景的基础。
  2. 创建 Scene 组件
    • useRef 用来获取立方体对象,方便后续对立方体进行操作。
    • useEffect 里定义了 animate 函数,通过 requestAnimationFrame 不断调用自身,实现立方体的旋转效果。
    • return 里,使用 <Canvas> 创建 3D 画布,添加了环境光和点光源让场景有亮度和立体感,创建了一个蓝色的立方体,还添加了 OrbitControls 让用户可以用鼠标控制视角。
  3. 创建 App 组件 :在 App 组件里使用 Scene 组件,把 3D 场景展示出来。
运行项目

把上面的代码保存为 App.js,然后在项目的入口文件(一般是 index.js)里引入并渲染 App 组件:

jsx 复制代码
// 引入 React 库
import React from'react';
// 引入 ReactDOM 库,用于将 React 组件渲染到 DOM 中
import ReactDOM from'react-dom/client';
// 引入我们定义的 App 组件
import App from './App';

// 创建一个根节点,用于挂载 React 应用
const root = ReactDOM.createRoot(document.getElementById('root'));
// 将 App 组件渲染到根节点上
root.render(<App />);

然后在终端里运行项目:

bash 复制代码
npm start

这样就能在浏览器里看到一个旋转的蓝色立方体啦,你还可以用鼠标拖动来改变视角,是不是很酷炫!

相关推荐
乌兰麦朵16 分钟前
Vue吹的颅内高潮,全靠选择性失明和 .value 的PUA!
前端·vue.js
Code季风16 分钟前
Gin Web 层集成 Viper 配置文件和 Zap 日志文件指南(下)
前端·微服务·架构·go·gin
蓝倾17 分钟前
如何使用API接口实现淘宝商品上下架监控?
前端·后端·api
舂春儿18 分钟前
如何快速统计项目代码行数
前端·后端
毛茸茸18 分钟前
⚡ 从浏览器到编辑器只需1秒,这个React定位工具改变了我的开发方式
前端
Pedantic19 分钟前
我们什么时候应该使用协议继承?——Swift 协议继承的应用与思
前端·后端
Software攻城狮20 分钟前
vite打包的简单配置
前端
Codebee20 分钟前
如何利用OneCode注解驱动,快速训练一个私有的AI代码助手
前端·后端·面试
流星稍逝21 分钟前
用vue3的写法结合uniapp在微信小程序中实现图片压缩、调整分辨率、做缩略图功能
前端·vue.js
知了一笑24 分钟前
独立开发问题记录-margin塌陷
前端