1.为什么要使用 renderjs
- 某些h5端使用的插件涉及到大量的dom操作,无法跨端使用。
- 直接运行在视图层,解决了视图层与逻辑层频繁通信导致的性能折损,让动画更流畅。
- renderjs是一种可以直接运行在视图层(webview)中的js技术,可以在视图层操作dom。
2.兼容性
App | H5 |
2.5.5+,仅支持vue | √ |
3.使用方式
设置 script 节点的 lang 为 renderjs
注意:module="openlayers" 中 openlayers 这是一个自定义属性,用于指定脚本模块的名称或标识符,写什么都可以。
<script module="openlayers" lang="renderjs">
export default {
mounted() {
// ...
},
methods: {
// ...
}
}
</script>
4.注意事项
- 目前仅支持内联使用。
- 不要直接引用大型类库,推荐通过动态创建 script 方式引用。
- 可以使用 vue 组件的生命周期(不支持 beforeDestroy、destroyed、beforeUnmount、unmounted),不可以使用 App、Page 的生命周期
- 视图层和逻辑层通讯方式与 WXS 一致,另外可以通过 this.$ownerInstance 获取当前组件的 ComponentDescriptor 实例。
- this.$ownerInstance.callMethod() 仅支持调用逻辑层vue选项式中的 methods 中定义的方法。
- 注意逻辑层给数据时最好一次性给到渲染层,而不是不停从逻辑层向渲染层发消息,那样还是会产生逻辑层和视图层的多次通信,还是会卡
- 观测更新的数据在视图层可以直接访问到。
- APP 端视图层的页面引用资源的路径相对于根目录计算,例如:./static/test.js。
- APP 端可以使用 dom、bom API,不可直接访问逻辑层数据,不可以使用 uni 相关接口(如:uni.request)
- H5 端逻辑层和视图层实际运行在同一个环境中,相当于使用 mixin 方式,可以直接访问逻辑层数据。
- vue3 项目不支持
setup script
用法。
5.renderjs模块内的生命周期
<!--
H5:所有 UNI 框架的生命周期都可使用
APP:仅可使用 VUE 组件生命周期
视图层与逻辑层可以重复定义生命周期,都会执行。
-->
<!-- 逻辑层 -->
<script>
export default {
onLoad() {
console.log('逻辑层生命周期 - onLoad');
},
created() {
console.log('逻辑层生命周期 - created');
},
mounted() {
console.log('逻辑层生命周期 - mounted');
}
}
</script>
<!-- 视图层 vue3版本下不会走下面的方法 -->
<script module="openlayers" lang="renderjs" type="module" >
export default {
onLoad() {
console.log('视图层生命周期 - onLoad'); // 页面生命周期 APP 不会执行 H5 会执行
},
created() {
console.log('视图层生命周期 - created'); // 组件生命周期 H5 APP 都会执行,重复定义也会执行,不会被覆盖。
},
mounted() {
console.log('视图层生命周期 - mounted'); // 组件生命周期 H5 APP 都会执行,重复定义也会执行,不会被覆盖。
}
}
</script>
H5效果图
APP效果图(我这里用的夜神模拟器)
6.renderjs模块内的this指向
<!-- 逻辑层 -->
<script>
export default {
data() {
return {
str:"逻辑层的数据"
}
},
methods: {
test() {
return "调用逻辑层的方法"
}
}
}
</script>
<!-- 视图层 -->
<script module="openlayers" lang="renderjs" type="module" >
export default {
mounted() {
console.log("尝试获取逻辑层的数据",this.str) // H5端可正常打印 APP打印undefined
console.log("尝试调用逻辑层的方法",this.test()) // H5端可正常调用 APP端报错
}
}
</script>
H5效果图
APP效果图(我这里用的夜神模拟器)
7.视图层和逻辑层的通信方式
- 视图层可以通过
this.$ownerInstance.callMethod('方法名', 传的值)
来和逻辑层进行通信。- 代码中
:变量名="变量值" :change:变量名="renderjs模块上的方法"
- change 就是监听定义的变量发生改变 -> 触发视图层上的方法 -> 通过
this.$ownerInstance.callMethod('方法名', 传的值)
给页面传参 -> 页面接收值 -> 渲染页面。
<template>
<view>
<!-- 监听变量 operation 的变化,operation 发生改变时,调用 openlayers 模块的 loadOperation 方法 -->
<view :operation="operation" :change:operation="openlayers.loadOperation"></view>
<view>点击了 {{total}} 次</view>
<button @click="onClick">点击</button>
</view>
</template>
<script>
export default {
data() {
return {
operation: true,
total: 0,
}
},
methods: {
/**
* 点击事件
*/
onClick() {
this.operation = !this.operation
},
/**
* 接收 renderjs 传过来的数据
* @param {Number} num 接收的内容
*/
reciveMessage(data) {
this.total = data;
}
}
}
</script>
<script module="openlayers" lang="renderjs">
export default {
data() {
return {
count: 0
}
},
methods: {
/**
* @param {*} newValue 新的值或状态
* @param {*} oldValue 旧的值或状态
* @param {*} ownerInstance 拥有该数据或组件的实例
* @param {*} instance 当前操作的具体实例
*/
loadOperation(newValue, oldValue, ownerInstance, instance) {
console.log(newValue, oldValue, ownerInstance, instance);
this.$ownerInstance.callMethod('reciveMessage', ++this.count); // 向uni-app页面组件发送信息
},
}
}
</script>
8.调用视图层renderJS中的方法
例:当前要增加一个地图放大功能,之前的写法是通过调用逻辑层的事件改变对象里的值触发视图层change事件,达到触发地图的方法。
现在可改成在点击事件内直接触发视图层的方法,以此来调用地图方法,不用在经过逻辑层和视图层通信这一步骤
<template>
<view>
<view id="mymap" class="mymap"></view>
<view class="but_sty">
<button @click="openlayers.zoomIn">放大</button>
<button @click="openlayers.zoomOut">缩小</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {}
}
},
</script>
<script module="openlayers" lang="renderjs">
import {
mapObject
} from "@/common/openlayers/openlayerMap.js";
export default {
methods: {
/**
* 地图放大
*/
zoomIn() {
console.log('放大');
mapObject.mapZoom('in');
},
/**
* 地图缩小
*/
zoomOut() {
console.log('缩小');
mapObject.mapZoom('out');
},
}
}
</script>