Webview +vue.js +echarts

本文档描述了在Android应用中使用WebView加载包含Echarts图表的HTML页面时遇到的问题。在Android 7.0上可以正常显示,但在5.0系统下图表无法显示。通过引入jQuery,问题在5.0上得到解决。主要涉及的技术包括:Vue.js、Echarts、Android WebView设置及JavaScript交互。

1.在assets目录下创建web目录,如下图 

2.b.html 内容如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../wwwroot/js/vue.js"></script>
    <script src="../wwwroot/js/echarts.js"></script>
</head>
<body bgcolor="#FFFFFF">
<div id="app">
   
    <div id="main" style="width: 200px; height: 200px; background-color:black">
        {{message}}
    </div>
</div>
<h1>easyboot11</h1>
</body>

<script>
    new Vue({
        el: '#app',
        data: {
            message: 'Hello Vue.js!'
        }, 

        methods: {
            myEcharts() {
                // 基于准备好的dom,初始化echarts实例
                var myChart = echarts.init(document.getElementById('main'));

                // 指定图表的配置项和数据
                var option = {
                    series: [{
                        type: 'gauge',
                        min: 0,
                        max: 120,
                        radius: '100%',
                        axisLine: {
                            lineStyle: {
                                width: 20,
                                color: [
                                    [0.3, '#67e0e3'],
                                    [0.7, '#37a2da'],
                                    [1, '#fd666d']
                                ]
                            }
                        },
                        pointer: {
                            itemStyle: {
                                color: 'auto'
                            }
                        },
                        axisTick: {
                            distance: -20,
                            length: 8,
                            lineStyle: {
                                color: '#fff',
                                width: 2
                            }
                        },
                        splitLine: {
                            distance: -20,
                            length: 20,
                            lineStyle: {
                                color: '#fff',
                                width: 4
                            }
                        },
                        anchor: {
                            show: true,
                            showAbove: true,
                            size: 15,
                            itemStyle: {
                                borderWidth: 5
                            }
                        },
                        axisLabel: {
                            color: 'auto',
                            distance: 25,
                            fontSize: 10
                        },
                        detail: {
                            valueAnimation: true,
                            formatter: '{value} km/h',
                            color: 'auto',
                            fontSize: 16
                        },
                        data: [{
                            value: 90
                        }]
                    }]
                };

                // 使用刚指定的配置项和数据显示图表。
                myChart.setOption(option);
            }
        },
        mounted() {
            this.myEcharts();
        }

   
    })
    
</script>
</html>

3.在activity中的oncreate中调用方法

