【React-Native开发3D应用】React Native加载GLB格式3D模型并打包至Android手机端
【React-Native开发3D应用】React Native加载GLB格式3D模型并打包至Android手机端
- 【加载3D模型】**React Native上如何加载glb格式的模型**
- 第零步,选择相关模型
- 第一步,导入相关模型加载库
- 第二步,自定义GLB模型加载钩子
- 第三步,借助gltf.pmnd.rs与自定义的模型加载钩子加载模型
- 【打包APK】解决**React Native上的打包问题**
- 生成数字签名
- 配置项目以使用签名密钥
- 构建 APK
- 注意事项
- 【3D内容的开发工具】高效率3D内容开发工具
- gltf.report 查看模型信息,调整模型大小
- 本地的`gltfjsx`或者在线的`https://gltf.pmnd.rs/`
- model-viewer
- A-Frame - Make WebVR
- 相关参考
最近在Native上开发3D应用,选用的是React-Native(https://github.com/facebook/react-native),原因如下:
- 开发语言使用JS,和ThreeJS(https://github.com/mrdoob/three.js)的适配性比较好。(Three.js 是一个轻量级的JavaScript库,用于在网页上创建和显示动画的3D计算机图形)
- 多端部署,开发一次,可部署到Android、IOS、Web等平台
但是,这里我们忽略了一个问题,ThreeJS主要用于Web端的3D开发,而移动端这边,虽然React-three-fiber(https://github.com/pmndrs/react-three-fiber)可以可用于react-native的开发
但是还是会存在一些Web端和移动端的库的适配性问题,如下:
- 3D模型的加载,Web端的模型加载非常简单,但是移动端的模型加载可能需要通过一些复杂的手段实现。(甚至打包APK都可能会出现例如3D模型没有打包进去等问题)
- 物理引擎,大部分物理引擎对Web端的适配性比较好,但是很少有支持移动端的物理引擎
这里,我们重点讨论一下如何较好的解决【React Native上3D模型加载和打包的问题】
【加载3D模型】React Native上如何加载glb格式的模型
如果大家之前还没有接触过React Native开发3D应用,可以看一下这篇Youtube。
A Beginner’s Guide to 3D Animations in React Native with three.js
但是这一块有一个问题,就是正常情况下移动端可以较好加载obj格式模型,但是无法像Web端那样直接加载例如glb格式的模型,我在网上找了众多解决办法,一个合理的解释是R3F库的适配性问题,库中的有一些方法无法很好的适用于移动端,你得配合其他的模型加载库。
直到我找到这个Issues,我最终可以很完美的加载glb格式模型:
https://github.com/pmndrs/react-three-fiber/issues/2992
接下来我们梳理一下这个Issues的解题步骤:
第零步,选择相关模型
这里推荐一个模型网站:
Sketchfab - The best 3D viewer on the web
这里我们以网站上的一只滑板兔模型为例,下载好模型:
第一步,导入相关模型加载库
这是我的dependencies:
"dependencies": {"@react-three/drei": "^9.82.1","@react-three/fiber": "^8.14.1","assert": "^2.1.0","base64-arraybuffer": "^1.0.2","expo": "^49.0.0","expo-asset-utils": "^3.0.0","expo-file-system": "^15.4.4","expo-gl": "~13.0.1","r3f-native-orbitcontrols": "^1.0.8","react": "18.2.0","react-native": "0.72.4","three": "^0.156.1","three-stdlib": "^2.25.1"}
第二步,自定义GLB模型加载钩子
我们需要自定义一个模型加载的钩子useGLTFCustom
:
// src\useGLTFCustom.tsx
import assert from 'assert';
import {decode} from 'base64-arraybuffer';
import {resolveAsync} from 'expo-asset-utils';
import * as FileSystem from 'expo-file-system';
import {suspend} from 'suspend-react';
import THREE from 'three';
import {GLTF, GLTFLoader} from 'three-stdlib';async function loadFileAsync({asset,funcName,
}: {asset: unknown;funcName: string;
}) {if (!asset) {throw new Error(`ExpoTHREE.${funcName}: Cannot parse a null asset`);}return (await resolveAsync(asset)).localUri ?? null;
}type ObjectGraph = {nodes: Record<string, THREE.Mesh>;materials: Record<string, THREE.Material>;
};// Collects nodes and materials from a THREE.Object3D
export function buildGraph(object: THREE.Object3D) {const data: ObjectGraph = {nodes: {}, materials: {}};if (object) {object.traverse((obj: any) => {if (obj.name) {data.nodes[obj.name] = obj;}if (obj.material && !data.materials[obj.material.name]) {data.materials[obj.material.name] = obj.material;}});}return data;
}
async function loadGLTFAsync({asset,
}: {asset: unknown;
}): Promise<GLTF & ObjectGraph> {const uri = await loadFileAsync({asset,funcName: 'loadGLTFAsync',});assert(uri, 'loadGLTFAsync uri should exist');const base64 = await FileSystem.readAsStringAsync(uri, {encoding: FileSystem.EncodingType.Base64,});const arrayBuffer = decode(base64);const loader = new GLTFLoader();const res = await loader.parseAsync(arrayBuffer, 'beb');if (res.scene) {Object.assign(res, buildGraph(res.scene));}return res as GLTF & ObjectGraph;
}export const useGLTFCustom = (asset: unknown) =>suspend(async () => loadGLTFAsync({asset}), ['useGLTFCustom', asset]);
第三步,借助gltf.pmnd.rs与自定义的模型加载钩子加载模型
GLTF -> React Three Fiber
这个网站是一个在线工具,它可以将GLTF/GLB模型转换为React Three Fiber组件。通过这个工具,开发者可以轻松地将3D内容转换为JSX组件,这是与React兼容的格式,从而能够便捷地将3D模型集成到网页应用程序中。如下:
以这只滑板兔为例,我们直接复制代码,并修改使用我们自定义的useGLTFCustom
模型加载钩子
// src\assets\Bunny.jsx
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
*/import React from 'react';
import {useGLTFCustom} from '../useGLTFCustom'; // 导入自定义模型加载钩子
import modelPath from './silent_ash_simple.glb';
const Bunny = props => {const {nodes, materials} = useGLTFCustom(modelPath);// console.log('materials:', materials);// console.log('nodes:', nodes);return (<group {...props} dispose={null}><group rotation={[-Math.PI / 2, 0, 0]} scale={0.398}><group rotation={[Math.PI / 2, 0, 0]}><group position={[0.002, 2.616, 0.003]}><meshcastShadowreceiveShadowgeometry={nodes.Object_4.geometry}material={materials.Bunny}/><meshcastShadowreceiveShadowgeometry={nodes.Object_5.geometry}material={materials.Skateboard}/></group></group></group></group>);
};export default Bunny;
然后直接在App.tsx中引用即可
import React, {Suspense} from 'react';
import {Canvas} from '@react-three/fiber/native';
import {StyleSheet, View} from 'react-native';
import useControls from 'r3f-native-orbitcontrols'; // 3D 视图控制轨道
import Bunny from './src/assets/Bunny'; // 导入3D模型的jsxconst App = () => {const [OrbitControls, events] = useControls();return (<View style={styles.container} {...events}><Canvas><OrbitControls enableZoom={false} enablePan={false} /><ambientLight intensity={2} /><directionalLight position={[0, 1, 0]} args={['white', 2]} /><Suspense fallback={null}><Bunny /></Suspense></Canvas></View>);
};export default App;const styles = StyleSheet.create({container: {flex: 1, backgroundColor: 'white'},
});
可以看到这个是手机端的一个效果,也是非常不错!
【打包APK】解决React Native上的打包问题
生成数字签名
keytool -genkeypair -v -keystore boardrop.keystore -alias boardrop -keyalg RSA -keysize 2048 -validity 10000
keytool
命令是用于生成和管理密钥库的,它是 Java Development Kit (JDK) 的一部分。
这个命令使用 Java 的 keytool
工具来生成一个新的密钥库(keystore)和密钥对(key pair),通常用于为 Android 应用程序签名。下面是对该命令每个参数的详细解释:
keytool
: 这是 Java 开发工具包(JDK)提供的一个命令行工具,用于管理密钥和证书。genkeypair
: 这个选项指示keytool
生成一个新的密钥对(即一个公钥和一个私钥)。v
: 表示在执行过程中输出详细信息(verbose output),帮助你了解keytool
在做什么。keystore boardrop.keystore
: 这指定了密钥库的文件名。如果该文件不存在,keytool
将会创建一个新文件。如果没有指定路径,它将被创建在命令执行的当前目录中。alias boardrop
: 这是你为密钥对设置的别名。在签名 Android 应用时,你将使用这个别名来引用密钥库中的密钥对。keyalg RSA
: 指定密钥算法为 RSA。这是一种公钥加密算法,广泛用于 SSL/TLS 和数字签名。keysize 2048
: 这指定了密钥的大小。2048 位是一个常用的大小,它提供了足够的安全性。validity 10000
: 这指定了证书的有效期(以天为单位)。在这个例子中,密钥对和其生成的证书将在大约 27 年后过期。对于 Android 应用的签名密钥,Google 建议至少设置为 25 年的有效期,以确保密钥的有效期超过任何应用的预期寿命。
执行该命令时,它会提示你输入密钥库的密码,这是保护密钥库的密码。你还需要为你的密钥对设置密码(如果你希望它与密钥库密码不同)。此外,它还会询问一些组织信息,如你的名字和姓氏、组织单位、组织名称、城市或地区名、州或省份名和国家代码。这些信息将被用来创建一个自签名的证书,它与密钥对一起存储在密钥库中。
这个自签名的证书不应该用于生产环境的应用发布,因为它不由证书颁发机构(CA)签发,但它可以用于测试和开发目的。
一旦你生成了密钥库和密钥对,你就可以使用它们来签名你的 Android 应用了。在你的 build.gradle
文件中,你会引用这个密钥库和别名,并提供相应的密码,以便在构建过程中签名 APK。
- 当提示输入密钥库口令时,你需要输入一个安全的密码,并记住它。这个密码将用于保护你的密钥库文件。
- 你会被要求再次确认密钥库口令。
- 接下来,
keytool
会询问你一系列问题,用于设置密钥库条目的证书颁发者信息。这包括你的名字、组织单位、组织名称、城市或地区名、省/市/自治区名和国家代码。 - 完成后,
keytool
会要求你确认信息的正确性,然后输入密钥的密码(如果和密钥库密码一致,可以直接回车)。 - 一旦完成,一个包含你的私钥和公钥的密钥库文件(在你的例子中是
boardrop.keystore
)将会被创建。
请确保在安全的地方备份你的 keystore 文件和密码,因为如果你想要更新应用或将其上传到应用商店,你将需要它们。
完成了密钥库的创建后,你现在应该已经有了一个 .keystore
文件。接下来的步骤是配置你的 Expo 应用来使用这个密钥库进行签名。
这里是你需要继续的步骤:
配置项目以使用签名密钥
- 将密钥库文件 (
boardrop.keystore
) 移动到你的 Expo 项目中的android/app
文件夹内。 - 打开你的项目中的
android/gradle.properties
文件,并添加以下行:
MYAPP_RELEASE_STORE_FILE=boardrop.keystore
MYAPP_RELEASE_KEY_ALIAS=boardrop
MYAPP_RELEASE_STORE_PASSWORD=你的密钥库密码
MYAPP_RELEASE_KEY_PASSWORD=你的密钥密码
- 替换
你的密钥库密码
和你的密钥密码
为你创建密钥库时所使用的密码。确保这些信息是正确的,因为它们将用于签名你的 APK。 - 确认或更新
android/app/build.gradle
文件中的签名配置部分以确保它使用上述属性:
android {...defaultConfig { ... }signingConfigs {release {if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {storeFile file(密钥文件(这里应该是'boardrop.keystore'))storePassword 你的密钥库密码keyAlias keystore别名keyPassword 你的密钥密码}}}buildTypes {release {...signingConfig signingConfigs.release}}
}
在这里:
storeFile
是你的keystore文件的路径,如果它位于android/app
文件夹,你可以直接用文件名。storePassword
是打开keystore时需要的密码。keyAlias
是你在创建keystore时指定的别名。keyPassword
是你的别名对应的密码。
需要注意的是,这里的keystore_password
、key_alias
和key_password
需要替换为你创建keystore时设置的实际密码和别名。这些信息通常是敏感的,应当保密处理
构建 APK
接下来,通过命令行构建 APK:
- 打开终端或命令提示符。
- 导航到你的 Expo 项目的
android
目录:
cd android
- 清理旧的构建文件:
./gradlew clean
- 构建 APK:
./gradlew assembleRelease
这将启动 APK 的构建过程。完成后,你会在 android/app/build/outputs/apk/release
文件夹下找到 APK 文件。
发送给手机安装后的运行效果如下:
React Native手机端运行打包后的GLB格式3D模型
注意事项
如果你遇到构建错误,请检查错误信息以确定问题所在,并适当调整你的配置或修复问题。
-
错误信息提示 Gradle 无法为它的 JVM 进程分配足够的堆空间。这通常意味着你的系统上可用的物理内存或者虚拟内存不足以满足
Xmx2048m
(即 2048MB 或 2GB)的配置。减少 JVM 的最大堆大小:
你可以尝试在gradle.properties
文件中减少-Xmx
参数的值。例如,你可以将其设置为 1024MB(1GB):org.gradle.jvmargs=-Xmx1024M -Dkotlin.daemon.jvm.options\="-Xmx2048M" -XX\:MaxMetaspaceSize\=512m
org.gradle.jvmargs=-Xmx1024M
:这个参数设置Gradle守护进程的最大堆内存大小为1024MB(即1GB)。Xmx
是JVM的标准参数之一,用于指定能够使用的最大堆内存量。Dkotlin.daemon.jvm.options="-Xmx2048M"
:这是一个传递给Kotlin编译守护进程的JVM参数,指定它可以使用的最大堆内存大小为2048MB(即2GB)。这个参数是为了确保在编译Kotlin代码时有足够的内存可用。XX:MaxMetaspaceSize=512m
:这个参数设置JVM的Metaspace(元空间)的最大大小为512MB。Metaspace是用于存放类的元数据的内存区域,这是Java 8引入的概念,它取代了以前的永久代(PermGen space)。
简而言之,这些配置确保了Gradle和Kotlin编译器守护进程有足够的内存来执行构建任务,同时也限制了它们使用内存的上限以防止占用过多的系统资源。
请注意,如果你的系统内存不足,这些设置可能会导致JVM无法启动,正如你之前遇到的错误所描述的那样。这种情况下,你可能需要降低这些内存设置的值,或者尝试关闭其他内存占用高的应用程序。
但是如果你确定你的内存是足够的话,系统仍然报错内存不足满足2G配置,这个时候你也许需要考虑你是不是安装错了JDK(你应该安装64位,而不是32位)
输出JAVA_HOME,如果位于x86下,如下:
由于路径中包含 "Program Files (x86)",这表明你当前设置的 `JAVA_HOME` 是指向一个32位版本的JDK。这就是为什么你无法为Gradle分配更多内存的原因(32位通常只能分配1~1.5G的虚拟内存)。你需要安装一个64位版本的JDK并更新 `JAVA_HOME` 环境变量。
-
错误信息显示网络问题导致的,可能是因为你的网络连接不稳定,或者是网络配置(如代理设置)阻止了连接。
在
gradle.properties
中配置本地代理,例如我用的是clashsystemProp.https.proxyHost=127.0.0.1 systemProp.https.proxyPort=7890
【3D内容的开发工具】高效率3D内容开发工具
gltf.report 查看模型信息,调整模型大小
glTF Report
本地的gltfjsx
或者在线的https://gltf.pmnd.rs/
将 gltf 变成 jsx 组件
https://github.com/pmndrs/gltfjsx 或者 https://gltf.pmnd.rs/
🧑💻 它创建所有对象和材质的虚拟图。现在您可以轻松更改内容并重新使用。
🏎️ 图表被修剪(空组、不必要的转换……)并且性能会更好。
⚡️ 它可以选择压缩您的模型,尺寸减少高达 70%-90%。
- 随意调整mesh
- 随意组合mesh
model-viewer
3D model-viewer embed
在网络和 AR 中轻松显示交互式 3D 模型
A-Frame - Make WebVR
A-Frame – Make WebVR
A-Frame 是一个用于构建虚拟现实 (VR) 体验的 Web 框架。 A-Frame 基于 HTML 之上,因此上手简单。但 A-Frame 不仅仅是 3D 场景图或标记语言;它还是一种标记语言。其核心是一个强大的实体组件框架,为 Three.js 提供了声明性、可扩展和可组合的结构。
相关参考
3D Optimization for Web—How I Got a Model From 26MB Down to 560KB
相关文章:

【React-Native开发3D应用】React Native加载GLB格式3D模型并打包至Android手机端
【React-Native开发3D应用】React Native加载GLB格式3D模型并打包至Android手机端 【加载3D模型】**React Native上如何加载glb格式的模型**第零步,选择相关模型第一步,导入相关模型加载库第二步,自定义GLB模型加载钩子第三步,借助…...
python的列表
定义 列表 是python中的一种数据类型,可以存放多个数据,列表中的数据可以是任意类型的。 格式 格式: my_list [] my_list list() 定义一个空的列表,有如上两种方式 遍历 for 循环 while循环 列表添加操作 列表添加操作有…...

[100天算法】-最短无序连续子数组(day 66)
题目描述 给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。你找到的子数组应是最短的,请输出它的长度。示例 1:输入: [2, 6, 4, 8, 10, 9, 15] 输出: 5 解释: 你只需要…...

001. 变量、环境变量
1、在终端中显示输出 shell脚本通常以shebang起始:#!/bin/bash/ shebang是一个文本行,其中#!位于解释器路径之前。/bin/bash是Bash的解释器命令路径。bash将以#符号开头的行视为注释。脚本中只有第一行可以使用shebang来定义解释该脚本所使…...

软考软件设计师刷题笔记整理
软件设计师 HTML代码中,创建指向邮箱地址的链接正确的是ARP攻击造成网络无法跨网段通信的原因是在软件开发过程中进行风险分析关于哈夫曼树的叙述关于风险管理的叙述ISO/IEC9126软件质量模型关于结构化开发方法的叙述分布式数据库中的分片透明、复制透明、位置透明和…...

Canal
canal译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费。 1.canal 工作原理 canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议MySQL master 收到…...
SpringBoot实现mysql与clickhouse多数据源
一、我们来实现一个mysql与clickhouse多数据源配置 二、数据源配置 # 指定服务名称 spring:application:name: demobigdatadatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/db?createDatabaseIfNotExisttrue&useUnicodetrue&…...
为什么是LangChain?
文章目录 一、前言二、认识langchain1. langchain的主要组成2. 总览LangChain2. LangChain的六大核心模块1. Models:模型统一接口2. Prompts:管理 LLM 输入3. Chains:将 LLM 与其他组件相结合,执行多个chain4. Indexes:…...

Labview的分支判断
和其他的编程语言一样的。都会有switch,case, if ,else; 再combo box中实现 再后台程序中对应的写上逻辑就好了。...

蓝桥杯双周赛算法心得——串门(双链表数组+双dfs)
大家好,我是晴天学长,树和dfs的结合,其邻接表的存图方法也很重要。需要的小伙伴可以关注支持一下哦!后续会继续更新的。💪💪💪 1) .串门 2) .算法思路 串门(怎么存图很关键…...
mysql 配置主从复制 及 Slave_SQL_Running = no问题排查
一、配置主数据库 1、在mysql 配置文件my.cnf中设置主数据库配置 server-id1 //唯一的标示符 log-binmysql-bin //开启二进制日志2、重启数据库 3、安全规范的写法是新建一个用户给这个用户复制的权限(直接用root也可以不建议) CREATE USER repl% IDEN…...

再获5G RedCap能力认证!宏电5G RedCap工业智能网关通过中国联通5G物联网OPENLAB开放实验室测试验证
近日,中国联通5G物联网OPENLAB开放实验室携手宏电股份完成5G RedCap工业智能网关端到端的测试验证,并颁发OPENLAB实验室面向RedCap终端的认证证书,为RedCap产业规模推广、全行业赋能打下坚实基础。 中国联通5G物联网OPENLAB开放实验室是中国…...
牛客--汽水瓶python
某商店规定:三个空汽水瓶可以换一瓶汽水,允许向老板借空汽水瓶(但是必须要归还)。 小张手上有n个空汽水瓶,她想知道自己最多可以喝到多少瓶汽水。 数据范围:输入的正整数满足 1≤n≤100 注意ÿ…...

TSINGSEE智能分析网关V4车辆结构化数据检测算法及车辆布控
车辆结构化视频AI检测技术,可通过AI识别对视频图像中划定区域内的出现的车辆进行检测、抓拍和识别,系统通过视频采集设备获取车辆特征信息,经过预处理之后,接入AI识别算法并与车辆底库进行对比,快速识别车辆身份和属性…...

git解决冲突的方法。
1、 cherry-pick git fetch ssh://jingyou.caigerrit.transtekcorp.com:29418/leshan refs/changes/23/34123/3 && git cherry-pick FETCH_HEAD2、 文件解冲突! 3、 cherry-pick完整。 git cherry-pick --continue4、查看状态。 5、 push。 git push o…...
[MT8766][Android12] 取消WIFI热点超过10分钟没有连接自动关闭设定
文章目录 开发平台基本信息问题描述解决方法 开发平台基本信息 芯片: MT8766 版本: Android 12 kernel: msm-4.19 问题描述 之前有个需求要设备默认开启WIFI热点,默认开启usb共享网络;而热点在原生的设定里面有个超时机制,如果在限定时间内…...
智能中仍存在着许多未被发现的逻辑
自然规律不仅包括精确的也包括模糊的,即模糊的基本自然律意味着自然界中的现象与规律并不是绝对精确的,存在一定的模糊性和不确定性。因此,用数学来完全描述和预测这些现象可能会有限制。 智能与人工智能(AI)抑或智能化…...

基于公共业务提取的架构演进——外部依赖防腐篇
背景 有了前两篇的帐号权限提取和功能设置提取的架构演进后,有一个问题就紧接着诞生了,对于诸多业务方来说,关键数据源的迁移如何在各个产品落地? 要知道这些数据都很关键: - 对于帐号,获取不到帐号信息是…...

uniapp小程序接入腾讯云【增强版人脸核身接入】
文档地址:https://cloud.tencent.com/document/product/1007/56812 企业申请注册这边就不介绍了,根据官方文档去申请注册。 申请成功后,下载【微信小程序sdk】 一、解压sdk,创建wxcomponents文件夹 sdk解压后发现是原生小程序代…...
Sass 最基础的语法
把每个点最简单的部分记录一下,方便自己查找 官方文档链接 Sass 笔记 1. & 父选择器,编译后为父选择器2. : 嵌套属性3. $ 变量3.1 数据类型3.2 变量赋值3.3. 数组3.4. map 4. 算数运算符5. #{}插值语法5.1 可以在选择器或属性名中使用变量5.2 将有引…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...