uni-app怎么使用RenderJS uni-app操作DOM提升方法详解深度解析|Duuu笔记
RenderJS是uni-app在非H5平台绕过Vue虚拟DOM直接操作原生渲染层的机制,因Vue响应式在小程序中编译为setData易卡顿,而RenderJS运行于渲染线程,可直接调用querySelector等API。
RenderJS 是什么,为什么不能直接用 Vue 操作 DOM
RenderJS 不是 Vue 的补充,而是 uni-app 在非 H5 平台(如小程序、App)上绕过 Vue 虚拟 DOM 直接操作原生渲染层的机制。Vue 的响应式更新在小程序里会被编译成 setData,频繁触发会导致卡顿;而 RenderJS 运行在「渲染线程」,能直接调用
querySelector
、
appendChild
等原生 API,跳过逻辑层通信开销。
但要注意:
renderjs
只支持
vue
文件中的
块,且仅在 App 和微信/支付宝等小程序生效,H5 下不运行。
怎么写一个可用的 RenderJS 脚本
必须满足三个硬性条件,缺一不可:
type="renderjs"
的
标签需放在
后、普通
前
导出对象必须有
mounted
方法,否则不执行
所有 DOM 操作必须在
mounted
或其调用的函数中进行,不能在顶层直接写
document.getElementById
示例结构:
export default {
mounted() {
const container = document.getElementById('list-container')
const item = document.createElement('div')
item.textContent = 'renderjs item'
container.appendChild(item)
}
}
RenderJS 和 Vue 之间怎么传数据
只能单向通信:Vue → RenderJS,靠
props
;RenderJS → Vue,靠
this.$emit
(注意不是
$emit
,也不是
uni.$emit
)。
常见错误现象:
独响
一个轻笔记+角色扮演的app
下载
在 RenderJS 中访问
this.$parent
或
this.data
—— 报错,不存在
试图用
props
接收响应式对象并监听变化 —— 不会触发,
props
是初始化快照,后续 Vue 层改了它不会同步
在
mounted
外调用
this.$emit
—— 无效,必须等 mounted 执行完才注册好事件通道
正确做法:Vue 层通过
:props="{ list: dataList }"
传原始数组,RenderJS 内部做一次渲染;列表变化时,Vue 主动再调用
this.$refs.xxx.updateList(newList)
(需提前在 renderjs 导出方法)。
哪些场景真适合用 RenderJS,哪些只是自找麻烦
适合:
高频滚动容器(如聊天消息流、长列表),需局部 DOM 更新避免整块重绘
Canvas / WebGL 渲染区域需要直连 canvas.getContext
第三方 UI 库(如 ECharts 小程序版)依赖原生节点操作
不适合:
简单表单交互、按钮点击反馈 —— Vue 响应式足够快,加 RenderJS 反而增加维护成本
跨平台一致性要求高的组件 —— RenderJS 在 H5 不生效,得额外写 fallback
需要和 Vuex/Pinia 深度联动的状态管理 —— RenderJS 拿不到 store 实例,也不该拿
性能影响很实际:一次
this.$emit
触发 Vue 层更新,本质还是走 setData,所以别指望它替代所有响应式逻辑。真正省的是「渲染层内部重排重绘」,不是「通信链路」。
容易被忽略的一点:RenderJS 脚本无法使用 ES6+ 动态 import、不能访问
localStorage
、没有
window
对象,调试时 console.log 输出位置也和普通 JS 不同——它出现在「渲染进程」控制台,不是浏览器或 App 的主控制台。