webViewEchart = (WebView) this.view.findViewById(R.id.wv_Dashboard);
webSettings=webViewEchart.getSettings();
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setAllowFileAccess(true);
webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setAllowContentAccess(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setAppCacheEnabled(true);

webViewEchart.loadUrl("file:///android_asset/web/wwwroot/b.html");

4.在android中的显示效果

5. 目前测试android 7.0 可用,5.0下不显示原因现在不明

测试了一下使用jquery就可以在5.0下显示了

<think> 在uni-app中,特别是在App端(渲染方式为v3),不支持浏览器环境下的DOM操作,因此不能使用`document`对象。 解决思路:使用uni-app提供的节点查询API(`uni.createSelectorQuery()`)来获取DOM节点,然后通过节点的`node`属性(在App端)获取原生节点对象,再传递给ECharts的`init`方法。 但是注意,在uni-app中使用ECharts,通常推荐使用专门的uni-app插件,如`ucharts`或`mpvue-echarts`等,因为它们已经做好了多端兼容。 不过,如果你坚持使用原生的ECharts,那么需要做一些兼容处理。 在App端,我们可以通过`uni.createSelectorQuery()`获取到原生节点,但是这个节点并不是浏览器中的DOM节点,而是一个类似DOM的对象(在App端实际上是原生视图的引用)。 但是,ECharts的`init`方法需要的是一个DOM元素。在uni-app的App端,我们可以通过`plus.webview.currentWebview()`获取到当前Webview窗口对象,然后通过`window.document`来获取document对象。但是这种方式仅适用于App端,且需要确保在Webview环境下。 然而,更推荐的做法是使用uni-app的renderjs技术,因为renderjs运行在视图层,可以直接操作DOM。特别是对于ECharts这样需要操作DOM的库,使用renderjs可以避免逻辑层和视图层通信带来的性能问题,并且可以正常使用DOM API。 下面我将提供两种解决方案: 1. 使用`uni.createSelectorQuery()`获取节点,然后通过节点的`node`属性(在App端)获取原生节点,再传递给ECharts。注意:这种方法在H5和App-V3下都可以,但是需要处理异步问题。 2. 使用renderjs(推荐),在视图层运行ECharts,这样可以直接使用DOM API。 由于问题中提到兼容App,并且不支持document,这里我们主要解决App端的兼容问题。下面分别给出两种方法的示例: 方法一:使用`uni.createSelectorQuery()` 注意:在App端,通过`uni.createSelectorQuery().select('#chart-mobility')`获取节点后,节点的`node`属性是一个原生对象,我们可以将其传递给ECharts。但是,ECharts要求传入的是一个DOM元素,而App端获取的节点并不是标准的DOM元素,所以这种方法在App端可能仍然不可行。因此,更推荐方法二。 方法二:使用renderjs(适用于vue文件) 步骤: a. 在页面中,将需要渲染图表的元素用`<view>`标签定义,并设置id和样式(宽高必须设置)。 b. 在`<script module="echarts" lang="renderjs">`中引入ECharts,并编写初始化图表的函数。 具体代码示例: ```vue <template> <view> <!-- 注意:这里的宽高一定要设置,否则图表无法显示 --> <view id="chart-mobility" style="width: 100%; height: 500rpx;" :prop="option" :change:prop="echarts.updateEcharts"></view> </view> </template> <script> export default { data() { return { option: { // ECharts的配置项 title: { text: '示例图表' }, tooltip: {}, xAxis: { data: ['A', 'B', 'C', 'D', 'E', 'F'] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] } } } } </script> <script module="echarts" lang="renderjs"> // 注意:这里引入ECharts的方式,如果是npm安装,可以import;如果是本地文件,可以使用相对路径 // 由于uni-app的renderjs中不支持直接使用node_modules里的模块,所以建议将echarts.min.js放到static目录下,然后通过相对路径引入(或者使用CDN) import * as echarts from './static/echarts.min.js' // 或者使用CDN链接 export default { mounted() { // 在mounted中初始化图表 // 注意:如果一开始没有数据,可以在change:prop的方法中初始化(如果有数据的话) if (this.option) { this.initEcharts() } }, methods: { // 初始化图表 initEcharts() { const chart = echarts.init(document.getElementById('chart-mobility')) chart.setOption(this.option) // 将chart实例保存到this上,以便后续更新 this.chart = chart // 监听窗口变化,重新调整图表大小 window.addEventListener('resize', () => { this.chart.resize() }) }, // 更新图表(当逻辑层的数据option变化时,会触发这个方法) updateEcharts(newValue, oldValue, ownerInstance, instance) { // 如果图表已经初始化,则更新数据 if (this.chart) { this.chart.setOption(newValue) } else { // 如果还没有初始化,则初始化 this.initEcharts() } } } } </script> ``` 解释: - 在`renderjs`中,我们可以使用标准的DOM API,因此`document.getElementById`可用。 - 逻辑层(第一个`<script>`)中定义的数据`option`,通过`:prop="option"`传递给视图层的`<view>`元素。当`option`变化时,通过`change:prop`事件触发`echarts.updateEcharts`方法(在renderjs模块中定义)。 - 在renderjs模块中,我们在`mounted`生命周期中尝试初始化图表(如果初始有数据的话)。然后在`updateEcharts`方法中处理数据更新。 注意事项: - 引入ECharts库:由于renderjs是在独立的JS运行环境中,我们需要将ECharts库引入到renderjs中。建议将echarts.min.js文件放到static目录下,然后通过相对路径引入(或者使用CDN链接,但要注意网络问题)。 - 性能:renderjs运行在视图层,不会阻塞逻辑层,因此适合处理复杂的DOM操作。 - 兼容性:这种方法在H5和App端都可以使用。 方法二(使用renderjs)是官方推荐的方式,因为它解决了App端无法使用DOM的问题。 因此,我推荐使用方法二。 相关问题: 由于上面的解决方案涉及到uni-app的renderjs技术和ECharts的使用,下面提出一些相关问题: §§相关问题§§: 1. 在uni-app中,renderjs的主要用途是什么?它和普通脚本有什么区别? 2. 除了ECharts,还有哪些图表库可以在uni-app中使用? 3. 在renderjs中如何引入外部JavaScript库? 4. 如何优化在uni-app中使用ECharts时的性能? </think> 在 UniApp 中使用 `document.getElementById` 会报错是因为 UniApp 的多端设计原则:**App 端使用原生渲染而非 Webview**,小程序端也没有 DOM 概念。要兼容 App 和小程序,需使用 UniApp 的 **节点查询 API** 替代 DOM 操作。 ### 解决方案代码(Vue3 示例) ```vue <template> <!-- 必须设置宽高 --> <view id="chart-mobility" ref="chartRef" style="width: 100%; height: 400px;" ></view> </template> <script setup> import { ref, onMounted } from 'vue' import * as echarts from 'echarts' // 需安装 echarts 依赖 const chartRef = ref(null) let chartInstance = null // 初始化图表 const initChart = () => { // 创建节点查询 uni.createSelectorQuery() .select('#chart-mobility') // 或 .select('.chart-class') .node(res => { if(!res || !res.node) { console.error('获取 canvas 节点失败') return } // 获取原生节点 const canvasNode = res.node // 初始化 ECharts(关键步骤) chartInstance = echarts.init(canvasNode) // 设置图表配置 chartInstance.setOption({ title: { text: '移动性分析' }, tooltip: {}, xAxis: { data: ['周一','周二','周三','周四','周五','周六','周日'] }, yAxis: {}, series: [{ name: '活跃度', type: 'bar', data: [120,200,150,80,70,110,130] }] }) // 窗口变化时重绘 uni.onWindowResize(() => chartInstance.resize()) }) .exec() } onMounted(() => { // 兼容 App 渲染延迟 setTimeout(initChart, 50) }) </script> ``` ### 关键点解释: 1. **节点查询替代 DOM** - 使用 `uni.createSelectorQuery().select().node()` 获取原生节点 - `res.node` 返回的是 App 端原生 canvas 节点对象 2. **跨端初始化** - `echarts.init(canvasNode)` 直接使用原生节点初始化 - 兼容 H5/小程序/App 三端: - App:`canvasNode` = Native Canvas - 小程序:`canvasNode` = 小程序 CanvasContext - H5:`canvasNode` = DOM Element 3. **渲染时机** - `setTimeout(initChart, 50)` 解决 App 端渲染延迟问题 - 也可在 `onReady` 生命周期触发 4. **自适应处理** - `uni.onWindowResize` 监听窗口变化 - `chartInstance.resize()` 调整图表尺寸 ### 注意事项: 1. **组件必须设置明确宽高** ```html <!-- 必须指定具体尺寸 --> <view style="width: 300px; height: 200px"></view> ``` 2. **NPM 安装 ECharts** ```bash npm install echarts --save ``` 3. **小程序端需额外配置**(在 `pages.json`): ```json { "usingComponents": { "ec-canvas": "path/to/your/ec-canvas" } } ``` ### 完整跨端处理方案: ```javascript // 封装通用初始化方法 async function safeInitChart(selector) { return new Promise(resolve => { uni.createSelectorQuery() .select(selector) .node(res => { if (!res || !res.node) { console.error('节点获取失败') return resolve(null) } const ctx = res.node const chart = echarts.init(ctx) resolve(chart) }) .exec() }) } // 使用示例 const chart = await safeInitChart('#chart-mobility') chart.setOption({ /* ... */ }) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值