如何将Lua向jQuery传递的武器HUD逻辑迁移至React?
React重构Lua服务器HUD武器显示逻辑
原功能说明
基于Lua服务器的HUD,实现玩家空手时显示拳头图片、持械时显示对应武器图片及弹药信息,原使用jQuery操作DOM,现切换到React需重构逻辑。
原Lua代码
SetInterval("run",150, function() local ped = PlayerPedId() local oldWeaponHash = nil local currentWeaponHash = nil local oldWeaponAmmo = nil local oldClipAmmo = nil currentWeaponHash = GetSelectedPedWeapon(ped) oldWeaponHash = currentWeaponHash local weaponName = nil local _, maxAmmo = GetMaxAmmo(ped, currentWeaponHash) for _k, value in pairs(weapons) do if currentWeaponHash == GetHashKey(value) then weaponName = value end end -- 判断是否空手(哈希值-1569615261对应空手状态) if currentWeaponHash == -1569615261 or currentWeaponHash == nil then SendNUIMessage({ show2 = true, -- 标记显示拳头图片 show3 = false -- 隐藏武器图片 }) else if weaponName ~= nil then local maxClipAmmo = GetMaxAmmoInClip(ped, currentWeaponHash, 1) local _, clipAmmo = GetAmmoInClip(ped, currentWeaponHash) local weaponAmmo = GetAmmoInPedWeapon(ped, currentWeaponHash) oldWeaponAmmo = weaponAmmo oldClipAmmo = clipAmmo SendNUIMessage({ updateWeapon = true, show2 = false, -- 隐藏拳头图片 show3 = true, -- 显示当前武器图片 weaponName = weaponName, maxAmmo = maxAmmo, maxClipAmmo = maxClipAmmo, clipAmmo = clipAmmo, weaponAmmo = weaponAmmo }) SetNuiFocus(false, false) end end end)
原jQuery代码
if (data.show2 == true) { var Url = `<img class="stoljpi mt-1" id="weapon_image" src="./assets/imgs/weapons/unarmed.png" alt="">` $("#slike").html(Url) $("#slike").fadeIn("100") } if (data.show2 == false) { var Url = `<img class="stoljpi mt-1" id="weapon_image" src="./assets/imgs/weapons/${data.weaponName}.png" alt="">` $("#slike").html(Url) }
React重构方案
核心思路
用React状态驱动视图替代jQuery的DOM操作,通过监听NUI消息同步Lua传来的武器状态,由React自动渲染对应UI。
1. 实现武器状态上下文(共享状态)
创建Context统一管理武器状态,方便组件间共享数据:
import { useState, useEffect, createContext, useContext } from 'react'; // 创建武器状态上下文 const WeaponContext = createContext(); // 状态提供者组件 export const WeaponProvider = ({ children }) => { const [weaponState, setWeaponState] = useState({ isUnarmed: true, // 是否空手 weaponName: '', // 武器名称 maxAmmo: 0, // 总弹药上限 maxClipAmmo: 0, // 弹夹上限 clipAmmo: 0, // 当前弹夹弹药 weaponAmmo: 0 // 总剩余弹药 }); useEffect(() => { // 监听Lua发送的NUI消息 const handleNuiMessage = (event) => { const data = event.data; if (data.show2 !== undefined) { // 构建新状态 const newState = { ...weaponState, isUnarmed: data.show2, weaponName: data.weaponName || '' }; // 持械时同步弹药数据 if (!data.show2) { newState.maxAmmo = data.maxAmmo; newState.maxClipAmmo = data.maxClipAmmo; newState.clipAmmo = data.clipAmmo; newState.weaponAmmo = data.weaponAmmo; } setWeaponState(newState); } }; window.addEventListener('message', handleNuiMessage); // 组件卸载时移除监听 return () => window.removeEventListener('message', handleNuiMessage); }, [weaponState]); return ( <WeaponContext.Provider value={weaponState}> {children} </WeaponContext.Provider> ); };
2. 实现武器HUD组件
基于状态渲染UI,替代jQuery的DOM拼接:
// 武器HUD展示组件 export const WeaponHUD = () => { const weaponState = useContext(WeaponContext); return ( <div id="slike" className="weapon-hud-container"> {/* 根据状态渲染对应图片 */} {weaponState.isUnarmed ? ( <img className="stoljpi mt-1" id="weapon_image" src="./assets/imgs/weapons/unarmed.png" alt="空手" style={{ display: 'block', animation: 'fadeIn 0.1s ease-in-out' }} /> ) : ( <img className="stoljpi mt-1" id="weapon_image" src={`./assets/imgs/weapons/${weaponState.weaponName}.png`} alt={weaponState.weaponName} /> )} {/* 可选:添加弹药信息显示 */} {!weaponState.isUnarmed && ( <div className="ammo-display"> <span className="clip-ammo">{weaponState.clipAmmo}/{weaponState.maxClipAmmo}</span> <span className="total-ammo">/{weaponState.weaponAmmo}</span> </div> )} </div> ); };
3. 入口组件集成
在React入口文件中包裹状态提供者:
import { WeaponProvider } from './WeaponContext'; import { WeaponHUD } from './WeaponHUD'; function App() { return ( <WeaponProvider> <div className="hud-container"> <WeaponHUD /> {/* 其他HUD组件 */} </div> </WeaponProvider> ); } export default App;
Lua代码微调
原Lua代码无需大幅修改,仅需移除SendReactMessage('pesnica')(该消息已被show2字段替代),保持SendNUIMessage的字段结构即可。
内容的提问来源于stack exchange,提问作者whereiam
相关产品推荐
相关产品推荐

