renderjs
是uni-app中一个运行在视图层的JS。可在App端和H5页面上运行。renderjs
的主要作用有2个:
(1)极大地减少了逻辑层(service)和视图层(view)的通讯损耗,提供高性能视图交互能力。纵然逻辑层和视图层分离的好处不容忽视,但例如Android端和小程序的高性能应用制作造成两层之间的通信阻塞迫使我们不得不放弃采用这种技术。由于renderjs运行在视图层,可以直接操作视图层的元素,因此可避免通信折损。
(2)在视图层操作DOM,运行for web的JS库。官方文档中不建议在uni-app里操作DOM,但可使用renderjs来操作一些dom、window的库。原因在于在app-vue环境下,视图层由webview渲染,而renderjs运行在视图层,可以很方便地操作dom和window。
移动端使用OpenLayers等开源GIS地图库最大的困难在于,若是没有提供相应的SDK将很难进行移动App的开发。由于uni-app不支持操作DOM元素,使得众多开源GIS地图库在开发移动应用时被舍弃。
如今,有了renderjs技术后,可直接在视图层操作DOM元素,让开发者可以像开发WebGIS一样开发移动端GIS,这极大地降低了开发难度,开发者只需掌握Vue框架的核心内容,而无需掌握Android及IOS的开发技术便可实现移动GIS应用的大部分功能。
如下为renderjs的使用方式,openlayers的写法跟开发WebGIS相同,写在script
中
<script module="test" lang="renderjs">
export default {
mounted() {
// ...
},
methods: {
// ...
}
}
</script>
当项目代码越来越多的时候,对代码进行组件化是必须的,网上针对renderjs组件之间通信的资料还比较少,官网给了一个较为简单的示例。
https://ext.dcloud.net.cn/plugin?id=1207
但是在实际开发中通信时遇到的一些情况网上并没有相关解答,所以我在这里做了总结并给出了相应的解决方案,供大家参考。
HTML
<view class="top-nav">
<button @click="ol.queryFeature">查询button>
view>
<view class="side-menu">
<scroll-view class="feature-list" scroll-x="true" scroll-y="true">
<view :prop="selectedFeature" :change:prop="ol.toFeature">view>
<view class="feature-list-view" @click="showFeature(item)"
v-for="(item, index) in searchList" :key="index" >
<view class="list-title">{{item.values_.objectid}}view>
<view class="list-item">{{item.values_.zt}}view>
view>
scroll-view>
view>
js (逻辑层)
<script>
export default {
data() {
return {
selectedFeature:{}
}
},
methods: {
//接受视图层传过来的信息
setSearchList(e){
console.log("option:",e)
this.searchList = e.option
},
showFeature(item){
console.log("show feature:",item);
this.selectedFeature = item;
}
}
}
</script>
renderjs(视图层)
<script module="ol" lang="renderjs">
export default {
data() {
return {
selectedFeature:{}
}
},
methods: {
queryFeature(event, ownerInstance){
...
// 调用 service 层的方法
ownerInstance.callMethod('setSearchList', {
option: features
})
...
},
toFeature(newValue, oldValue, ownerInstance, instance){
...
console.log("newValue:",newValue.values_.objectid)
...
}
}
}
</script>
(1)逻辑层到视图层的通信
在html中写一个监听属性变化的监听器:
<view :prop="selectedFeature" :change:prop="ol.toFeature"></view>
当点击结果列表中的某一项时,触发点击事件showFeature
,执行逻辑层代码this.selectedFeature = item;
此时selectedFeature
的值发生了变化,从而触发监听selectedFeature
的视图层事件ol.toFeature
,在监听逻辑层属性变化的视图层函数中有几个参数:newValue
、oldValue
、ownerInstance
、instance
,其中的newValue
即为改变后的属性值。此即逻辑层向视图层的通信。
(2)视图层到逻辑层的通信
首先在HTML中绑定视图层的函数ol.queryFeature
,该函数有两个参数event
和ownerInstance
,使用ownerInstance
的callMethod
方法可调用逻辑层的方法setSearchList
,callMethod
的第二个参数为一个对象,逻辑层中setSearchList
函数的形参便是视图层传递过来的值。此即视图层向逻辑层的通信。
(1)子组件通过事件向上传递值给父组件时,不能直接传值到视图层(renderjs
模块),只能传值给逻辑层,因此需在逻辑层监听值的变化来触发视图层中的方法来执行事件或者改变视图层中的变量。
(2)子组件中不可以通过事件向上传递,在父组件的逻辑层绑定视图层的方法进行调用。一种解决思路是在逻辑层添加一个触发视图层方法的触发器,在Vuex
中监听该触发器属性的状态,逻辑层监听到触发器状态变化后便会调用视图层的方法。