一、UniApp中使用renderjs
1 為什么要使用 renderjs
某些h5端使用的插件涉及到大量的dom操作妄壶,無(wú)法跨端使用摔握。
受限于框架視圖層與邏輯層的分離而導(dǎo)致的通信折損,而導(dǎo)致的頁(yè)面動(dòng)畫不流暢丁寄。
2 renderjs解決了哪些問(wèn)題
- renderjs是一種可以直接運(yùn)行在視圖層(webview)中的js技術(shù)氨淌,可以在視圖層操作dom。
- 直接運(yùn)行在視圖層伊磺,解決了視圖層與邏輯層頻繁通信導(dǎo)致的性能折損盛正,讓動(dòng)畫更流暢。
3 兼容性
App | H5 |
---|---|
2.5.5+支持 | ? |
4 使用方式
設(shè)置 script 節(jié)點(diǎn)的 lang 為 renderjs
<script module="test" lang="renderjs">
export default {
mounted() {
// ...
},
methods: {
// ...
}
}
</script>
5 注意事項(xiàng)
- 目前僅支持內(nèi)聯(lián)使用屑埋。
- 不要直接引用大型類庫(kù)豪筝,推薦通過(guò)動(dòng)態(tài)創(chuàng)建 script 方式引用。
- 可以使用 vue 組件的生命周期不可以使用 App摘能、Page 的生命周期
- 視圖層和邏輯層通訊方式與 WXS 一致续崖,另外可以通過(guò) this.$ownerInstance 獲取當(dāng)前組件的 ComponentDescriptor 實(shí)例。
- 觀測(cè)更新的數(shù)據(jù)在視圖層可以直接訪問(wèn)到团搞。
- APP 端視圖層的頁(yè)面引用資源的路徑相對(duì)于根目錄計(jì)算严望,例如:./static/test.js。
- APP 端可以使用 dom逻恐、bom API像吻,不可直接訪問(wèn)邏輯層數(shù)據(jù),不可以使用 uni 相關(guān)接口(如:uni.request)
- H5 端邏輯層和視圖層實(shí)際運(yùn)行在同一個(gè)環(huán)境中梢莽,相當(dāng)于使用 mixin 方式萧豆,可以直接訪問(wèn)邏輯層數(shù)據(jù)。
6 renderjs模塊內(nèi)的生命周期
<!--
H5:所有 UNI 框架的生命周期都可使用
APP:僅可使用 VUE 組件生命周期
視圖層與邏輯層可以重復(fù)定義生命周期昏名,都會(huì)執(zhí)行涮雷。
-->
<!-- 邏輯層 -->
<script>
export default {
onLoad() {
console.log('邏輯層生命周期 - onLoad');
},
created() {
console.log('邏輯層生命周期 - created');
},
mounted() {
console.log('邏輯層生命周期 - mounted');
}
}
</script>
<!-- 視圖層 -->
<script module="moduleName" lang="renderjs" type="module" >
export default {
onLoad() {
console.log('視圖層生命周期 - onLoad'); // 頁(yè)面生命周期 APP 不會(huì)執(zhí)行 H5 會(huì)執(zhí)行
},
created() {
console.log('視圖層生命周期 - created'); // 組件生命周期 H5 APP 都會(huì)執(zhí)行,重復(fù)定義也會(huì)執(zhí)行轻局,不會(huì)被覆蓋洪鸭。
},
mounted() {
console.log('視圖層生命周期 - mounted'); // 組件生命周期 H5 APP 都會(huì)執(zhí)行样刷,重復(fù)定義也會(huì)執(zhí)行,不會(huì)被覆蓋览爵。
}
}
</script>
7 renderjs模塊內(nèi)的this指向
<!-- 邏輯層 -->
<script>
export default {
data() {
return {
str:"邏輯層的數(shù)據(jù)模型"
}
},
methods: {
test() {
return "調(diào)用邏輯層的方法"
}
}
}
</script>
<!-- 視圖層 -->
<script module="moduleName" lang="renderjs" type="module" >
export default {
mounted() {
console.log("嘗試獲取邏輯層的數(shù)據(jù)模型",this.str) // H5端可正常打印 APP打印undefined
console.log("嘗試調(diào)用邏輯層的方法",this.test()) // H5端可正常調(diào)用 APP端報(bào)錯(cuò)
}
}
</script>
8 視圖層和邏輯層的通信方式
視圖層可以通過(guò)this.$ownerInstance.callMethod('方法名', 傳的值)
來(lái)和邏輯層進(jìn)行通信
代碼中 :變量名="變量值" :change:變量名=”renderjs模塊上的方法“
change就是監(jiān)聽定義的變量發(fā)生改變---->觸發(fā)視圖層上的方法----->通過(guò)this.$ownerInstance.callMethod('方法名', 傳的值)
給頁(yè)面?zhèn)鲄?--->頁(yè)面接收值---->渲染頁(yè)面
示例代碼:
<template>
<view>
<!-- 監(jiān)聽變量 operation 的變化置鼻,operation 發(fā)生改變時(shí),調(diào)用 test 模塊的 loadOperation 方法 -->
<view :operation="operation" :change:operation="test.loadOperation">
<!-- 調(diào)用 test 模塊的 clicked 變量 -->
test模塊:{{test.clicked}}
</view>
<br />
<view>您總共點(diǎn)擊了 {{total}} 次</view>
<br />
<button @click="onClick">點(diǎn)擊</button>
</view>
</template>
<script>
export default {
data() {
return {
operation: true,
total:0,
}
},
methods: {
onClick(e){
this.operation = !this.operation
},
/**
* 接收 renderjs 傳過(guò)來(lái)的數(shù)據(jù)
* @param {Object} data
*/
reciveMessage(data) {
this.total = data;
}
}
}
</script>
<script module="test" lang="renderjs">
export default {
data() {
return {
clicked: false,
count: 0
}
},
methods: {
loadOperation(newValue, oldValue, ownerInstance, instance) {
// 數(shù)據(jù)變更
console.log(newValue,oldValue,ownerInstance,instance)
this.clicked = newValue;
// 向uni-app頁(yè)面組件發(fā)送信息
this.sendMsg();
},
sendMsg() {
// 向頁(yè)面?zhèn)鲄? this.$ownerInstance.callMethod('reciveMessage', ++this.count)
},
}
}
</script>
<style>
</style>
二蜓竹、Uniapp中結(jié)合renderJS使用echarts
1.echarts引入方式(通過(guò)動(dòng)態(tài)創(chuàng)建script方式引用)
html使用echarts的方式:
1.為 ECharts 準(zhǔn)備一個(gè)具備高寬的 DOM 容器箕母。
<body>
<!-- 為 ECharts 準(zhǔn)備一個(gè)具備大小(寬高)的 DOM -->
<div id="main" style="width: 600px;height:400px;"></div>
</body>
2.通過(guò) echarts.init 方法初始化一個(gè) echarts 實(shí)例
// 基于準(zhǔn)備好的dom俱济,初始化echarts實(shí)例
var myChart = echarts.init(document.getElementById('main'));
3.通過(guò) setOption 方法生成一個(gè)簡(jiǎn)單的柱狀圖嘶是,
// 指定圖表的配置項(xiàng)和數(shù)據(jù)
var option = {
title: {
text: 'ECharts 入門示例'
},
tooltip: {},
legend: {
data:['銷量']
},
xAxis: {
data: ["襯衫","羊毛衫","雪紡衫","褲子","高跟鞋","襪子"]
},
yAxis: {},
series: [{
name: '銷量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
};
// 使用指定的配置項(xiàng)和數(shù)據(jù)顯示圖表。
myChart.setOption(option);
renderjs使用echarts的方式:(同html的使用方式大致相同)
1.為 ECharts 準(zhǔn)備一個(gè)具備高寬的 DOM 容器蛛碌。
<view class="content">
<view id="echarts" style="width:100%;height:300rpx"></view>
</view>
2.引入renderjs聂喇, 動(dòng)態(tài)引入echarts。原生操作dom 蔚携。將echarts引入
3.script標(biāo)簽上的onload事件加載完成后初始化echarts 實(shí)例
4.通過(guò) setoption方法生成
<script module="echarts" lang="renderjs">
let myChart
export default {
mounted() {
if (typeof window.echarts === 'function') {
myChart = echarts.init(document.getElementById('echarts'))
// 觀測(cè)更新的數(shù)據(jù)在 view 層可以直接訪問(wèn)到
myChart.setOption(this.option)
} else {
// 動(dòng)態(tài)引入較大類庫(kù)避免影響頁(yè)面展示
const script = document.createElement('script')
// view 層的頁(yè)面運(yùn)行在 www 根目錄希太,其相對(duì)路徑相對(duì)于 www 計(jì)算
script.src = 'static/echarts.js'
//script標(biāo)簽的onload事件都是在外部js文件被加載完成并執(zhí)行完成后才被觸發(fā)的
script.onload = ()=>{
myChart = echarts.init(document.getElementById('echarts'),)
myChart.setOption(this.option)
}
document.head.appendChild(script)
}
},
methods: {
}
}
</script>
三、echarts的主題配置與封裝
1.主題配置
主題配置是全局控制echarts的樣式
在echarts官網(wǎng)可以可視化定制配置酝蜒,然后導(dǎo)出json或者js文件誊辉。
配置的具體方法:
JS版本
下載或復(fù)制以下的主題保存至 *.js 文件;
將該文件在 HTML 中引用秕硝;
使用 echarts.init(dom, 'customed') 創(chuàng)建圖表芥映,第二個(gè)參數(shù)即為 *.js 文件中注冊(cè)的主題名字。
json版本
下載或復(fù)制以下的主題保存至 *.json 文件远豺;
讀取該 JSON 文件奈偏,并使用 obj = JSON.parse(data) 將其轉(zhuǎn)換成對(duì)象;
調(diào)用 echarts.registerTheme('customed', obj) 注冊(cè)主題躯护;
使用 echarts.init(dom, 'customed') 創(chuàng)建圖表惊来,第二個(gè)參數(shù)即為剛才注冊(cè)的主題名字。
在uniapp中可以直接建一個(gè)js文件棺滞,modules.exports一個(gè)對(duì)象裁蚁。然后頁(yè)面引入使用
// 通用配置項(xiàng)
module.exports = {
"color": [
"#5470c6",
"#91cc75",
"#fac858",
"#ee6666",
"#73c0de",
"#3ba272",
"#fc8452",
"#9a60b4",
"#ea7ccc"
],
"backgroundColor": "rgba(0, 0, 0, 0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#464646"
},
"subtextStyle": {
"color": "#6E7079"
}
},
....
....
....
}
2.使用renderJS封裝echarts,實(shí)現(xiàn)主題配置
實(shí)現(xiàn)效果:一個(gè)組件继准,可以實(shí)現(xiàn)不同的圖表功能枉证,樣式可以全局配置,避免option樣式過(guò)多
實(shí)現(xiàn)思路:
1.在同個(gè)頁(yè)面使用多個(gè)圖表移必,id名必須不一致
2.option配置項(xiàng)需改成傳參形式
3.主題配置文件
主要代碼如下:
<template>
<view class="content">
<!-- #ifdef APP-PLUS || H5 -->
<view @click="echarts.onClick" :prop="optionData" :style="{width:moduleParam.width,height:moduleParam.height}" :change:prop="echarts.updateEcharts" :moduleParam="moduleParam" :change:moduleParam="echarts.upmoduleParam" :id="moduleParam.id" class="echarts" ></view>
<!-- <button @click="changeOption">更新數(shù)據(jù)</button> -->
<!-- #endif -->
<!-- #ifndef APP-PLUS || H5 -->
<view>非 APP室谚、H5 環(huán)境不支持</view>
<!-- #endif -->
</view>
</template>
<script>
export default {
data() {
return {
}
},
props:{
moduleParam:{
type:Object,
default:()=>{
id: "myCharts";
width: "100%";
height: "300rpx"
}
},
optionData:{
type:Object,
default:()=>{}
}
},
onLoad() {
},
methods: {
changeOption() {
// 父組件刷新數(shù)據(jù)
this.$emit("changeOption")
},
onViewClick(options) {
this.$emit("getClickData",options)
}
}
}
</script>
<script module="echarts" lang="renderjs">
import echartsConfig from '@/common/echarts-config.js'
let myChart
export default {
data(){
return{
clickData:null
}
},
mounted() {
if (typeof window.echarts === 'function') {
this.initEcharts()
} else {
// 動(dòng)態(tài)引入較大類庫(kù)避免影響頁(yè)面展示
const script = document.createElement('script')
// view 層的頁(yè)面運(yùn)行在 www 根目錄,其相對(duì)路徑相對(duì)于 www 計(jì)算
script.src = 'static/echarts.min.js'
script.onload = this.initEcharts.bind(this)
document.head.appendChild(script)
}
},
methods: {
initEcharts(){
echarts.registerTheme('echartsConfig',echartsConfig ) //注冊(cè)主題
myChart = echarts.init(document.getElementById(this.moduleParam.id),"echartsConfig")
// 觀測(cè)更新的數(shù)據(jù)在 view 層可以直接訪問(wèn)到
myChart.setOption(this.optionData)
// 點(diǎn)擊傳參
myChart.on('click', params => {
// console.log(params)
this.clickData = params
})
},
updateEcharts(newValue, oldValue, ownerInstance, instance) {
// 監(jiān)聽 service 層數(shù)據(jù)變更
console.log(newValue)
myChart = echarts.init(document.getElementById(this.moduleParam.id),"echartsConfig")
myChart.setOption(newValue)
},
upmoduleParam(newvalue,oldvalue){},
onClick(event, ownerInstance) {
// console.log(this.clickData)
if(!this.clickData){
return
}
ownerInstance.callMethod('onViewClick',{
value:this.clickData.value,
name:this.clickData.name,
dataIndex:this.clickData.dataIndex,
seriesName:this.clickData.seriesName
})
// 上次點(diǎn)擊數(shù)據(jù)置空
this.clickData = null
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.echarts {
width: 100%;
height: 600rpx;
}
</style>
主題配置文件
// 通用配置項(xiàng)
module.exports = {
"color": [
"#5470c6",
"#91cc75",
"#fac858",
"#ee6666",
"#73c0de",
"#3ba272",
"#fc8452",
"#9a60b4",
"#ea7ccc"
],
"backgroundColor": "rgba(0, 0, 0, 0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#464646"
},
"subtextStyle": {
"color": "#6E7079"
}
},
"line": {
"itemStyle": {
"borderWidth": 1
},
"lineStyle": {
"width": 2
},
"symbolSize": 4,
"symbol": "emptyCircle",
"smooth": false
},
"radar": {
"itemStyle": {
"borderWidth": 1
},
"lineStyle": {
"width": 2
},
"symbolSize": 4,
"symbol": "emptyCircle",
"smooth": false
},
"bar": {
"itemStyle": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
},
"pie": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"scatter": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"boxplot": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"parallel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"sankey": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"funnel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"gauge": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"candlestick": {
"itemStyle": {
"color": "#eb5454",
"color0": "#47b262",
"borderColor": "#eb5454",
"borderColor0": "#47b262",
"borderWidth": 1
}
},
"graph": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"lineStyle": {
"width": 1,
"color": "#aaa"
},
"symbolSize": 4,
"symbol": "emptyCircle",
"smooth": false,
"color": [
"#5470c6",
"#91cc75",
"#fac858",
"#ee6666",
"#73c0de",
"#3ba272",
"#fc8452",
"#9a60b4",
"#ea7ccc"
],
"label": {
"color": "#eee"
}
},
"map": {
"itemStyle": {
"normal": {
"areaColor": "#eee",
"borderColor": "#444",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(255,215,0,0.8)",
"borderColor": "#444",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(100,0,0)"
}
}
}
},
"geo": {
"itemStyle": {
"normal": {
"areaColor": "#eee",
"borderColor": "#444",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(255,215,0,0.8)",
"borderColor": "#444",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(100,0,0)"
}
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#6E7079"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "#6E7079"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#6E7079"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#E0E6F1"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.2)",
"rgba(210,219,238,0.2)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": false,
"lineStyle": {
"color": "#6E7079"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#6E7079"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#6E7079"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#E0E6F1"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.2)",
"rgba(210,219,238,0.2)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": false,
"lineStyle": {
"color": "#6E7079"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#6E7079"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#6E7079"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#E0E6F1"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.2)",
"rgba(210,219,238,0.2)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#6E7079"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "#6E7079"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#6E7079"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#E0E6F1"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.2)",
"rgba(210,219,238,0.2)"
]
}
}
},
"toolbox": {
"iconStyle": {
"normal": {
"borderColor": "#999"
},
"emphasis": {
"borderColor": "#666"
}
}
},
"legend": {
"textStyle": {
"color": "#333"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#ccc",
"width": 1
},
"crossStyle": {
"color": "#ccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#DAE1F5",
"width": 2
},
"itemStyle": {
"normal": {
"color": "#A4B1D7",
"borderWidth": 1
},
"emphasis": {
"color": "#FFF"
}
},
"controlStyle": {
"normal": {
"color": "#A4B1D7",
"borderColor": "#A4B1D7",
"borderWidth": 1
},
"emphasis": {
"color": "#A4B1D7",
"borderColor": "#A4B1D7",
"borderWidth": 1
}
},
"checkpointStyle": {
"color": "#316bf3",
"borderColor": "fff"
},
"label": {
"normal": {
"textStyle": {
"color": "#A4B1D7"
}
},
"emphasis": {
"textStyle": {
"color": "#A4B1D7"
}
}
}
},
"visualMap": {
"color": [
"#bf444c",
"#d88273",
"#f6efa6"
]
},
"dataZoom": {
"handleSize": "undefined%",
"textStyle": {}
},
"markPoint": {
"label": {
"color": "#eee"
},
"emphasis": {
"label": {
"color": "#eee"
}
}
}
}
頁(yè)面引用:
<template>
<view class="content">
<dom-echart :moduleParam="moduleParam1" :optionData="option" @changeOption="changeOption()"></dom-echart>
<dom-echart :moduleParam="moduleParam2" :optionData="option1" @changeOption="changeOption1()"></dom-echart>
<dom-echart :moduleParam="moduleParam3" :optionData="option2" @changeOption="changeOption2()"></dom-echart>
</view>
</template>
<script>
import domEchart from './index/index.vue'
export default {
components:{
domEchart
},
data() {
return {
moduleParam1:{
id:"moId1",
},
moduleParam2:{
id:"moId2",
},
moduleParam3:{
id:"moId3",
},
option: {
title: {
text: 'ECharts1'
},
xAxis: {
data: ["襯衫1", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"]
},
yAxis: {},
series: [{
name: '銷量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
},
option1: {
title: {
text: 'ECharts2'
},
series: [{
name: '銷量',
type: 'pie',
data: [53, 20, 28, 12, 10, 20]
}]
},
option2: {
title: {
text: 'ECharts3'
},
xAxis: {
data: ["襯衫1", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"]
},
yAxis: {},
series: [{
name: '銷量',
type: 'line',
data: [53, 20, 28, 12, 10, 20]
}]
}
}
},
onLoad() {
},
methods: {
changeOption(){
const data = this.option.series[0].data
// 隨機(jī)更新示例數(shù)據(jù)
data.forEach((item, index) => {
data.splice(index, 1, Math.random() * 40)
})
},
changeOption1(){
const data = this.option1.series[0].data
// 隨機(jī)更新示例數(shù)據(jù)
data.forEach((item, index) => {
data.splice(index, 1, Math.random() * 40)
})
},
changeOption2(){
const data = this.option2.series[0].data
// 隨機(jī)更新示例數(shù)據(jù)
data.forEach((item, index) => {
data.splice(index, 1, Math.random() * 40)
})
}
}
}
</script>
<style>
</style>
實(shí)現(xiàn)效果
dome源碼請(qǐng)移步gitee:https://gitee.com/shen-miaoxin/uniapp-renderjs-echarts
點(diǎn)個(gè)小星星~